Diciamo che abbiamo 4 servizi, da A a D, che comunicano (per la maggior parte) attraverso una sorta di sistema asincrono basato sugli eventi. Quando una nuova entità viene creata in A, B & C riceve quell'evento. B crea un'entità propria in base a quell'evento e C effettua una chiamata sincrona a D per eseguire un'azione. Infine D riceve l'entità sia di A che di B ed esegue l'azione richiesta da C che richiede le entità di A e B.
Nota: A, B e D sono essenzialmente servizi CRUD che hanno anche API REST, mentre C è logica aziendale e non ha stato. A, B e D sono intesi come servizi indipendenti dal prodotto in un ambiente cloud.
Questo flusso funziona bene quando si tratta di aggiornare entità esistenti in quanto il servizio D memorizza una copia parziale dei dati ricevuti da A e B, ma crea una sorta di condizione di competizione quando A crea una nuova entità. Nota che anche se A e B hanno creato le loro entità prima che C effettui la chiamata, non c'è alcuna garanzia che D abbia letto entrambi gli eventi.
Quali sono i modi più comuni per affrontare questo? Ne ho creati diversi, ma nessuno di loro sembra particolarmente eccezionale.
- Riprova pattern
- Quale entità esegue il tentativo? Poiché questa azione deve essere eseguita alla fine, presumo che averla in servizio D sia una cattiva idea, poiché non può distinguere da input errati tramite l'API REST o richiede funzionalità duplicate per distinguere tra un evento e una chiamata REST.
- Anche se fosse accettabile, spinge la logica aziendale in un servizio CRUD.
- Webhook tra D e B
- Ancora una volta, mette la logica in un servizio CRUD (kinda).
- Thread sleep on C
- Questi ovunque in un servizio in esecuzione in genere sembrano un'idea orribile ...
- Non aiuta con la condizione in cui B si abbassa mentre il resto rimane attivo.
Modifica in risposta alle risposte:
- Avere C aspettare i due eventi prima che invochi D
- Questo purtroppo non garantisce che D abbia letto quegli stessi eventi, anche se è più probabile.
- C non può inviare l'intero contenuto dell'evento da A alla richiesta, solo l'ID dell'oggetto senza duplicare i metodi dell'interfaccia REST su D; gli altri servizi a venire non avranno nulla tranne l'ID quando richiedono il / i servizio / i di D. In tutti gli altri casi, tutte le informazioni necessarie risiederanno in D per eseguire il suo servizio, il caso scomodo sembra essere solo per le nuove entità.
- D aspettare che entrambi creino gli eventi da A e B e poi eseguano la logica senza che C debba dirlo.
- Questo sembra infrangere il principio della responsabilità unica.
- A, B e D sono intesi come servizi "indipendenti dal prodotto", vedi modifica alla nota sopra. L'implicazione è che ciò porterebbe la logica in un servizio utilizzato da più prodotti, anche se la logica è specifica per un solo prodotto.