Quali sono le best practice per la gestione degli errori nelle azioni in più passaggi tra client e server?

Aug 18 2020

Ho un sito Web che carica le offerte di lavoro nella mia API, ci sono diversi passaggi per farlo:

  1. Carica un'immagine del logo nell'archivio file.

  2. Inserisci i dati relativi all'offerta di lavoro in un database.

  3. Elaborare un pagamento con un fornitore di terze parti.

  4. Invia un'e-mail tramite un provider di terze parti.

In generale, puoi immaginare che altri passaggi siano presenti qui in diverse applicazioni, ad esempio ottenere alcune informazioni da un'API di terze parti, convalidare un ReCAPTCHA, aggiornare l'API di indicizzazione di Google, inviare un SMS, ecc. Ecc.

Poiché tutti questi utilizzano terze parti e sono indipendenti dal server che gestisce la chiamata API, ognuno di loro può non riuscire a lasciare alcuni dei passaggi completati con successo e altri no (ad es. Logo aggiornato ma pagamento non riscosso).

La mia domanda è: come vengono generalmente gestiti gli errori in questo tipo di azioni in più passaggi tra client e server nei sistemi di produzione? Esistono standard accettati o best practice?


ho considerato:

  1. Non gestire gli errori e sperare solo che tutto vada a buon fine.

  2. Definire una funzione "annulla" sul back-end per ciascuno dei passaggi e se uno dei passaggi fallisce, quindi chiamarla nei passaggi precedenti. Con azioni costituite da molti passaggi, questo potrebbe trasformarsi in codice spaghetti abbastanza rapidamente e alcuni passaggi non possono essere annullati così facilmente, ad esempio l'invio di un'e-mail.

  3. Creare un endpoint separato sul back-end per ciascuno dei passaggi e consentire al client di chiamarli a turno. Questo potrebbe anche utilizzare un endpoint API "annulla", quindi se il client riceve un errore in uno dei passaggi, può quindi annullare tutti i passaggi precedenti. Ciò ha il vantaggio di consentire al cliente di stimare lo stato di avanzamento dell'azione in fase di completamento, ovvero potrebbe visualizzare all'utente "1 passaggio su 5 completato".

  4. Creare una riga in un DB (o database in memoria?) per ogni azione e quando ogni passaggio è completato contrassegnando la colonna corrispondente come completata. Quando ogni colonna nella riga è completata, invia una risposta all'utente.

Risposte

1 RalfKleberhoff Aug 19 2020 at 13:30

Questo processo in più passaggi è una transazione, che passa da uno stato iniziale coerente ("non è successo niente") a uno stato finale ("annuncio di lavoro eseguito"), con passaggi intermedi che lasciano l'app in uno stato (probabilmente) incoerente.

Non dovresti delegare la gestione della transazione al tuo cliente, in particolare non suddividere il processo in singole chiamate (o forse salterà la fase di pagamento - un male per l'azienda).

Se un passaggio fallisce, è sicuramente una sciocchezza continuare, devi fare una sorta di rollback a uno stato accettabile, non necessariamente lo stato iniziale. Ad esempio, non vedo l'assoluta necessità di rimuovere l'immagine caricata dall'archiviazione dei file.

Innanzitutto, proverei a organizzare i passaggi in modo tale che la maggior parte dei passaggi intermedi siano accettabili, quindi non è necessario eseguire il rollback.

I passaggi difficili sono sicuramente il pagamento e l'e-mail (se ho capito bene la tua attività).

  • Fatturare il cliente senza l'invio delle e-mail è sbagliato (vicino alla frode).
  • Inviare le email senza ricevere il pagamento significa perdere denaro (se questo non accade spesso, potrebbe essere tollerabile). Sicuramente non puoi ripristinare le email, una volta che sono state inviate, ma forse puoi ripristinare i pagamenti (a meno che tu non perda la connessione al provider proprio in quel momento).

Dato che fai affidamento su connessioni esterne, non vedo un modo per evitare assolutamente il completamento parziale della tua transazione, quindi progetterei il processo in modo tale che i fallimenti intermedi

  • altamente improbabile
  • o lasciare uno stato tollerabile.

Quindi, lo farei

  1. Effettua il ping di tutti i servizi esterni per assicurarti che siano attivi e raggiungibili
  2. Carica un'immagine del logo nell'archivio file.
  3. Inserisci i dati relativi all'offerta di lavoro in un database.
  4. Invia un'e-mail tramite un provider di terze parti.
  5. Elaborare un pagamento con un fornitore di terze parti.

La procedura di rollback sarebbe

  • rimuovere l'immagine dall'archivio file,
  • rimuovere l'offerta di lavoro dal database,
  • se l'e-mail è stata inviata, ma il pagamento non è andato a buon fine: pianifica la richiesta di pagamento per un secondo tentativo.
JacquesB Aug 18 2020 at 21:56

"Migliore" ovviamente dipende dai requisiti. Il numero 1 è chiaramente il più semplice da implementare ma le transazioni andranno perse/incomplete in caso di errori. Forse questo è un compromesso accettabile dal punto di vista aziendale?

La soluzione più robusta consiste nel suddividere il processo in una serie di passaggi in cui ogni passaggio è una transazione. Una transazione è completata o fallita e, se fallisce, può essere ritentata in sicurezza. (Ad esempio l'invio di una mail o di un sms sarebbe una transazione.) Una riga del database tiene traccia di quali passaggi sono stati completati.

Non penso che dovresti chiedere al cliente di chiamare ogni passaggio. Ciò creerebbe un accoppiamento stretto e aumenterebbe solo la complessità. Basta che il cliente chiami una singola richiesta con tutti i dati necessari, che avvia il flusso di lavoro. Il client può quindi inviare una richiesta separata e periodica per eseguire il polling dello stato se si desidera mostrare lo stato di avanzamento.

Il supporto per l'annullamento è più complicato e (come osservi) non sempre possibile. Se qualche passaggio può fallire in un modo in cui l'intero processo dovrebbe essere rifiutato (come se una carta di credito non potesse essere valida), allora penso che dovrebbe essere eseguito in una fase di convalida prima che venga avviato il processo in più fasi. Ciò ti consentirà di fornire un feedback sincrono al cliente e di chiedere al cliente di rivedere e reinserire i dati.

AdrianL Aug 27 2020 at 01:00

Come altri hanno già detto, idealmente vuoi raggruppare tutti i pezzi necessari per un annuncio di lavoro di successo e fare in modo che un cliente lo invii al tuo back-end in un'unica richiesta. In quanto sviluppatore di dispositivi mobili, sostengo sempre che i clienti lavorino il meno possibile per preservare l'utilizzo dei dati e la durata della batteria.

Per quanto riguarda il backend, suggerirei di provare a inserire prima le informazioni più importanti in db, quindi provare ad esempio a inserire dati supplementari dopo come un'immagine del logo