Adios
BlogNext.js SaaS

Next.js SaaS

Come eseguire job in background e webhook affidabili in un SaaS Next.js

Progetta job persistenti, webhook verificati, nuovi tentativi, idempotenza, scadenze, stati di errore e lavoro in background osservabile attorno a un SaaS Next.js.

Team di AdiosAggiornato 17 luglio 20268 min di lettura

Una richiesta è poco adatta a lavoro che può durare minuti, dipendere da un provider inaffidabile o dover sopravvivere al riavvio di un processo. Lo stato persistente deve durare oltre la richiesta.

Identifica il lavoro da spostare fuori dalla richiesta

Sposta importazioni, esportazioni, report, elaborazione di contenuti multimediali, email massive, sincronizzazione con provider e altro lavoro lento dietro un confine di job persistente. La richiesta deve validare l'intento, salvare il job e restituire un identificatore utilizzabile dall'interfaccia per mostrare l'avanzamento.

Non tutte le attività asincrone richiedono un servizio separato dal primo giorno. Richiedono però stato persistente, un responsabile, un contratto di esecuzione e un percorso di recupero. Una Promise non attesa in un Route Handler può scomparire al termine del processo senza lasciare un record affidabile per l'utente.

Modella il ciclo di vita del job

Registra ID stabile, tipo, proprietario, riferimento all'input validato, stato, numero di tentativi, prossima esecuzione, riferimento al risultato ed errore sanitizzato. Usa stati come queued, running, succeeded, failed e canceled. Un lease o un heartbeat impedisce a due worker di mantenere senza segnalazioni lo stesso tentativo per sempre.

Conserva payload e output grandi fuori dal record della coda quando opportuno. Il job deve fare riferimento a oggetti persistenti e verificare di nuovo autorizzazione o appartenenza correnti prima di pubblicare il risultato.

type JobState =
  | "queued"
  | "running"
  | "succeeded"
  | "failed"
  | "canceled";

type Job = {
  id: string;
  tenantId: string;
  type: string;
  state: JobState;
  attempts: number;
  runAfter: Date;
};

Rendi idempotente l'esecuzione

Un worker può arrestarsi dopo il successo di un'azione esterna ma prima che il successo venga registrato localmente. Progetta ogni passaggio perché possa essere ripetuto in sicurezza. Usa chiavi di business univoche, chiavi di idempotenza dei provider, upsert e checkpoint registrati, senza presumere che ogni evento venga consegnato una sola volta.

Separa l'identità del job da quella del tentativo. I nuovi tentativi devono condividere lo stesso job di business e registrare evidenze distinte per ogni tentativo. L'interfaccia può così mostrare cosa è successo senza creare più esportazioni o email indistinguibili.

Limita nuovi tentativi e chiamate esterne

Imposta scadenze di connessione e risposta per i provider. Riprova timeout transitori, limiti di frequenza ed errori temporanei con backoff e jitter. Non riprovare indefinitamente input non validi, autorizzazioni revocate o rifiuti permanenti del provider.

Esaurito il numero di tentativi previsto, porta il job in uno stato di errore visibile e genera avvisi secondo la sua importanza. Conserva contesto sufficiente per intervenire senza registrare credenziali o payload privati.

  • —Classifica gli errori prima di riprovare.
  • —Limita il numero di tentativi e il tempo totale trascorso.
  • —Distribuisci i nuovi tentativi nel tempo con jitter.
  • —Offri un nuovo tentativo manuale solo quando l'operazione può essere ripetuta in sicurezza.

Proteggi i webhook in ingresso

Ricevi gli eventi dei provider in un Route Handler, verifica la firma sul corpo originale, rifiuta richieste non valide o obsolete secondo il protocollo del provider e registra l'ID dell'evento prima del lavoro costoso. Restituisci rapidamente successo quando il passaggio persistente del lavoro è completato.

Usa un vincolo di unicità per deduplicare le consegne. Associa l'evento del provider a un tenant o account locale tramite metadati attendibili o ID del provider salvati, non tramite un campo tenant arbitrario nel payload.

Mostra agli utenti progressi veritieri

Un job inviato non è un job completato. Restituisci il suo ID e mostra nell'app lo stato in coda o in esecuzione. Aggiorna tramite navigazione sul server, polling o un canale in tempo reale adatto al prodotto. Rendi visibili errore e annullamento, anziché lasciare uno spinner per sempre.

Proteggi il download dei risultati con gli stessi controlli di appartenenza della richiesta iniziale. Fai scadere i file generati quando opportuno e separa le spiegazioni per gli utenti dai dettagli interni degli errori.

Verifica interruzione e consegna duplicata

Ferma un worker a metà passaggio, riavvialo, consegna due volte lo stesso webhook, ritarda un provider oltre il timeout, esaurisci i tentativi e rimuovi l'accesso di un utente prima del completamento. Conferma che l'operazione rimanga sicura e lo stato finale comprensibile.

Verifica la distribuzione mentre i job sono in esecuzione. I worker devono completare, rilasciare o riprovare in sicurezza il lavoro assegnato con lease, secondo il progetto. Le migrazioni dello schema devono rimanere compatibili con i job in coda creati dal rilascio precedente.

Gestisci job e workflow accanto all'app

Adios può eseguire processi applicativi persistenti e workflow ispezionabili con trigger, passaggi, attese, approvazioni e cronologia delle esecuzioni. Mantieni il percorso della richiesta Next.js concentrato su validazione e passaggio persistente del lavoro, poi lascia al worker o al workflow l'esecuzione con nuovi tentativi.

Distribuisci configurazione e riferimenti ai segreti accanto al sorgente, esamina separatamente i log dell'applicazione e dei workflow e usa verifiche dello stato per i servizi che ricevono traffico. Così il rilascio rivolto ai clienti rimane stabile, mentre i guasti in background conservano evidenze e percorso di recupero propri.

env:
  DATABASE_URL: secret://DATABASE_URL
  EMAIL_API_KEY: secret://EMAIL_API_KEY

runtime:
  name: node@24
  port: 3000
  health_path: /api/health
Tutti gli articoli