/** * @fileoverview Entity-agnostic per-key serial task queue. The lowest-layer primitive behind the * fire-and-forget save pattern: tasks enqueued under the same key run strictly in order (the next * cannot start until the prior settles), tasks under different keys run concurrently, and failures * are captured for a later `flush()` rather than propagated outward. MJGlobal cannot reference * `BaseEntity`, so this knows nothing about entities — see `BaseEntitySaveQueue` for the entity façade. * * Self-bounding: only *in-flight* tasks are retained (they drop out as they settle), and failures are * tallied into counters — so a long-lived queue that never flushes does not grow without bound. * @module @memberjunction/global */ /** Aggregate outcome of a {@link KeyedSerialTaskQueue.flush}. */ export interface SerialTaskFlushResult { /** Tasks that rejected (threw) OR resolved a falsy "not ok" value, since the last flush. */ failures: number; /** Tasks that rejected (threw), since the last flush. */ rejections: number; } /** * A per-key serial task chain. Tasks for the **same key** (compared by object identity) run one at a * time in enqueue order; tasks for **different keys** run concurrently. Enqueuing is fire-and-forget — * the returned promise never rejects, and failures are tallied for {@link flush}. * * This is what makes "mutate after the prior task lands" structural: a task enqueued after another on * the same key physically cannot begin until the prior one resolves. */ export declare class KeyedSerialTaskQueue { /** Latest tail promise per key (object identity) — never rejects, so the chain can't break. */ private tails; /** Currently-running tasks (each removes itself on settle), for `flush()` to await. */ private inFlight; /** Failures/rejections since the last flush (counters, not a growing list — keeps memory bounded). */ private failures; private rejections; private readonly onError?; constructor(opts?: { onError?: (err: unknown, label?: string) => void; }); /** * Enqueues `task` to run after all prior tasks for `key` have settled. Fire-and-forget: returns * the task's result promise, but the caller need not await it — it resolves to the task's value on * success or `undefined` on failure, and **never rejects**. Failures (a thrown error, or a resolved * value `opts.isOk` deems falsy) are counted for {@link flush} and routed to `onError`. * * @param key Serialization key (object identity). Same key → serialized; different keys → concurrent. * @param task The work to run. * @param opts.label Diagnostic label passed to `onError`. * @param opts.isOk Treats a resolved value as a failure when it returns false (e.g. `Save()` → `false`). * @param opts.after Optional dependency key — the task waits for this key's latest task to settle * before running, in addition to waiting for its own key's prior tasks. Use this to honour * cross-instance ordering constraints like self-referencing foreign keys (e.g. a child step's * INSERT must land after its parent step's INSERT). */ enqueue(key: object, task: () => Promise, opts?: { label?: string; isOk?: (v: T) => boolean; after?: object; }): Promise; /** * Awaits the currently in-flight tasks, then reports and resets the failure tally accumulated since * the last flush. Tasks enqueued after this call begins are not awaited here. */ flush(): Promise; } //# sourceMappingURL=KeyedSerialTaskQueue.d.ts.map