Quello che sto per descrivere è essenzialmente un problema di commit in due fasi tra due sistemi diversi e sto cercando consigli su come gestirlo. Nella nostra applicazione web, scarichiamo alcune costose operazioni di terze parti, come l'invio di e-mail, a processi out-of-band in background (la chiamiamo infrastruttura di lavoro)Impegno a due fasi - Come utilizzare la mia coda in modo efficace?
Per inviare un'email, ad esempio, creiamo sia un oggetto email che un lavoro di posta elettronica nel nostro database. Dovremo quindi attendere che il nostro monitor del lavoro prelevi il lavoro di posta elettronica e lo invii. Il monitoraggio del lavoro funziona essenzialmente eseguendo il polling del database ogni pochi secondi quando è inattivo.
Questo, tuttavia, aggiunge un ritardo nell'invio di e-mail e aggiunge quello che vedo come carico indebito sul database con il polling. Sarebbe molto più bello se potessimo mettere immediatamente il lavoro di posta elettronica in coda non appena verrà creata l'email.
Tuttavia, ciò non riesce attualmente per due motivi. Innanzitutto, la coda è spesso molto più veloce della richiesta web. L'e-mail viene prelevata per l'elaborazione prima che la richiesta Web abbia impegnato la sua transazione di database, quindi non può generare correttamente l'e-mail. In secondo luogo, se la richiesta web non riesce, ripristina la transazione del database, il che significa che l'email deve essere non inviata. Tuttavia, se è già stato messo in coda, non è più nel controllo della richiesta.
Esiste una buona strategia per la creazione di un commit a due fasi tra la coda e il database? Per riferimento, stiamo usando RabbitMQ e MySQL con le tabelle InnoDB. Un'idea che avevo in testa era di incollare i lavori di posta elettronica in coda dopo che la transazione del database è stata commessa, ma ciò lascia la possibilità che l'e-mail non venga mai messa in coda. Dovrò ancora creare un processo di polling per le e-mail che avrebbero dovuto essere inviate e non lo erano.