Callbackurile de trimitere după commit lasă de decis recuperarea
Rails a mutat callbackurile de trimitere după commit când amânarea este activă. Stabiliți recuperarea pentru date salvate al căror job nu ajunge în coadă.
Mutarea unui callback de trimitere după commit îl așază în jurul interacțiunii cu coada pe care trebuie să o observe. Nu transformă însă confirmarea tranzacției în baza de date și scrierea într-o coadă externă într-o singură operație indivizibilă. Aplicațiile trebuie în continuare să decidă ce se întâmplă când datele sunt confirmate, dar jobul nu poate fi livrat. Recuperarea potrivită depinde de consecința pierderii acelui job.
Această retrospectivă din noiembrie 2026 privește raportul Rails din 9 mai 2025 și modificarea integrată la 5 mai. Raportul evidențiază amânarea callbackurilor around_enqueue când enqueue_after_transaction_commit este activat. Sunt datele integrării și ale anunțului săptămânal, nu dovada că toate versiunile Rails aveau acel comportament în săptămâna cercetată.
Funcția trebuie să înconjoare încercarea reală
Cererea de integrare descrie cum un contributor folosea around_enqueue pentru a intercepta erorile de conectivitate Sidekiq și a salva în baza de date conținutul nelivrat, pentru o posibilă recuperare manuală. Este relatarea contributorului, nu o implementare AL+. Problema raportată era că funcțiile callback rulau la apelarea perform_later, deși interacțiunea cu adaptorul putea avea loc ulterior, după commit.
O funcție încheiată înaintea acelei interacțiuni ulterioare nu poate intercepta o excepție apărută după încheierea sa. Schimbarea momentului contează deci chiar dacă jobul era deja amânat. Afirmațiile „trimiterea are loc după commit” și „callbackul înconjoară încercarea efectivă” exprimă relații diferite. Modificarea rezolvă a doua relație când setarea este activată.
Modulul integrat pentru amânare înregistrează activitatea prin ActiveRecord.after_all_transactions_commit. Implementarea corespunzătoare a trimiterii execută callbackurile în jurul apelului intern către adaptor. Citiți fișierele împreună: explică felul în care traseul amânat ajunge ulterior la callbackuri. Rezumatul săptămânal nu trebuie tratat drept descriere completă a interfeței.
Setarea este o condiție a discuției. Nu generalizați comportamentul la joburile configurate pentru trimitere imediată. Și un callback obișnuit de execuție a jobului are alt ciclu de viață decât unul de trimitere. Un executant poate prelucra doar jobul pe care îl primește; recuperarea unui conținut care nu a intrat niciodată în coadă trebuie să înceapă în altă parte.
Commitul separă două feluri de reușită
Considerați un flux ipotetic de comenzi. O tranzacție înregistrează o comandă acceptată și solicită un job care să anunțe alt sistem. După confirmarea tranzacției, adaptorul încearcă să trimită jobul. Dacă încercarea eșuează, comanda poate rămâne stocată valid, în timp ce notificarea lipsește. Amânarea încercării evită dependența de date neconfirmate, dar lasă posibil acest eșec ulterior.
Codul care gestionează cererea trebuie să înțeleagă și semnificația valorii returnate imediat. În implementarea integrată, traseul amânat poate returna o instanță a jobului înainte ca adaptorul să își încheie încercarea ulterioară. Instanța nu poate fi interpretată drept confirmare durabilă de primire din partea cozii externe. Programarea unei încercări viitoare și predarea reușită a conținutului sunt observații separate.
Un callback care interceptează o eroare de conexiune și scrie o înregistrare pentru recuperare poate acoperi un traseu util de eșec. Nu acoperă toate opririle posibile ale procesului. Dacă procesul dispare după commit, dar înainte de scrierea înregistrării de recuperare, nu este garantată existența nici a jobului, nici a înregistrării. Schimbarea momentului nu poate închide singură această fereastră.
Rezultatul unei încercări de trimitere poate fi și incert, nu doar un eșec clar. Conexiunea se poate întrerupe după ce serviciul extern a acceptat solicitarea, dar înainte ca aplicația să vadă confirmarea. O nouă încercare riscă atunci să dubleze activitatea. Aplicația are nevoie de o politică pentru identificarea operației de afaceri și tolerarea sau prevenirea efectelor duplicate; poziția callbackului nu creează livrare exact o dată.
O înregistrare de recuperare are nevoie și de informații suficiente pentru a distinge o operație netrimisă de una deja încheiată. Păstrarea doar a mesajului excepției poate ajuta diagnosticul fără să facă sigură reluarea. Decideți ce identifică operația și cum îi verifică responsabilul starea înainte de altă încercare. Aceasta este responsabilitatea aplicației, dincolo de schimbarea momentului callbackului.
Intenția durabilă are un cost de operare
Pentru o operație cu consecințe, un outbox este o soluție posibilă: salvați intenția de a trimite activitatea împreună cu modificarea de afaceri, în aceeași tranzacție, apoi un proces separat livrează intențiile în așteptare. Este o arhitectură propusă. Schimbarea Rails nu adaugă automat un asemenea tabel sau proces, iar articolul nu pretinde o implementare ori un experiment.
Soluția mută întrebarea de la păstrarea intenției la capacitatea procesului de livrare de a progresa. Înregistrările în așteptare trebuie urmărite, reîncercările cer o politică, iar livrarea duplicată trebuie încă tratată. Echipa trebuie să decidă și ce se întâmplă când o înregistrare nu poate fi livrată niciodată. Durabilitatea este utilă doar dacă activitatea blocată devine vizibilă unei persoane responsabile.
Cel mai puternic contraargument este un job cu miză mică, care poate fi reconstruit. O actualizare periodică sau o notificare opțională poate să nu justifice datele și obligațiile de operare suplimentare ale unui outbox. Un proces documentat de reîncercare sau reconciliere poate fi suficient dacă afacerea îi acceptă limitele. Cerința este o alegere explicită despre pierdere, întârziere și duplicate, nu o arhitectură universală.
Într-un proiect de dezvoltare software la comandă, urmăriți un job cu consecințe de la înregistrarea confirmată la primirea în coadă și apoi la efectul său. Numiți responsabilul recuperării pentru fiecare interval neacoperit. Păstrați îmbunătățirea callbackului pentru problema de ciclu de viață pe care o rezolvă și tratați intenția durabilă ca pe o decizie separată, cu un cost proporțional cu obligația față de client.
Paul