mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-30 21:45:13 +02:00
32 lines
1.1 KiB
JavaScript
32 lines
1.1 KiB
JavaScript
// Shared idempotency helper for money-moving entry points. Any operation that
|
|
// must not happen twice derives a stable key (from the caller's idempotencyKey
|
|
// or from the request payload) and routes through once().
|
|
import crypto from 'node:crypto';
|
|
|
|
const inflight = new Map();
|
|
|
|
export function deriveKey(scope, parts) {
|
|
const hash = crypto.createHash('sha256').update(JSON.stringify(parts)).digest('hex').slice(0, 24);
|
|
return `${scope}:${hash}`;
|
|
}
|
|
|
|
// Runs produce() at most once per key. The key is claimed synchronously, so
|
|
// concurrent callers share one execution, and the receipt is persisted, so a
|
|
// retry after a restart returns the stored receipt instead of re-running.
|
|
export async function once(store, key, produce) {
|
|
const existing = store.get(key);
|
|
if (existing) return { ...existing, duplicate: true };
|
|
if (inflight.has(key)) return { ...(await inflight.get(key)), duplicate: true };
|
|
const pending = (async () => {
|
|
const receipt = await produce();
|
|
store.set(key, receipt);
|
|
return receipt;
|
|
})();
|
|
inflight.set(key, pending);
|
|
try {
|
|
return await pending;
|
|
} finally {
|
|
inflight.delete(key);
|
|
}
|
|
}
|