Operare în producție
Idempotency, retry și sincronizare
Cum păstrezi o integrare corectă când apar timeouturi, concurență sau răspunsuri întârziate.
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
| Semnal | Acțiune recomandată |
|---|---|
| 400 / validare | Corectează requestul. Nu relua automat același payload invalid. |
| 401 / 403 | Verifică cheia, mediul și permisiunile. Nu folosi credențialele altui comerciant. |
| 404 | Verifică identificatorul și instalarea; nu presupune că resursa există în alt mediu. |
| 409 / conflict | Recitește resursa și versiunea; rezolvă conflictul înainte de retry. |
| 429 | Respectă Retry-After când există; aplică backoff și jitter. |
| 5xx / rețea / timeout | Retry 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ă.
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.
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);
});
}