-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasync-store.ts
More file actions
109 lines (104 loc) · 4.47 KB
/
async-store.ts
File metadata and controls
109 lines (104 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import type {
AppendContextSnapshotOptions,
CancelRunOptions,
ClaimTaskOptions,
ClaimTaskResult,
CompleteTaskOptions,
ContextSnapshotRecord,
CreateRunOptions,
EnqueueTaskOptions,
EventRecord,
ExpireLeaseResult,
FailTaskOptions,
HeartbeatLeaseOptions,
ListEventsResult,
ListEventsSinceOptions,
ListPendingTasksOptions,
ListRunsOptions,
PauseTaskOptions,
PruneRunsOptions,
PruneRunsResult,
ReleaseTaskOptions,
ResumeTaskOptions,
RunRecord,
TaskLeaseRecord,
TaskRecord,
ListDeadTasksOptions,
RequeueDeadTaskOptions,
} from './types.js'
/**
* Observer callback for every durable event an async store writes. See
* `AsyncParallelMcpStore.addEventListener`.
*/
export type AsyncParallelMcpEventListener = (event: EventRecord) => void | Promise<void>
/**
* Contract every **async** adapter (Postgres, MySQL, Redis-backed, …) must
* satisfy in order to plug into
* {@link import('./async-orchestrator.js').AsyncParallelMcpOrchestrator}.
*
* This is the structural twin of {@link import('./store.js').ParallelMcpStore}
* but every method returns a `Promise`. Semantic guarantees are identical:
*
* - Typed errors are the same (`LeaseConflictError`, `LeaseExpiredError`,
* `RunTerminalError`, `DependencyCycleError`, `InvalidTransitionError`,
* `DuplicateTaskKeyError`, `RecordNotFoundError`).
* - `claimNextTask` must be atomic across writers.
* - `addEventListener` returns a detach function. Listener errors are
* swallowed so observability cannot break writes.
* - `transaction` runs `fn` inside one atomic unit; adapters that cannot
* offer real transactions (e.g. a naive Redis backend) should document
* that explicitly and reject with a clear error instead of silently
* interleaving writes.
*
* Authoring an async adapter?
* - Run `@razroo/parallel-mcp-testkit`'s `runAsyncConformanceSuite`.
* - Use `toAsyncStore(syncStore)` in tests that do not yet need real I/O.
*/
export interface AsyncParallelMcpStore {
/** Register an observer. Returns a detach function. */
addEventListener(listener: AsyncParallelMcpEventListener): () => void
/**
* Close the backing connection / pool. Idempotent. After `close()`, any
* further method call must reject.
*/
close(): Promise<void>
/**
* Run `fn` inside one atomic transaction. Every durable write performed
* inside commits or rolls back as one unit.
*/
transaction<T>(fn: () => Promise<T>): Promise<T>
createRun(options: CreateRunOptions): Promise<RunRecord>
enqueueTask(options: EnqueueTaskOptions): Promise<TaskRecord>
claimNextTask(options: ClaimTaskOptions): Promise<ClaimTaskResult | null>
heartbeatLease(options: HeartbeatLeaseOptions): Promise<TaskLeaseRecord>
markTaskRunning(options: Omit<PauseTaskOptions, 'status' | 'reason'>): Promise<TaskRecord>
pauseTask(options: PauseTaskOptions): Promise<TaskRecord>
resumeTask(options: ResumeTaskOptions): Promise<TaskRecord>
completeTask(options: CompleteTaskOptions): Promise<TaskRecord>
failTask(options: FailTaskOptions): Promise<TaskRecord>
releaseTask(options: ReleaseTaskOptions): Promise<TaskRecord>
appendContextSnapshot(options: AppendContextSnapshotOptions): Promise<ContextSnapshotRecord>
cancelRun(options: CancelRunOptions): Promise<RunRecord>
expireLeases(options?: { now?: Date | string | number | undefined }): Promise<ExpireLeaseResult>
getRun(runId: string): Promise<RunRecord | null>
getTask(taskId: string): Promise<TaskRecord | null>
getCurrentContextSnapshot(runId: string): Promise<ContextSnapshotRecord | null>
listRunTasks(runId: string): Promise<TaskRecord[]>
listRunEvents(runId: string): Promise<EventRecord[]>
listRuns(options?: ListRunsOptions): Promise<RunRecord[]>
listPendingTasks(options?: ListPendingTasksOptions): Promise<TaskRecord[]>
listEventsSince(options?: ListEventsSinceOptions): Promise<ListEventsResult>
pruneRuns(options: PruneRunsOptions): Promise<PruneRunsResult>
/**
* List tasks currently parked in the dead-letter queue. A task enters the
* DLQ when `maxAttempts` has been exhausted; its last `error` is
* preserved on the {@link TaskRecord} for operator triage.
*/
listDeadTasks(options?: ListDeadTasksOptions): Promise<TaskRecord[]>
/**
* Requeue a task that exhausted its retry budget. Resets `attemptCount`
* to `0` (unless `resetAttempts: false`), clears `error`, and returns the
* task to `queued` so a future `claimNextTask` can pick it up.
*/
requeueDeadTask(options: RequeueDeadTaskOptions): Promise<TaskRecord>
}