Mergi la conținut

Operare în producție

Idempotency, retry și sincronizare

Cum păstrezi o integrare corectă când apar timeouturi, concurență sau răspunsuri întârziate.

Exemple server-side cu SDK-urile oficiale Monedo. Înlocuiește identificatorii și configurația cu resursele propriei instalări. Datele din exemple nu sunt tranzacții reale.

O operație logică, o cheie stabilă

Generează cheia când creezi operația în sistemul tău și persist-o înainte de request. Reutilizează aceeași cheie numai cu aceiași parametri. Nu genera un UUID nou pentru fiecare retry și nu include timestampul curent în payloadul reluat. Dacă utilizatorul schimbă suma sau contractul, creează o revizie explicită a operației. Un timeout lasă rezultatul necunoscut; nu înseamnă că serverul a anulat încasarea.

Politica de reluare

SemnalAcțiune recomandată
400 / validareCorectează requestul. Nu relua automat același payload invalid.
401 / 403Verifică cheia, mediul și permisiunile. Nu folosi credențialele altui comerciant.
404Verifică identificatorul și instalarea; nu presupune că resursa există în alt mediu.
409 / conflictRecitește resursa și versiunea; rezolvă conflictul înainte de retry.
429Respectă Retry-After când există; aplică backoff și jitter.
5xx / rețea / timeoutRetry limitat cu idempotency pentru scrieri; citește starea resursei cunoscute.

Urmărește operațiile asincrone

Un request poate întoarce o operație durabilă în locul rezultatului financiar final. Salvează operation.id și consultă operations.retrieve sau waitForOperation. succeeded confirmă terminarea operației; dead_letter și cancelled cer tratare explicită. Expirarea timpului de așteptare al SDK-ului nu anulează operația remote. Pentru polling folosește intervale limitate și backoff, nu bucle fără pauză.

javascript
try {
  const operation = await monedo.waitForOperation(operationId);
  await operationStore.markCompleted(operation.id);
} catch (error) {
  // Preserve operationId for polling or manual investigation.
  // A local timeout must not trigger a second transfer.
  await operationStore.recordFailure(operationId, {
    code: error.code, requestId: error.requestId
  });
  throw error;
}

Parcurge toate paginile și salvează cursorul

Cursorul este opac. Nu îl decoda și nu îl înlocui cu un offset. Păstrează filtrele identice pe durata parcurgerii, procesează pagina și abia apoi avansează cursorul. paginate din Payments produce pagini, nu obiecte individuale. Helpers pages din Commerce și Fiscal urmează același principiu. Pentru sincronizare incrementală, persistă checkpointul numai după commitul local și deduplică elementele repetate în ferestrele de suprapunere.

javascript
for await (const page of monedo.paginate('/v1/subscriptions', { limit: 100 })) {
  await database.transaction(async (tx) => {
    await tx.subscriptions.upsertMany(page.data);
    await tx.sync.saveCursor(page.next_cursor);
  });
}