@lostgradient/weft 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli/generated/operation-catalog.snapshot.json +1334 -0
- package/dist/cli/generated/operation-client.generated.d.ts +9 -2
- package/dist/cli/generated/operation-client.generated.js +2 -0
- package/dist/core/engine/activity-reconciliation.d.ts +2 -2
- package/dist/core/engine/activity-reconciliation.js +12 -8
- package/dist/core/engine/async-activity-completion.js +12 -4
- package/dist/core/engine/async-activity-records.d.ts +11 -1
- package/dist/core/engine/async-activity-records.js +4 -3
- package/dist/core/engine/attributes-tags.d.ts +11 -1
- package/dist/core/engine/attributes-tags.js +4 -3
- package/dist/core/engine/bulk-operations-purge.js +5 -2
- package/dist/core/engine/bulk-operations.js +17 -5
- package/dist/core/engine/callback-creators-bundles.js +1 -1
- package/dist/core/engine/callback-creators-core.js +4 -2
- package/dist/core/engine/checkpoint-io.js +1 -1
- package/dist/core/engine/child-workflow.js +2 -1
- package/dist/core/engine/completed-review-storage.js +1 -1
- package/dist/core/engine/condition-waiters.d.ts +45 -3
- package/dist/core/engine/condition-waiters.js +12 -3
- package/dist/core/engine/disposal.js +6 -0
- package/dist/core/engine/engine-internal-types.d.ts +12 -4
- package/dist/core/engine/fenced-write.d.ts +46 -15
- package/dist/core/engine/fenced-write.js +39 -6
- package/dist/core/engine/finalizer-state.d.ts +3 -1
- package/dist/core/engine/handle-result.d.ts +49 -1
- package/dist/core/engine/handle-result.js +95 -20
- package/dist/core/engine/index.d.ts +13 -5
- package/dist/core/engine/index.js +155 -5
- package/dist/core/engine/inline-launch-queue.js +9 -0
- package/dist/core/engine/internals.d.ts +73 -0
- package/dist/core/engine/invoke-update-handler.d.ts +19 -0
- package/dist/core/engine/invoke-update-handler.js +7 -0
- package/dist/core/engine/lease-deposition.d.ts +132 -0
- package/dist/core/engine/lease-deposition.js +31 -0
- package/dist/core/engine/lease-errors.d.ts +80 -9
- package/dist/core/engine/lease-errors.js +28 -2
- package/dist/core/engine/lifecycle/resume.js +3 -1
- package/dist/core/engine/lifecycle/standalone-claim-acquire.d.ts +33 -0
- package/dist/core/engine/lifecycle/standalone-claim-acquire.js +25 -0
- package/dist/core/engine/lifecycle/start-commit.js +20 -6
- package/dist/core/engine/lifecycle/transition.d.ts +15 -1
- package/dist/core/engine/lifecycle/transition.js +6 -3
- package/dist/core/engine/operations-activity.js +1 -1
- package/dist/core/engine/operations-time.js +21 -7
- package/dist/core/engine/owner-side-signal-poll.d.ts +132 -0
- package/dist/core/engine/owner-side-signal-poll.js +22 -0
- package/dist/core/engine/owner-side-update-poll.d.ts +116 -0
- package/dist/core/engine/owner-side-update-poll.js +22 -0
- package/dist/core/engine/ownership-bootstrap.d.ts +280 -0
- package/dist/core/engine/ownership-bootstrap.js +89 -0
- package/dist/core/engine/ownership-mode-marker.d.ts +82 -0
- package/dist/core/engine/ownership-mode-marker.js +52 -0
- package/dist/core/engine/ownership-options.d.ts +22 -6
- package/dist/core/engine/ownership-options.js +42 -12
- package/dist/core/engine/pending-updates.js +35 -24
- package/dist/core/engine/queries.d.ts +70 -0
- package/dist/core/engine/queries.js +58 -4
- package/dist/core/engine/schedules.js +1 -1
- package/dist/core/engine/signals.d.ts +11 -1
- package/dist/core/engine/signals.js +11 -7
- package/dist/core/engine/sleep-timer-acknowledgements.d.ts +68 -0
- package/dist/core/engine/sleep-timer-acknowledgements.js +19 -0
- package/dist/core/engine/storage-io.d.ts +58 -10
- package/dist/core/engine/storage-io.js +27 -9
- package/dist/core/engine/termination/cleanup.d.ts +5 -4
- package/dist/core/engine/termination/complete.js +23 -4
- package/dist/core/engine/termination/finalizer-claim.js +4 -4
- package/dist/core/engine/termination/state-commit-callbacks.d.ts +15 -0
- package/dist/core/engine/termination/state-commit-callbacks.js +0 -0
- package/dist/core/engine/termination/suspend.js +1 -1
- package/dist/core/engine/update-validation.d.ts +28 -0
- package/dist/core/engine/update-validation.js +37 -0
- package/dist/core/engine/updates.d.ts +17 -16
- package/dist/core/engine/updates.js +24 -47
- package/dist/core/engine/wake-ownership-check.d.ts +86 -0
- package/dist/core/engine/wake-ownership-check.js +19 -0
- package/dist/core/engine/wake-ownership-guard.d.ts +46 -0
- package/dist/core/engine/wake-ownership-guard.js +23 -0
- package/dist/core/engine/workflow-claim-codec.d.ts +64 -0
- package/dist/core/engine/workflow-claim-codec.js +44 -0
- package/dist/core/engine/workflow-claim-cooldown.d.ts +60 -0
- package/dist/core/engine/workflow-claim-cooldown.js +17 -0
- package/dist/core/engine/workflow-claim-fold.d.ts +82 -0
- package/dist/core/engine/workflow-claim-fold.js +53 -0
- package/dist/core/engine/workflow-claim-metrics.d.ts +131 -0
- package/dist/core/engine/workflow-claim-metrics.js +62 -0
- package/dist/core/engine/workflow-claim-reclaim-scan.d.ts +96 -0
- package/dist/core/engine/workflow-claim-reclaim-scan.js +66 -0
- package/dist/core/engine/workflow-claim-reclaim-target.d.ts +107 -0
- package/dist/core/engine/workflow-claim-reclaim-target.js +155 -0
- package/dist/core/engine/workflow-claim-registry.d.ts +227 -0
- package/dist/core/engine/workflow-claim-registry.js +198 -0
- package/dist/core/engine/workflow-claim-renewal-interval.d.ts +50 -0
- package/dist/core/engine/workflow-claim-renewal-interval.js +132 -0
- package/dist/core/engine/workflow-claim-renewal-subpasses.d.ts +265 -0
- package/dist/core/engine/workflow-claim-renewal-subpasses.js +104 -0
- package/dist/core/engine/workflow-claim-renewal-task.d.ts +159 -0
- package/dist/core/engine/workflow-claim-renewal-task.js +65 -0
- package/dist/core/engine/workflow-claim-transitions.d.ts +186 -0
- package/dist/core/engine/workflow-claim-transitions.js +120 -0
- package/dist/core/inline-execution-strategy.d.ts +20 -0
- package/dist/core/inline-execution-strategy.js +15 -4
- package/dist/core/scheduler/scheduler-class.js +3 -3
- package/dist/core/scheduler/timer-sources.d.ts +13 -0
- package/dist/core/scheduler/timer-sources.js +1 -1
- package/dist/core/types/options.d.ts +17 -1
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +2 -1
- package/dist/http.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +8 -0
- package/dist/indexeddb.js +1 -1
- package/dist/json-schema.js +3 -3
- package/dist/observability/index.js +2 -2
- package/dist/server/operations/get-task-detail-schema.d.ts +341 -0
- package/dist/server/operations/get-task-detail-schema.js +118 -0
- package/dist/server/operations/get-task-detail.d.ts +346 -0
- package/dist/server/operations/get-task-detail.js +215 -0
- package/dist/server/operations/static-registrations.js +3 -0
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +113 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/index.d.ts +38 -35
- package/dist/storage/interface.d.ts +87 -125
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-encoding.d.ts +51 -0
- package/dist/storage/key-encoding.js +13 -0
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +3 -0
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +2 -2
- package/dist/storage/node-sqlite.js +113 -0
- package/dist/storage/ownership-keys.d.ts +55 -0
- package/dist/storage/ownership-keys.js +6 -0
- package/dist/storage/postgres.js +2 -2
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -1
- package/dist/worker/protocol.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure, storage-agnostic builders for the `wf-owner-epoch:<id>` /
|
|
3
|
+
* `wf-owner-holder:<id>` compare-and-swap fragments described in
|
|
4
|
+
* [ADR 0002 § Ownership transitions](../../../documentation/contributing/architecture-decisions/0002-multiengine-per-workflow-ownership.md#ownership-transitions).
|
|
5
|
+
*
|
|
6
|
+
* Every function here returns a `{ conditions, operations }` fragment meant to
|
|
7
|
+
* be passed straight to {@link storageConditionalBatch}, or folded into a
|
|
8
|
+
* larger batch alongside an enabling write (a start, a delayed-start fire, a
|
|
9
|
+
* terminal-state commit). None of them perform IO, read a clock, or import
|
|
10
|
+
* `EngineInternals` — `now` and every previously-read byte value are supplied
|
|
11
|
+
* by the caller, which is what makes every CAS branch here exhaustively
|
|
12
|
+
* unit-testable without a real `Storage` or a live claim manager (a later
|
|
13
|
+
* stage). This mirrors why `lease-codec.ts` was split out of
|
|
14
|
+
* `lease-manager.ts`: the transition math has no engine state of its own.
|
|
15
|
+
*
|
|
16
|
+
* **Why raw bytes, not re-encoded values, for every condition.** A
|
|
17
|
+
* `conditionalBatch` precondition compares the whole stored value as bytes.
|
|
18
|
+
* Re-deriving expected bytes from a decoded value (`encode(decode(raw))`)
|
|
19
|
+
* only round-trips by luck — a storage adapter's byte-level transport (e.g. a
|
|
20
|
+
* `BYTEA` column) or an older writer's differently-ordered JSON keys can be
|
|
21
|
+
* logically equal but byte-different, which would spuriously fail a CAS that
|
|
22
|
+
* should have succeeded. Every builder below therefore takes the exact bytes
|
|
23
|
+
* the caller most recently read or wrote, never a value reconstructed from a
|
|
24
|
+
* decoded record. See `lease-manager.ts`'s `readState`/`takeOwnership` for the
|
|
25
|
+
* same discipline applied to the global lease.
|
|
26
|
+
*
|
|
27
|
+
* @module core/engine/workflow-claim-transitions
|
|
28
|
+
*/
|
|
29
|
+
import type { BatchOperation, ConditionalBatchCondition } from '../../storage/interface.ts';
|
|
30
|
+
/**
|
|
31
|
+
* `workflowClaimTtl` must be at least this many multiples of
|
|
32
|
+
* `workflowClaimRenewInterval`, enforced at `Engine` construction. Proposed
|
|
33
|
+
* default per ADR 0002; not yet a fixed final value (see the ADR's Open
|
|
34
|
+
* questions), but exported here so callers reference the constant rather than
|
|
35
|
+
* a repeated literal.
|
|
36
|
+
*/
|
|
37
|
+
export declare const WORKFLOW_CLAIM_TTL_SAFETY_MULTIPLIER = 3;
|
|
38
|
+
/**
|
|
39
|
+
* Grace multiplier applied to `workflowClaimRenewInterval` and added to a
|
|
40
|
+
* holder's `expiresAt` before the `expire` judgment considers it stale. This
|
|
41
|
+
* dampens clock-skew-driven false-expiry judgments. Proposed default per ADR
|
|
42
|
+
* 0002 (see the ADR's Open questions for the not-yet-fixed final value).
|
|
43
|
+
*/
|
|
44
|
+
export declare const WORKFLOW_CLAIM_TAKEOVER_GRACE_MULTIPLIER = 2;
|
|
45
|
+
/** A `{ conditions, operations }` fragment for `storageConditionalBatch`. */
|
|
46
|
+
export type WorkflowClaimTransitionFragment = {
|
|
47
|
+
conditions: ConditionalBatchCondition[];
|
|
48
|
+
operations: BatchOperation[];
|
|
49
|
+
};
|
|
50
|
+
/** Input to {@link buildWorkflowClaimAcquireTransition}. */
|
|
51
|
+
export type WorkflowClaimAcquireInput = {
|
|
52
|
+
workflowId: string;
|
|
53
|
+
/** This engine's identity, minted once per process. */
|
|
54
|
+
engineId: string;
|
|
55
|
+
now: number;
|
|
56
|
+
claimTtlMs: number;
|
|
57
|
+
/**
|
|
58
|
+
* The exact bytes last read for `wf-owner-epoch:<workflowId>`, or `null`
|
|
59
|
+
* when genuinely never written. `acquire` always reads this key first — it
|
|
60
|
+
* never assumes absence — so a never-seen id observes `null` and mints
|
|
61
|
+
* epoch `1`, while a reused id (e.g. after release, or `start-new` reusing
|
|
62
|
+
* a purged id) observes its true prior epoch and mints one past it. This is
|
|
63
|
+
* the ABA-safety property: the epoch counter is never reset, so a stale
|
|
64
|
+
* zombie's cached epoch from an earlier generation can never coincide with
|
|
65
|
+
* a later one.
|
|
66
|
+
*/
|
|
67
|
+
observedEpochBytes: Uint8Array | null;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* `acquire`: holder expected absent, epoch expected the exact bytes just
|
|
71
|
+
* read. Grants a fresh claim at `(observedEpoch ?? 0) + 1`. Meant to be
|
|
72
|
+
* folded into the same atomic batch as the enabling write (a create-batch or
|
|
73
|
+
* a pending-to-running transition), except for the named `acquire (standalone
|
|
74
|
+
* resume)` exception described in the ADR, which commits this fragment alone.
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildWorkflowClaimAcquireTransition(input: WorkflowClaimAcquireInput): WorkflowClaimTransitionFragment;
|
|
77
|
+
/** Input to {@link buildWorkflowClaimRenewTransition}. */
|
|
78
|
+
export type WorkflowClaimRenewInput = {
|
|
79
|
+
workflowId: string;
|
|
80
|
+
now: number;
|
|
81
|
+
claimTtlMs: number;
|
|
82
|
+
/**
|
|
83
|
+
* The exact holder bytes this engine last wrote (from its own prior
|
|
84
|
+
* acquire, takeover, or renew) — the sole CAS condition. The epoch key is
|
|
85
|
+
* not conditioned on separately: any epoch change already changes these
|
|
86
|
+
* bytes, since `epoch` is one of the holder record's fields.
|
|
87
|
+
*/
|
|
88
|
+
currentHolderBytes: Uint8Array;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* `renew`: holder expected the exact bytes this engine last wrote. Rewrites
|
|
92
|
+
* the holder with the SAME `engineId`, SAME `epoch`, and SAME `claimedAt`,
|
|
93
|
+
* and a fresh `expiresAt`. `currentHolderBytes` must decode (it is this
|
|
94
|
+
* engine's own prior write); a caller that no longer has a valid cached
|
|
95
|
+
* holder should not attempt renewal.
|
|
96
|
+
*/
|
|
97
|
+
export declare function buildWorkflowClaimRenewTransition(input: WorkflowClaimRenewInput): WorkflowClaimTransitionFragment;
|
|
98
|
+
/** Input to {@link buildWorkflowClaimReleaseTransition}. */
|
|
99
|
+
export type WorkflowClaimReleaseInput = {
|
|
100
|
+
workflowId: string;
|
|
101
|
+
/** This engine's cached epoch bytes — CAS condition on `wf-owner-epoch:<workflowId>`. */
|
|
102
|
+
currentEpochBytes: Uint8Array;
|
|
103
|
+
/** This engine's last-known holder bytes — CAS condition on `wf-owner-holder:<workflowId>`. */
|
|
104
|
+
currentHolderBytes: Uint8Array;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* `release`: epoch expected this engine's cached epoch bytes AND holder
|
|
108
|
+
* expected last-known holder bytes. Deletes ONLY the holder — the epoch key
|
|
109
|
+
* is never deleted, so a successor's next `acquire` reads the true prior
|
|
110
|
+
* epoch and mints one past it rather than re-minting a stale generation.
|
|
111
|
+
*/
|
|
112
|
+
export declare function buildWorkflowClaimReleaseTransition(input: WorkflowClaimReleaseInput): WorkflowClaimTransitionFragment;
|
|
113
|
+
/** Input to {@link buildWorkflowClaimTakeoverTransition}. */
|
|
114
|
+
export type WorkflowClaimTakeoverInput = {
|
|
115
|
+
workflowId: string;
|
|
116
|
+
engineId: string;
|
|
117
|
+
now: number;
|
|
118
|
+
claimTtlMs: number;
|
|
119
|
+
/** The exact stale holder bytes read during the `expire` judgment — CAS condition. */
|
|
120
|
+
observedHolderBytes: Uint8Array;
|
|
121
|
+
/** The exact epoch bytes read alongside `observedHolderBytes` — CAS condition and the source for the minted epoch, never self-reported by the stale holder. */
|
|
122
|
+
observedEpochBytes: Uint8Array;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* `takeover`: holder expected the exact stale holder bytes read AND epoch
|
|
126
|
+
* expected the exact epoch bytes read alongside it. Grants a fresh claim at
|
|
127
|
+
* `readEpoch + 1`, minted from the epoch bytes just read — never from the
|
|
128
|
+
* stale holder's self-reported `epoch` field, which a corrupt or hostile
|
|
129
|
+
* record could understate.
|
|
130
|
+
*/
|
|
131
|
+
export declare function buildWorkflowClaimTakeoverTransition(input: WorkflowClaimTakeoverInput): WorkflowClaimTransitionFragment;
|
|
132
|
+
/** Input to {@link buildWorkflowClaimExternalTerminalRotationTransition}. */
|
|
133
|
+
export type WorkflowClaimExternalTerminalRotationInput = {
|
|
134
|
+
workflowId: string;
|
|
135
|
+
/**
|
|
136
|
+
* The exact bytes last read for `wf-owner-epoch:<workflowId>`, or `null`
|
|
137
|
+
* when the workflow was never claimed (e.g. cancelling a workflow that
|
|
138
|
+
* never resumed). The rotated epoch is `(observedEpoch ?? 0) + 1`, the same
|
|
139
|
+
* never-a-literal minting rule `acquire` uses.
|
|
140
|
+
*/
|
|
141
|
+
observedEpochBytes: Uint8Array | null;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* External terminal rotation: rotates `wf-owner-epoch:<workflowId>` to
|
|
145
|
+
* `readEpoch + 1` and deletes `wf-owner-holder:<workflowId>`, in one fragment
|
|
146
|
+
* meant to be folded into the SAME atomic batch that writes a cancel,
|
|
147
|
+
* timeout, suspend, or purge terminal/suspended state. Any engine may commit
|
|
148
|
+
* this — that is what makes these transitions "intentionally external" per
|
|
149
|
+
* the ADR's entry-point classification. Rotation is what deposes a still-running
|
|
150
|
+
* owner: its next write carries the now-stale epoch and loses its CAS.
|
|
151
|
+
*
|
|
152
|
+
* This must NOT be used for non-terminal external mutations (signal delivery,
|
|
153
|
+
* tag/search-attribute edits) — those do not end the run, so the owner's
|
|
154
|
+
* continued execution is correct and the epoch must not rotate under it.
|
|
155
|
+
*/
|
|
156
|
+
export declare function buildWorkflowClaimExternalTerminalRotationTransition(input: WorkflowClaimExternalTerminalRotationInput): WorkflowClaimTransitionFragment;
|
|
157
|
+
/** Input to {@link isWorkflowClaimExpired}. */
|
|
158
|
+
export type WorkflowClaimExpiryInput = {
|
|
159
|
+
/** `expiresAt` from the holder bytes last read. */
|
|
160
|
+
expiresAt: number;
|
|
161
|
+
/** This engine's own clock. */
|
|
162
|
+
now: number;
|
|
163
|
+
/** The configured `workflowClaimRenewInterval`, scaled by {@link WORKFLOW_CLAIM_TAKEOVER_GRACE_MULTIPLIER}. */
|
|
164
|
+
renewIntervalMs: number;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* `expire`: an observed condition, not a storage transition. A holder is
|
|
168
|
+
* eligible for `takeover` once its `expiresAt` plus a grace term
|
|
169
|
+
* (`WORKFLOW_CLAIM_TAKEOVER_GRACE_MULTIPLIER * renewIntervalMs`) is strictly
|
|
170
|
+
* earlier than `now` — matching the ADR's "is earlier than this engine's own
|
|
171
|
+
* clock" wording exactly, so a grace-adjusted deadline equal to `now` is NOT
|
|
172
|
+
* yet expired. The grace term dampens clock-skew-driven false-expiry
|
|
173
|
+
* judgments; it carries no write-safety weight on its own — only the
|
|
174
|
+
* subsequent `takeover` CAS does.
|
|
175
|
+
*/
|
|
176
|
+
export declare function isWorkflowClaimExpired(input: WorkflowClaimExpiryInput): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Pull the exact bytes a just-built transition fragment wrote for `key`,
|
|
179
|
+
* rather than re-encoding a value from the fields the caller happens to
|
|
180
|
+
* know. This is what lets {@link WorkflowClaimRegistry} cache "the bytes it
|
|
181
|
+
* actually wrote" without silently drifting if `workflow-claim-transitions.ts`'s
|
|
182
|
+
* internal object-literal field order ever changed. Exported so the
|
|
183
|
+
* not-found branch — unreachable through the registry itself, since every
|
|
184
|
+
* fragment it extracts from is one it just built — has direct unit coverage.
|
|
185
|
+
*/
|
|
186
|
+
export declare function extractPutOperationValue(operations: BatchOperation[], key: string): Uint8Array;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { KEYS } from "../../storage/interface.js";
|
|
2
|
+
import {
|
|
3
|
+
decodeEpoch,
|
|
4
|
+
decodeWorkflowClaimHolder,
|
|
5
|
+
encodeEpoch,
|
|
6
|
+
encodeWorkflowClaimHolder
|
|
7
|
+
} from "./workflow-claim-codec.js";
|
|
8
|
+
export const WORKFLOW_CLAIM_TTL_SAFETY_MULTIPLIER = 3, WORKFLOW_CLAIM_TAKEOVER_GRACE_MULTIPLIER = 2;
|
|
9
|
+
function nextEpochFromObservedBytes(observedEpochBytes) {
|
|
10
|
+
return ((observedEpochBytes === null ? null : decodeEpoch(observedEpochBytes)) ?? 0) + 1;
|
|
11
|
+
}
|
|
12
|
+
function buildClaimGrantOperations(input) {
|
|
13
|
+
const holder = {
|
|
14
|
+
engineId: input.engineId,
|
|
15
|
+
epoch: input.nextEpoch,
|
|
16
|
+
expiresAt: input.now + input.claimTtlMs,
|
|
17
|
+
claimedAt: input.now
|
|
18
|
+
};
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
type: "put",
|
|
22
|
+
key: KEYS.workflowOwnerEpoch(input.workflowId),
|
|
23
|
+
value: encodeEpoch(input.nextEpoch)
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "put",
|
|
27
|
+
key: KEYS.workflowOwnerHolder(input.workflowId),
|
|
28
|
+
value: encodeWorkflowClaimHolder(holder)
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
export function buildWorkflowClaimAcquireTransition(input) {
|
|
33
|
+
const nextEpoch = nextEpochFromObservedBytes(input.observedEpochBytes);
|
|
34
|
+
return {
|
|
35
|
+
conditions: [
|
|
36
|
+
{ key: KEYS.workflowOwnerHolder(input.workflowId), expectedValue: null },
|
|
37
|
+
{ key: KEYS.workflowOwnerEpoch(input.workflowId), expectedValue: input.observedEpochBytes }
|
|
38
|
+
],
|
|
39
|
+
operations: buildClaimGrantOperations({
|
|
40
|
+
workflowId: input.workflowId,
|
|
41
|
+
engineId: input.engineId,
|
|
42
|
+
now: input.now,
|
|
43
|
+
claimTtlMs: input.claimTtlMs,
|
|
44
|
+
nextEpoch
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function buildWorkflowClaimRenewTransition(input) {
|
|
49
|
+
const currentHolder = decodeWorkflowClaimHolder(input.currentHolderBytes);
|
|
50
|
+
if (currentHolder === null)
|
|
51
|
+
throw Error("buildWorkflowClaimRenewTransition: currentHolderBytes did not decode to a valid holder record");
|
|
52
|
+
const renewedHolder = {
|
|
53
|
+
engineId: currentHolder.engineId,
|
|
54
|
+
epoch: currentHolder.epoch,
|
|
55
|
+
expiresAt: input.now + input.claimTtlMs,
|
|
56
|
+
claimedAt: currentHolder.claimedAt
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
conditions: [
|
|
60
|
+
{ key: KEYS.workflowOwnerHolder(input.workflowId), expectedValue: input.currentHolderBytes }
|
|
61
|
+
],
|
|
62
|
+
operations: [
|
|
63
|
+
{
|
|
64
|
+
type: "put",
|
|
65
|
+
key: KEYS.workflowOwnerHolder(input.workflowId),
|
|
66
|
+
value: encodeWorkflowClaimHolder(renewedHolder)
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function buildWorkflowClaimReleaseTransition(input) {
|
|
72
|
+
return {
|
|
73
|
+
conditions: [
|
|
74
|
+
{ key: KEYS.workflowOwnerEpoch(input.workflowId), expectedValue: input.currentEpochBytes },
|
|
75
|
+
{ key: KEYS.workflowOwnerHolder(input.workflowId), expectedValue: input.currentHolderBytes }
|
|
76
|
+
],
|
|
77
|
+
operations: [{ type: "delete", key: KEYS.workflowOwnerHolder(input.workflowId) }]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export function buildWorkflowClaimTakeoverTransition(input) {
|
|
81
|
+
const nextEpoch = nextEpochFromObservedBytes(input.observedEpochBytes);
|
|
82
|
+
return {
|
|
83
|
+
conditions: [
|
|
84
|
+
{ key: KEYS.workflowOwnerHolder(input.workflowId), expectedValue: input.observedHolderBytes },
|
|
85
|
+
{ key: KEYS.workflowOwnerEpoch(input.workflowId), expectedValue: input.observedEpochBytes }
|
|
86
|
+
],
|
|
87
|
+
operations: buildClaimGrantOperations({
|
|
88
|
+
workflowId: input.workflowId,
|
|
89
|
+
engineId: input.engineId,
|
|
90
|
+
now: input.now,
|
|
91
|
+
claimTtlMs: input.claimTtlMs,
|
|
92
|
+
nextEpoch
|
|
93
|
+
})
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function buildWorkflowClaimExternalTerminalRotationTransition(input) {
|
|
97
|
+
const nextEpoch = nextEpochFromObservedBytes(input.observedEpochBytes);
|
|
98
|
+
return {
|
|
99
|
+
conditions: [
|
|
100
|
+
{ key: KEYS.workflowOwnerEpoch(input.workflowId), expectedValue: input.observedEpochBytes }
|
|
101
|
+
],
|
|
102
|
+
operations: [
|
|
103
|
+
{
|
|
104
|
+
type: "put",
|
|
105
|
+
key: KEYS.workflowOwnerEpoch(input.workflowId),
|
|
106
|
+
value: encodeEpoch(nextEpoch)
|
|
107
|
+
},
|
|
108
|
+
{ type: "delete", key: KEYS.workflowOwnerHolder(input.workflowId) }
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export function isWorkflowClaimExpired(input) {
|
|
113
|
+
return input.expiresAt + WORKFLOW_CLAIM_TAKEOVER_GRACE_MULTIPLIER * input.renewIntervalMs < input.now;
|
|
114
|
+
}
|
|
115
|
+
export function extractPutOperationValue(operations, key) {
|
|
116
|
+
const operation = operations.find((candidate) => candidate.type === "put" && candidate.key === key);
|
|
117
|
+
if (operation === void 0)
|
|
118
|
+
throw Error(`workflow-claim-registry: expected a "put" operation for key "${key}"`);
|
|
119
|
+
return operation.value;
|
|
120
|
+
}
|
|
@@ -66,6 +66,26 @@ export declare class InlineExecutionStrategy implements ExecutionStrategy {
|
|
|
66
66
|
* activity failures, etc.).
|
|
67
67
|
*/
|
|
68
68
|
throwIntoWorkflow(workflowId: string, error: unknown, operationFailureCategory?: FailureCategory): void;
|
|
69
|
+
/**
|
|
70
|
+
* Synchronously evict a workflow's live/parked context, generator, and
|
|
71
|
+
* abort controller the moment a same-engine reclaim begins (WFT-79) —
|
|
72
|
+
* BEFORE `onReclaimed`'s `recoverPendingAsyncActivities`/`resumeFromLifecycle`
|
|
73
|
+
* await anything. `takeover()` installing a new local epoch does not, by
|
|
74
|
+
* itself, evict this engine's OLD in-memory state for a workflow it
|
|
75
|
+
* previously held and was deposed from (deposition only drops the claim
|
|
76
|
+
* registry entry; contexts/generators survive — see `index.ts`'s
|
|
77
|
+
* `onWorkflowClaimReclaimed`). Without this, `query()` and
|
|
78
|
+
* `tryInlineUpdateHandler()`'s engine-id-only staleness check
|
|
79
|
+
* (`isWorkflowClaimedByAnotherEngine`) sees the SAME engine as both the old
|
|
80
|
+
* and new holder and answers "not stale," serving reads/handler invocations
|
|
81
|
+
* from the pre-reclaim closure throughout the async-activity reload and
|
|
82
|
+
* force-replay preparation window. Evicting here makes that window
|
|
83
|
+
* observably contextless instead — `query()` falls through to its
|
|
84
|
+
* documented not-locally-owned/undefined handling, and
|
|
85
|
+
* `tryInlineUpdateHandler()` falls through to `'not-owned-locally'` — until
|
|
86
|
+
* `adoptWorkflow` installs the fresh generation.
|
|
87
|
+
*/
|
|
88
|
+
evictContextForReclaim(workflowId: string): void;
|
|
69
89
|
/**
|
|
70
90
|
* Store a context and generator created externally (engine resume path).
|
|
71
91
|
* Clears any retained parked context so a concurrent query sees the new
|
|
@@ -115,6 +115,12 @@ export class InlineExecutionStrategy {
|
|
|
115
115
|
return;
|
|
116
116
|
this.#throwIntoGenerator(workflowId, generator, error, operationFailureCategory);
|
|
117
117
|
}
|
|
118
|
+
evictContextForReclaim(workflowId) {
|
|
119
|
+
this.#generators.delete(workflowId);
|
|
120
|
+
this.#abortControllers.delete(workflowId);
|
|
121
|
+
this.#contexts.delete(workflowId);
|
|
122
|
+
this.#parkedContexts.delete(workflowId);
|
|
123
|
+
}
|
|
118
124
|
adoptWorkflow(workflowId, generator, context, abortController) {
|
|
119
125
|
this.#parkedContexts.delete(workflowId);
|
|
120
126
|
this.#generators.set(workflowId, generator);
|
|
@@ -135,18 +141,23 @@ export class InlineExecutionStrategy {
|
|
|
135
141
|
this[Symbol.dispose]();
|
|
136
142
|
}
|
|
137
143
|
#driveGenerator(workflowId, generator, lastResult) {
|
|
138
|
-
return this.#advanceGenerator(workflowId, () => generator.next(lastResult), void 0);
|
|
144
|
+
return this.#advanceGenerator(workflowId, generator, () => generator.next(lastResult), void 0);
|
|
139
145
|
}
|
|
140
146
|
#throwIntoGenerator(workflowId, generator, error, operationFailureCategory) {
|
|
141
|
-
return this.#advanceGenerator(workflowId, () => generator.throw(error), operationFailureCategory);
|
|
147
|
+
return this.#advanceGenerator(workflowId, generator, () => generator.throw(error), operationFailureCategory);
|
|
142
148
|
}
|
|
143
|
-
#advanceGenerator(workflowId, advance, fallbackFailureCategory) {
|
|
149
|
+
#advanceGenerator(workflowId, generator, advance, fallbackFailureCategory) {
|
|
144
150
|
return this.#trackWorkflowAdvance(workflowId, (async () => {
|
|
145
151
|
try {
|
|
146
152
|
if (this.#abortControllers.get(workflowId)?.signal.aborted)
|
|
147
153
|
return;
|
|
148
|
-
|
|
154
|
+
const iterationResult = await advance();
|
|
155
|
+
if (this.#generators.get(workflowId) !== generator)
|
|
156
|
+
return;
|
|
157
|
+
this.#handleIterationResult(workflowId, iterationResult);
|
|
149
158
|
} catch (error) {
|
|
159
|
+
if (this.#generators.get(workflowId) !== generator)
|
|
160
|
+
return;
|
|
150
161
|
this.#cleanup(workflowId, {
|
|
151
162
|
preserveTrackedAdvance: !0,
|
|
152
163
|
preserveTrackedTurn: !0
|
|
@@ -178,11 +178,11 @@ export class Scheduler {
|
|
|
178
178
|
}
|
|
179
179
|
async#buildTimerIndexDeleteOperation(nextEntry) {
|
|
180
180
|
const indexKey = `timer-idx:${nextEntry.entry.id}`;
|
|
181
|
-
if (nextEntry.entry.kind === "schedule")
|
|
182
|
-
return this.#
|
|
181
|
+
if (nextEntry.entry.kind === "schedule" || nextEntry.entry.kind === "sleep" || nextEntry.entry.kind === "wait-condition")
|
|
182
|
+
return this.#buildLookupBasedTimerIndexDeleteOperation(nextEntry, indexKey);
|
|
183
183
|
return shouldDeleteTimerIndexWithoutLookup(nextEntry.entry) ? { type: "delete", key: indexKey } : null;
|
|
184
184
|
}
|
|
185
|
-
async#
|
|
185
|
+
async#buildLookupBasedTimerIndexDeleteOperation(nextEntry, indexKey) {
|
|
186
186
|
const indexValue = await this.#storage.get(indexKey);
|
|
187
187
|
if (indexValue === null)
|
|
188
188
|
return null;
|
|
@@ -15,4 +15,17 @@ export declare function readNextTerminalCleanupTimerEntry(iterator: AsyncIterato
|
|
|
15
15
|
export declare function readNextTeardownTimerEntry(iterator: AsyncIterator<[string, Uint8Array]>, storage: Storage): Promise<ScannedTimerEntry | null>;
|
|
16
16
|
export declare function advanceTimerSource(timerSource: TimerSource, storage: Storage): Promise<void>;
|
|
17
17
|
export declare function selectNextTimerSource(timerSources: TimerSource[]): TimerSource | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* `true` for a timer kind whose `timer-idx:` reverse-index entry is safe to
|
|
20
|
+
* delete unconditionally on fire, with no read-and-compare first.
|
|
21
|
+
* `'terminal-cleanup'`/`'teardown'` get no reverse index at all (never
|
|
22
|
+
* cancelled out-of-band). `'schedule'`/`'sleep'`/`'wait-condition'` are
|
|
23
|
+
* EXCLUDED even though this function's signature still accepts them —
|
|
24
|
+
* `scheduler-class.ts`'s `#buildTimerIndexDeleteOperation` checks those three
|
|
25
|
+
* kinds and routes them through the lookup-and-compare path BEFORE ever
|
|
26
|
+
* calling this function, because each can have its deterministic id re-armed
|
|
27
|
+
* by a legitimate successor (schedule's own re-arm-on-every-tick; a
|
|
28
|
+
* `start-new` replacement reusing a sleep/wait-condition id) while the
|
|
29
|
+
* original fire is still being cleaned up.
|
|
30
|
+
*/
|
|
18
31
|
export declare function shouldDeleteTimerIndexWithoutLookup(entry: TimerEntry): boolean;
|
|
@@ -63,5 +63,5 @@ export function selectNextTimerSource(timerSources) {
|
|
|
63
63
|
return selectedSource;
|
|
64
64
|
}
|
|
65
65
|
export function shouldDeleteTimerIndexWithoutLookup(entry) {
|
|
66
|
-
return entry.kind !== "schedule" && entry.kind !== "terminal-cleanup" && entry.kind !== "teardown";
|
|
66
|
+
return entry.kind !== "schedule" && entry.kind !== "terminal-cleanup" && entry.kind !== "teardown" && entry.kind !== "sleep" && entry.kind !== "wait-condition";
|
|
67
67
|
}
|
|
@@ -282,8 +282,14 @@ export interface EngineOptions<TServices = unknown> {
|
|
|
282
282
|
* writing after its lease expired. Epoch fencing of durable writes is what
|
|
283
283
|
* closes that gap. Keep infrastructure-level single-instance enforcement as the
|
|
284
284
|
* real control.
|
|
285
|
+
*
|
|
286
|
+
* `'workflow-lease'` (ADR 0002) fences execution per workflow instead of the
|
|
287
|
+
* whole store, so multiple engines may share one durable store. Mutually
|
|
288
|
+
* exclusive with `'lease'` (enforced across processes via a store-wide
|
|
289
|
+
* marker) and rejected with `detectSecondInstance: true`; unlike `'lease'`,
|
|
290
|
+
* compatible with `backgroundTasks: 'manual'` via `runMaintenance()`.
|
|
285
291
|
*/
|
|
286
|
-
ownership?: 'none' | 'lease';
|
|
292
|
+
ownership?: 'none' | 'lease' | 'workflow-lease';
|
|
287
293
|
/**
|
|
288
294
|
* Lease time-to-live for `ownership: 'lease'` (default `30s`). A holder renews
|
|
289
295
|
* well within this window; once it lapses without renewal, a waiting instance
|
|
@@ -308,6 +314,16 @@ export interface EngineOptions<TServices = unknown> {
|
|
|
308
314
|
* Ignored when `ownership` is not `'lease'`.
|
|
309
315
|
*/
|
|
310
316
|
leaseWaitTimeout?: Duration;
|
|
317
|
+
/**
|
|
318
|
+
* Claim time-to-live for `ownership: 'workflow-lease'` (default `30s`); like
|
|
319
|
+
* {@link EngineOptions.leaseTtl} but scoped per workflow. Ignored otherwise.
|
|
320
|
+
*/
|
|
321
|
+
workflowClaimTtl?: Duration;
|
|
322
|
+
/**
|
|
323
|
+
* Claim renewal interval for `ownership: 'workflow-lease'` (default `5s`);
|
|
324
|
+
* like {@link EngineOptions.leaseRenewInterval}, scoped per workflow.
|
|
325
|
+
*/
|
|
326
|
+
workflowClaimRenewInterval?: Duration;
|
|
311
327
|
/**
|
|
312
328
|
* History circuit-breaker thresholds. When `history.maxEvents` is set, a
|
|
313
329
|
* workflow whose event-log record count would exceed it is forced to a
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* }
|
|
26
26
|
* ```
|
|
27
27
|
*/
|
|
28
|
-
export type WeftErrorCode = 'WorkflowAlreadyExistsError' | 'BulkDeleteRequiresTerminalWorkflowsError' | 'BulkOperationConfirmationError' | 'WorkflowTypeNotRegisteredForRecoveryError' | 'EngineCreateNameMismatchError' | 'EngineDisposedError' | 'EngineDisposalError' | 'WorkflowNotFoundError' | 'WorkflowNotRegisteredError' | 'WorkflowConcurrencyLimitExceededError' | 'WorkflowSuspendNotSupportedError' | 'ActivityResolutionError' | 'BranchTopologyChangedError' | 'PersistedDataIncompatibleError' | 'WorkflowTimeoutError' | 'HttpClientError' | 'WorkerProtocolIncompatibleError' | 'UpdateTimeoutError' | 'UpdateValidationError' | 'WorkflowTerminalError' | 'WorkflowBuilderError' | 'VersionMismatchError' | 'EffectReplayConflictError' | 'ReviewTimeoutError' | 'AtomicStateConflictError' | 'StandardSchemaValidationError' | 'ActivityReconciliationCapabilityError' | 'ActivityReconciliationConflictError' | 'ActivityReconciliationIndeterminateError' | 'DurableActivityScopeError' | 'DurableActivityUnsupportedError' | 'AsyncActivityTokenNotFoundError' | 'ActivityScheduleToCloseTimeoutError' | 'ActivityPerAttemptTimeoutError' | 'PayloadSizeExceededError' | 'StartOrSignalConflictError' | 'WorkflowTeardownPendingError' | 'IdempotencyKeyPurgedError' | 'WorkerManifestBuildError';
|
|
28
|
+
export type WeftErrorCode = 'WorkflowAlreadyExistsError' | 'BulkDeleteRequiresTerminalWorkflowsError' | 'BulkOperationConfirmationError' | 'WorkflowTypeNotRegisteredForRecoveryError' | 'EngineCreateNameMismatchError' | 'EngineDisposedError' | 'EngineDisposalError' | 'WorkflowNotFoundError' | 'WorkflowNotRegisteredError' | 'WorkflowConcurrencyLimitExceededError' | 'WorkflowSuspendNotSupportedError' | 'ActivityResolutionError' | 'BranchTopologyChangedError' | 'PersistedDataIncompatibleError' | 'WorkflowTimeoutError' | 'HttpClientError' | 'WorkerProtocolIncompatibleError' | 'UpdateTimeoutError' | 'UpdateValidationError' | 'WorkflowTerminalError' | 'WorkflowBuilderError' | 'VersionMismatchError' | 'EffectReplayConflictError' | 'ReviewTimeoutError' | 'AtomicStateConflictError' | 'StandardSchemaValidationError' | 'ActivityReconciliationCapabilityError' | 'ActivityReconciliationConflictError' | 'ActivityReconciliationIndeterminateError' | 'DurableActivityScopeError' | 'DurableActivityUnsupportedError' | 'AsyncActivityTokenNotFoundError' | 'ActivityScheduleToCloseTimeoutError' | 'ActivityPerAttemptTimeoutError' | 'PayloadSizeExceededError' | 'StartOrSignalConflictError' | 'WorkflowTeardownPendingError' | 'IdempotencyKeyPurgedError' | 'WorkerManifestBuildError' | 'OwnershipModeMismatchError';
|
|
29
29
|
/**
|
|
30
30
|
* Generic abstract base for all Weft library errors. The `TCode` parameter
|
|
31
31
|
* makes each subclass's `code` its own literal type; the exported base surface
|
package/dist/core/weft-error.js
CHANGED
|
@@ -45,7 +45,8 @@ const publicWeftErrorCodeMap = {
|
|
|
45
45
|
StartOrSignalConflictError: !0,
|
|
46
46
|
WorkflowTeardownPendingError: !0,
|
|
47
47
|
IdempotencyKeyPurgedError: !0,
|
|
48
|
-
WorkerManifestBuildError: !0
|
|
48
|
+
WorkerManifestBuildError: !0,
|
|
49
|
+
OwnershipModeMismatchError: !0
|
|
49
50
|
}, PUBLIC_WEFT_ERROR_CODES = new Set(Object.keys(publicWeftErrorCodeMap));
|
|
50
51
|
export function isWeftError(value) {
|
|
51
52
|
return value instanceof WeftError;
|
package/dist/http.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
async function*
|
|
2
|
-
`);Z=A.pop()??"";for(let g of A)yield g}if(Z+=Q.decode(),Z.length>0)yield Z}finally{if(!j)try{await J.cancel()}catch{}J.releaseLock()}}function N(F){let G=[];for(let J=0;J<F.length;J+=512)G.push(String.fromCharCode(...F.subarray(J,J+512)));return btoa(G.join(""))}function R(F){let G=atob(F),J=new Uint8Array(G.length);for(let Q=0;Q<G.length;Q+=1)J[Q]=G.charCodeAt(Q);return J}function q(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}async function _(F,G){return await F.get(G)!==null}async function*X(F,G,J){for await(let[Q]of F.scan(G,J))yield Q}async function H(F,G){let J=0;for await(let Q of X(F,G))J++;return J}async function L(F,G){let J=[];for await(let Q of X(F,G))J.push({type:"delete",key:Q});if(J.length===0)return 0;return await F.batch(J),J.length}async function U(F,G,J){let Q=[];for await(let Z of X(F,G,J))Q.push({type:"delete",key:Z});if(Q.length===0)return 0;return await F.batch(Q),Q.length}function C(F,G,J){if(!F.capabilities()[G])throw Error(`Feature "${J}" requires storage capability "${G}", but this storage backend does not provide it.`)}var D=1e4;class T extends Error{code="StorageBatchOperationLimitExceededError";cap=D;count;target;constructor(F,G){super(`${F} count ${G} exceeds MAX_BATCH_OPERATIONS (${D}).`);this.name="StorageBatchOperationLimitExceededError",this.target=F,this.count=G}}function M(F,G){if(G>D)throw new T(F,G)}function K(F){return F.length>0?F.slice(0,-1)+String.fromCharCode(F.charCodeAt(F.length-1)+1):"ÿ"}function e(F,G={}){if(G.gt!==void 0&&F<=G.gt)return!1;if(G.gte!==void 0&&F<G.gte)return!1;if(G.lt!==void 0&&F>=G.lt)return!1;if(G.lte!==void 0&&F>G.lte)return!1;return!0}function FF(F,G){if(F===null||G===null)return F===G;if(F.byteLength!==G.byteLength)return!1;for(let J=0;J<F.byteLength;J++)if(F[J]!==G[J])return!1;return!0}async function S(F,G){if(F.has)return F.has(G);return _(F,G)}function O(F,G,J){if(F.keys)return F.keys(G,J);return X(F,G,J)}async function P(F,G){if(F.count)return F.count(G);return H(F,G)}async function b(F,G){if(F.deletePrefix)return F.deletePrefix(G);return L(F,G)}async function v(F,G,J){if(M("conditionalBatch conditions",G.length),M("conditionalBatch operations",J.length),C(F,"conditionalBatch","storageConditionalBatch"),!F.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return F.conditionalBatch(G,J)}function c(F){if(F===void 0)return;if(typeof F!=="number"||!Number.isInteger(F)||F<0)throw Error("deleteRange limit must be a finite non-negative integer");return F===0?0:F}function V(F){let G={},J=!1;for(let Z of["gt","gte","lt","lte"]){let $=F[Z];if($===void 0)continue;if(typeof $!=="string")throw Error("deleteRange bounds must be strings");G[Z]=$,J=!0}if(!J)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let Q=c(F.limit);if(Q!==void 0)G.limit=Q;return G}async function h(F,G,J){let Q=V(J);if(F.deleteRange)return F.deleteRange(G,Q);return U(F,G,Q)}function I(F,G){let J={key:F,open:!1};if(G.gte!==void 0&&G.gte>J.key)J.key=G.gte,J.open=!1;if(G.gt!==void 0&&G.gt>=J.key)J.key=G.gt,J.open=!0;return J}function u(F,G){let J={key:K(F),open:!0};if(G.lt!==void 0&&G.lt<=J.key)J.key=G.lt,J.open=!0;if(G.lte!==void 0&&G.lte<J.key)J.key=G.lte,J.open=!1;return J}function ZF(F,G){let J=I(F,G),Q=u(F,G);if(J.key>Q.key||J.key===Q.key&&(J.open||Q.open))return null;return{lower:J,upper:Q}}function E(F){return F.replaceAll(/:+$/g,"")}function k(F,G){let J=E(F),Q=E(G);if(J.length===0)return Q;if(Q.length===0)return J;return`${J}:${Q}`}class W{#F;#J;constructor(F,G){this.#F=F,this.#J=E(G)}#G(F){if(this.#J.length===0)return F;return F.length===0?`${this.#J}:`:`${this.#J}:${F}`}#Z(F){return F.map((G)=>{if(G.type==="put")return{type:"put",key:this.#G(G.key),value:G.value};return{type:"delete",key:this.#G(G.key)}})}#$(F){if(this.#J.length===0)return F;return F.slice(this.#J.length+1)}#M(F){let G={};if(F.limit!==void 0)G.limit=F.limit;if(F.gt!==void 0)G.gt=this.#G(F.gt);if(F.gte!==void 0)G.gte=this.#G(F.gte);if(F.lt!==void 0)G.lt=this.#G(F.lt);if(F.lte!==void 0)G.lte=this.#G(F.lte);return G}#Q(F={}){let G=this.#M(F);if(F.reverse!==void 0)G.reverse=F.reverse;return G}#X(F){return this.#M(F)}capabilities(){return this.#F.capabilities()}scoped(F){return new W(this.#F,k(this.#J,F))}async get(F){return this.#F.get(this.#G(F))}async put(F,G){await this.#F.put(this.#G(F),G)}async delete(F){await this.#F.delete(this.#G(F))}async*scan(F,G){for await(let[J,Q]of this.#F.scan(this.#G(F),this.#Q(G)))yield[this.#$(J),Q]}async batch(F){M("batch operations",F.length),await this.#F.batch(this.#Z(F))}async conditionalBatch(F,G){return v(this.#F,F.map((J)=>({key:this.#G(J.key),expectedValue:J.expectedValue})),this.#Z(G))}async has(F){return S(this.#F,this.#G(F))}async deletePrefix(F){return b(this.#F,this.#G(F))}async deleteRange(F,G){let J=this.#X(V(G));return h(this.#F,this.#G(F),J)}async*keys(F,G){for await(let J of O(this.#F,this.#G(F),this.#Q(G)))yield this.#$(J)}async count(F){return P(this.#F,this.#G(F))}[Symbol.dispose](){this.#F[Symbol.dispose]()}}function m(F,G){return new W(F,G)}var w=67108864;function x(F){if(F.type==="put")return{type:"put",key:F.key,value:N(F.value)};return{type:"delete",key:F.key}}function f(F){return{key:F.key,expectedValue:F.expectedValue===null?null:N(F.expectedValue)}}function d(F){if(!q(F)||typeof F.key!=="string"||typeof F.value!=="string")throw Error("HTTPStorage scan response contained an invalid NDJSON entry.");return{key:F.key,value:F.value}}function l(F){if(!q(F)||typeof F.applied!=="boolean")throw Error('HTTPStorage conditional batch response must include a boolean "applied" field.');return F.applied}function Y(F,G,J){if(J!==void 0)F.searchParams.set(G,String(J))}function p(F){if(F.trim().length===0)return null;let G=d(JSON.parse(F));return[G.key,R(G.value)]}class s{#F;#J;#G;constructor(F){this.#F=F.baseUrl instanceof URL?F.baseUrl:new URL(F.baseUrl),this.#J={...F.headers},this.#G=F.remoteConditionalBatch??!1}capabilities(){return{persistence:"remote",readAfterWrite:"eventual",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:this.#G,boundedRangeDelete:!1}}#Z(F){let G=this.#F.href.endsWith("/")?this.#F.href:`${this.#F.href}/`;return new URL(F.replace(/^\/+/,""),G)}#$(F){return this.#Z(`/v1/storage/${encodeURIComponent(F)}`)}#M(F,G){let J=this.#Z("/v1/storage");return J.searchParams.set("prefix",F),Y(J,"limit",G.limit),Y(J,"reverse",G.reverse),Y(J,"gt",G.gt),Y(J,"gte",G.gte),Y(J,"lt",G.lt),Y(J,"lte",G.lte),J}async#Q(F,G={},J=[]){let Q=new Headers(this.#J);for(let[$,j]of new Headers(G.headers).entries())Q.set($,j);let Z=await fetch(F,{...G,headers:Q});if(!Z.ok&&!J.includes(Z.status))throw Error(`HTTPStorage request failed: ${G.method??"GET"} ${F.pathname} returned ${String(Z.status)}.`);return Z}async get(F){let G=await this.#Q(this.#$(F),{method:"GET"},[404]);if(G.status===404)return null;return new Uint8Array(await G.arrayBuffer())}async put(F,G){await this.#Q(this.#$(F),{method:"PUT",headers:{"content-type":"application/octet-stream"},body:new Blob([G])})}async delete(F){await this.#Q(this.#$(F),{method:"DELETE"})}async*scan(F,G={}){let J=await this.#Q(this.#M(F,G),{method:"GET",headers:{accept:"application/x-ndjson"}});for await(let Q of B(J,{maximumBytes:w,sizeLimitError:()=>Error("HTTPStorage scan response exceeded the maximum allowed size.")})){let Z=p(Q);if(Z!==null)yield Z}}async batch(F){M("batch operations",F.length),await this.#Q(this.#Z("/v1/storage/-/batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({operations:F.map(x)})})}async conditionalBatch(F,G){M("conditionalBatch conditions",F.length),M("conditionalBatch operations",G.length);let J=await this.#Q(this.#Z("/v1/storage/-/conditional-batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({conditions:F.map(f),operations:G.map(x)})});return l(await J.json())}has(F){return _(this,F)}async*keys(F,G){yield*X(this,F,G)}count(F){return H(this,F)}deletePrefix(F){return L(this,F)}deleteRange(F,G){return U(this,F,V(G))}scoped(F){return m(this,F)}[Symbol.dispose](){}}export{s as HTTPStorage};
|
|
1
|
+
async function*T(F,Q){if(F.body===null)return;let Y=F.body.getReader(),_=new TextDecoder,$="",M=0,H=!1;try{while(!0){let{done:k,value:B}=await Y.read();if(k){H=!0;break}if(M+=B.byteLength,M>Q.maximumBytes)throw Q.sizeLimitError();$+=_.decode(B,{stream:!0});let R=$.split(`
|
|
2
|
+
`);$=R.pop()??"";for(let w of R)yield w}if($+=_.decode(),$.length>0)yield $}finally{if(!H)try{await Y.cancel()}catch{}Y.releaseLock()}}function q(F){let Q=[];for(let Y=0;Y<F.length;Y+=512)Q.push(String.fromCharCode(...F.subarray(Y,Y+512)));return btoa(Q.join(""))}function C(F){let Q=atob(F),Y=new Uint8Array(Q.length);for(let _=0;_<Q.length;_+=1)Y[_]=Q.charCodeAt(_);return Y}function D(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}async function L(F,Q){return await F.get(Q)!==null}async function*G(F,Q,Y){for await(let[_]of F.scan(Q,Y))yield _}async function U(F,Q){let Y=0;for await(let _ of G(F,Q))Y++;return Y}async function E(F,Q){let Y=[];for await(let _ of G(F,Q))Y.push({type:"delete",key:_});if(Y.length===0)return 0;return await F.batch(Y),Y.length}async function N(F,Q,Y){let _=[];for await(let $ of G(F,Q,Y))_.push({type:"delete",key:$});if(_.length===0)return 0;return await F.batch(_),_.length}function P(F,Q,Y){if(!F.capabilities()[Q])throw Error(`Feature "${Y}" requires storage capability "${Q}", but this storage backend does not provide it.`)}var K="default";function Z(F){return encodeURIComponent(F)}var O={workflowOwnerEpoch:(F)=>`wf-owner-epoch:${Z(F)}`,workflowOwnerHolder:(F)=>`wf-owner-holder:${Z(F)}`,ownershipModeMarker:()=>"ownership-mode-marker"};var W=1e4;class b extends Error{code="StorageBatchOperationLimitExceededError";cap=W;count;target;constructor(F,Q){super(`${F} count ${Q} exceeds MAX_BATCH_OPERATIONS (${W}).`);this.name="StorageBatchOperationLimitExceededError",this.target=F,this.count=Q}}function X(F,Q){if(Q>W)throw new b(F,Q)}function v(F){return F.length>0?F.slice(0,-1)+String.fromCharCode(F.charCodeAt(F.length-1)+1):"ÿ"}function LF(F,Q={}){if(Q.gt!==void 0&&F<=Q.gt)return!1;if(Q.gte!==void 0&&F<Q.gte)return!1;if(Q.lt!==void 0&&F>=Q.lt)return!1;if(Q.lte!==void 0&&F>Q.lte)return!1;return!0}function UF(F,Q){if(F===null||Q===null)return F===Q;if(F.byteLength!==Q.byteLength)return!1;for(let Y=0;Y<F.byteLength;Y++)if(F[Y]!==Q[Y])return!1;return!0}async function h(F,Q){if(F.has)return F.has(Q);return L(F,Q)}function m(F,Q,Y){if(F.keys)return F.keys(Q,Y);return G(F,Q,Y)}async function x(F,Q){if(F.count)return F.count(Q);return U(F,Q)}async function y(F,Q){if(F.deletePrefix)return F.deletePrefix(Q);return E(F,Q)}async function c(F,Q,Y){if(X("conditionalBatch conditions",Q.length),X("conditionalBatch operations",Y.length),P(F,"conditionalBatch","storageConditionalBatch"),!F.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return F.conditionalBatch(Q,Y)}var J=(F)=>String(F).padStart(16,"0"),f="0",l="1",S=(F,Q,Y,_)=>`sig:${Z(F)}:${Z(Q)}:${_}:${Z(Y)}`,EF={workflow:(F)=>`wf:${Z(F)}`,checkpoint:(F)=>`wf:${Z(F)}:ckpt`,checkpointHistory:(F,Q)=>`wf:${Z(F)}:ckpt:${String(Q).padStart(10,"0")}`,timelinePrefix:(F)=>`wf:${Z(F)}:timeline:`,timeline:(F,Q)=>`wf:${Z(F)}:timeline:${String(Q).padStart(10,"0")}`,schedule:(F)=>`schedule:${Z(F)}`,scheduleTick:(F,Q)=>`schedule-due:${String(F).padStart(16,"0")}:${Z(Q)}`,scheduleRun:(F)=>`schedule-run:${Z(F)}`,scheduleRunLink:(F)=>`schedule-run-link:${Z(F)}`,scheduleRunBySchedulePrefix:(F)=>`schedule-run-by-schedule:${Z(F)}:`,scheduleRunBySchedule:(F,Q)=>`schedule-run-by-schedule:${Z(F)}:${Z(Q)}`,operation:(F,Q,Y)=>`op:${F}:${J(Q)}:${Y}`,operationInflight:(F)=>`op:inflight:${F}`,operationQueued:(F)=>`op:queued:${F}`,operationResolved:(F)=>`op:resolved:${F}`,bulkOperationAuditPrefix:()=>"audit:bulk:",bulkOperationAudit:(F,Q,Y)=>`audit:bulk:${J(F)}:${Z(Q)}:${Z(Y)}`,operationResolvedByTimePrefix:()=>"op:resolved-by-time:",operationResolvedByTime:(F,Q)=>`op:resolved-by-time:${J(F)}:${Z(Q)}`,asyncActivity:(F,Q)=>`async-act:v1:${Z(F)}:${Z(Q)}`,asyncActivityResolution:(F,Q)=>`async-act:v1:${Z(F)}:${Z(Q)}:resolution`,activityReconciliationPrefix:(F)=>`actrec:v1:${Z(F)}:`,activityReconciliation:(F,Q,Y)=>`actrec:v1:${Z(F)}:${Z(Q)}:${Y}`,eventPrefix:(F)=>`ev:${Z(F)}:`,event:(F,Q)=>`ev:${Z(F)}:${String(Q).padStart(10,"0")}`,eventHead:(F)=>`ev:${Z(F)}:head`,eventWatermark:(F)=>`ev:${Z(F)}:watermark`,fleetEventPrefix:()=>"fleet-event:",fleetEvent:(F)=>`fleet-event:${String(F).padStart(10,"0")}`,fleetEventTail:()=>"fleet-event-tail",fleetEventByWorkflowPrefix:(F)=>`fleet-event-by-workflow:${Z(F)}:`,fleetEventByWorkflow:(F,Q)=>`fleet-event-by-workflow:${Z(F)}:${String(Q).padStart(10,"0")}`,signal:(F,Q,Y)=>S(F,Q,Y,l),startSignal:(F,Q,Y)=>S(F,Q,Y,f),signalSequence:(F)=>`sigseq:v1:${Z(F)}`,signalAcceptedResponsePrefix:(F)=>`sigres:v1:${Z(F)}:`,signalAcceptedResponse:(F,Q,Y)=>`sigres:v1:${Z(F)}:${Z(Q)}:${Z(Y)}`,deadline:(F,Q)=>`wf-deadline:${J(F)}:${Z(Q)}`,terminalCleanup:(F,Q)=>`wf-cleanup:${J(F)}:${Z(Q)}`,teardownTimer:(F,Q)=>`wf-teardown:${J(F)}:${Z(Q)}`,delayedStart:(F,Q)=>`wf-delayed:${J(F)}:${Z(Q)}`,terminalWorkflowPrefix:()=>"wf-terminal:",terminalWorkflow:(F,Q)=>`wf-terminal:${J(F)}:${Z(Q)}`,attribute:(F)=>`attr:${Z(F)}`,attributeIndex:(F,Q,Y)=>`idx:${F}:${Q}:${Z(Y)}`,tagIndex:(F,Q)=>`tag:${Z(F)}:${Z(Q)}`,updatePrefix:(F)=>`upd:${Z(F)}:`,update:(F,Q)=>`upd:${Z(F)}:${Q}`,updateResponse:(F)=>`upr:${F}`,updateIdempotency:(F,Q)=>`upk:${Z(F)}:${Q}`,startIdempotency:(F)=>`start-idem:${Z(F)}`,startIdempotencySignalId:(F)=>`start-idem:${F}`,livenessPrefix:()=>"liveness:",liveness:(F)=>`liveness:${Z(F)}`,leasePrefix:()=>"lease:",leaseEpoch:()=>"lease:epoch",leaseHolder:()=>"lease:holder",...O,budget:(F,Q,Y)=>`budget:${F}:${Q}:${Y}`,review:(F,Q)=>`review:${Z(F)}:${Q}`,workflowHeaders:(F)=>`wf-headers:${Z(F)}`,childCancellationPrefix:(F)=>`child-cancel:${Z(F)}:`,childCancellation:(F,Q)=>`child-cancel:${Z(F)}:${Z(Q)}`,childWorkflowByParentPrefix:(F,Q)=>`child-by-parent:${Z(F)}:${Q===void 0?"":`${Z(Q)}:`}`,childWorkflowByParent:(F,Q,Y)=>`child-by-parent:${Z(F)}:${Q===void 0?"":`${Z(Q)}:`}${Z(Y)}`,terminalCleanupNeeded:(F)=>`wf-cleanup-needed:${Z(F)}`,workflowConcurrency:(F,Q)=>`wf-concurrency:${Z(F)}:${Z(Q)}`,workflowConcurrencyHolder:(F)=>`wf-concurrency-holder:${Z(F)}`,workflowHasServices:(F)=>`wf-has-services:${Z(F)}`,finalizerState:(F)=>`wf-finalizer-state:${Z(F)}`,teardownOwed:(F)=>`wf-teardown-needed:${Z(F)}`,teardownSucceeded:(F)=>`wf-teardown-succeeded:${Z(F)}`,teardownDeadLetter:(F)=>`wf-teardown-deadletter:${Z(F)}`,offload:(F,Q)=>`offload:${Z(F)}:${Q}`,archive:(F,Q)=>`archive:${Z(F)}:${Q}`,stateExecution:(F,Q)=>`state:execution:${Z(F)}:${Z(Q)}`,stateWorkflow:(F,Q)=>`state:workflow-scope:${K}:${Z(F)}:${Z(Q)}`,streamChunkPrefix:(F,Q)=>`blob:${Z(F)}:${Q}:chunk:`,streamChunk:(F,Q,Y)=>`blob:${Z(F)}:${Q}:chunk:${String(Y).padStart(10,"0")}`,streamTail:(F,Q)=>`blob:${Z(F)}:${Q}:tail`,streamMetadata:(F,Q)=>`blob:${Z(F)}:${Q}:meta`,budgetCharged:(F)=>`budget-charged:${F}`,toolEffect:(F,Q,Y)=>`tool-effect:${Z(F)}:${Q}:${Y}`,workflowVisibilityStatus:(F,Q)=>`wf-idx-status:${Z(F)}:${Z(Q)}`,workflowVisibilityType:(F,Q)=>`wf-idx-type:${Z(F)}:${Z(Q)}`,workflowVisibilityCreated:(F,Q)=>`wf-idx-created:${J(F)}:${Z(Q)}`,workflowVisibilityUpdated:(F,Q)=>`wf-idx-updated:${J(F)}:${Z(Q)}`,workflowVisibilityDeadline:(F,Q)=>`wf-idx-deadline:${J(F)}:${Z(Q)}`,workflowVisibilityManifest:(F)=>`wf-idx-manifest:${Z(F)}`,workflowVisibilityMetaVersion:()=>"wf-idx-meta:version",workflowVisibilityMetaBuiltAt:()=>"wf-idx-meta:built-at",workflowVisibilityMetaCursor:()=>"wf-idx-meta:cursor"};function d(F){if(F===void 0)return;if(typeof F!=="number"||!Number.isInteger(F)||F<0)throw Error("deleteRange limit must be a finite non-negative integer");return F===0?0:F}function j(F){let Q={},Y=!1;for(let $ of["gt","gte","lt","lte"]){let M=F[$];if(M===void 0)continue;if(typeof M!=="string")throw Error("deleteRange bounds must be strings");Q[$]=M,Y=!0}if(!Y)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let _=d(F.limit);if(_!==void 0)Q.limit=_;return Q}async function I(F,Q,Y){let _=j(Y);if(F.deleteRange)return F.deleteRange(Q,_);return N(F,Q,_)}function p(F,Q){let Y={key:F,open:!1};if(Q.gte!==void 0&&Q.gte>Y.key)Y.key=Q.gte,Y.open=!1;if(Q.gt!==void 0&&Q.gt>=Y.key)Y.key=Q.gt,Y.open=!0;return Y}function a(F,Q){let Y={key:v(F),open:!0};if(Q.lt!==void 0&&Q.lt<=Y.key)Y.key=Q.lt,Y.open=!0;if(Q.lte!==void 0&&Q.lte<Y.key)Y.key=Q.lte,Y.open=!1;return Y}function WF(F,Q){let Y=p(F,Q),_=a(F,Q);if(Y.key>_.key||Y.key===_.key&&(Y.open||_.open))return null;return{lower:Y,upper:_}}function z(F){return F.replaceAll(/:+$/g,"")}function s(F,Q){let Y=z(F),_=z(Q);if(Y.length===0)return _;if(_.length===0)return Y;return`${Y}:${_}`}class A{#F;#Y;constructor(F,Q){this.#F=F,this.#Y=z(Q)}#Q(F){if(this.#Y.length===0)return F;return F.length===0?`${this.#Y}:`:`${this.#Y}:${F}`}#_(F){return F.map((Q)=>{if(Q.type==="put")return{type:"put",key:this.#Q(Q.key),value:Q.value};return{type:"delete",key:this.#Q(Q.key)}})}#$(F){if(this.#Y.length===0)return F;return F.slice(this.#Y.length+1)}#J(F){let Q={};if(F.limit!==void 0)Q.limit=F.limit;if(F.gt!==void 0)Q.gt=this.#Q(F.gt);if(F.gte!==void 0)Q.gte=this.#Q(F.gte);if(F.lt!==void 0)Q.lt=this.#Q(F.lt);if(F.lte!==void 0)Q.lte=this.#Q(F.lte);return Q}#Z(F={}){let Q=this.#J(F);if(F.reverse!==void 0)Q.reverse=F.reverse;return Q}#M(F){return this.#J(F)}capabilities(){return this.#F.capabilities()}scoped(F){return new A(this.#F,s(this.#Y,F))}async get(F){return this.#F.get(this.#Q(F))}async put(F,Q){await this.#F.put(this.#Q(F),Q)}async delete(F){await this.#F.delete(this.#Q(F))}async*scan(F,Q){for await(let[Y,_]of this.#F.scan(this.#Q(F),this.#Z(Q)))yield[this.#$(Y),_]}async batch(F){X("batch operations",F.length),await this.#F.batch(this.#_(F))}async conditionalBatch(F,Q){return c(this.#F,F.map((Y)=>({key:this.#Q(Y.key),expectedValue:Y.expectedValue})),this.#_(Q))}async has(F){return h(this.#F,this.#Q(F))}async deletePrefix(F){return y(this.#F,this.#Q(F))}async deleteRange(F,Q){let Y=this.#M(j(Q));return I(this.#F,this.#Q(F),Y)}async*keys(F,Q){for await(let Y of m(this.#F,this.#Q(F),this.#Z(Q)))yield this.#$(Y)}async count(F){return x(this.#F,this.#Q(F))}[Symbol.dispose](){this.#F[Symbol.dispose]()}}function g(F,Q){return new A(F,Q)}var n=67108864;function u(F){if(F.type==="put")return{type:"put",key:F.key,value:q(F.value)};return{type:"delete",key:F.key}}function i(F){return{key:F.key,expectedValue:F.expectedValue===null?null:q(F.expectedValue)}}function t(F){if(!D(F)||typeof F.key!=="string"||typeof F.value!=="string")throw Error("HTTPStorage scan response contained an invalid NDJSON entry.");return{key:F.key,value:F.value}}function r(F){if(!D(F)||typeof F.applied!=="boolean")throw Error('HTTPStorage conditional batch response must include a boolean "applied" field.');return F.applied}function V(F,Q,Y){if(Y!==void 0)F.searchParams.set(Q,String(Y))}function o(F){if(F.trim().length===0)return null;let Q=t(JSON.parse(F));return[Q.key,C(Q.value)]}class e{#F;#Y;#Q;constructor(F){this.#F=F.baseUrl instanceof URL?F.baseUrl:new URL(F.baseUrl),this.#Y={...F.headers},this.#Q=F.remoteConditionalBatch??!1}capabilities(){return{persistence:"remote",readAfterWrite:"eventual",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:this.#Q,boundedRangeDelete:!1}}#_(F){let Q=this.#F.href.endsWith("/")?this.#F.href:`${this.#F.href}/`;return new URL(F.replace(/^\/+/,""),Q)}#$(F){return this.#_(`/v1/storage/${encodeURIComponent(F)}`)}#J(F,Q){let Y=this.#_("/v1/storage");return Y.searchParams.set("prefix",F),V(Y,"limit",Q.limit),V(Y,"reverse",Q.reverse),V(Y,"gt",Q.gt),V(Y,"gte",Q.gte),V(Y,"lt",Q.lt),V(Y,"lte",Q.lte),Y}async#Z(F,Q={},Y=[]){let _=new Headers(this.#Y);for(let[M,H]of new Headers(Q.headers).entries())_.set(M,H);let $=await fetch(F,{...Q,headers:_});if(!$.ok&&!Y.includes($.status))throw Error(`HTTPStorage request failed: ${Q.method??"GET"} ${F.pathname} returned ${String($.status)}.`);return $}async get(F){let Q=await this.#Z(this.#$(F),{method:"GET"},[404]);if(Q.status===404)return null;return new Uint8Array(await Q.arrayBuffer())}async put(F,Q){await this.#Z(this.#$(F),{method:"PUT",headers:{"content-type":"application/octet-stream"},body:new Blob([Q])})}async delete(F){await this.#Z(this.#$(F),{method:"DELETE"})}async*scan(F,Q={}){let Y=await this.#Z(this.#J(F,Q),{method:"GET",headers:{accept:"application/x-ndjson"}});for await(let _ of T(Y,{maximumBytes:n,sizeLimitError:()=>Error("HTTPStorage scan response exceeded the maximum allowed size.")})){let $=o(_);if($!==null)yield $}}async batch(F){X("batch operations",F.length),await this.#Z(this.#_("/v1/storage/-/batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({operations:F.map(u)})})}async conditionalBatch(F,Q){X("conditionalBatch conditions",F.length),X("conditionalBatch operations",Q.length);let Y=await this.#Z(this.#_("/v1/storage/-/conditional-batch"),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({conditions:F.map(i),operations:Q.map(u)})});return r(await Y.json())}has(F){return L(this,F)}async*keys(F,Q){yield*G(this,F,Q)}count(F){return U(this,F)}deletePrefix(F){return E(this,F)}deleteRange(F,Q){return N(this,F,j(Q))}scoped(F){return g(this,F)}[Symbol.dispose](){}}export{e as HTTPStorage};
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export { FAULT_CODE_TO_FAILURE_CATEGORY, failureCategoryForFaultCode, isFaultCod
|
|
|
22
22
|
export type { FaultCode } from './core/fault-code.ts';
|
|
23
23
|
export { DurableActivityScopeError, DurableActivityUnsupportedError, durableActivity, } from './core/context/durable-activity.ts';
|
|
24
24
|
export { ActivityReconciliationCapabilityError, ActivityReconciliationConflictError, ActivityReconciliationIndeterminateError, ActivityResolutionError, AsyncActivityTokenNotFoundError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, ENGINE_LEASE_LOST_WARNING_NAME, ENGINE_LEASE_SYNCHRONOUS_DISPOSE_WARNING_NAME, Engine, EngineCreateNameMismatchError, EngineDisposalError, EngineDisposedError, EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, IdempotencyKeyPurgedError, PersistedDataIncompatibleError, ScheduleHandle, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowHandle, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './core/engine';
|
|
25
|
-
export
|
|
25
|
+
export { OwnershipModeMismatchError, WORKFLOW_CLAIM_LOST_WARNING_NAME, WORKFLOW_WAKE_DISCARDED_WARNING_NAME, WeftWorkflowClaimLostWarning, WeftWorkflowWakeDiscardedWarning, WorkflowClaimUnavailableError, } from './core/engine';
|
|
26
|
+
export type { EngineCreateOptions, EngineLeaseHealth, EngineStateNamespace, LeaseLostReason, RecoverAllOptions, RecoveredWorkflowInfo, WorkflowWakeKind, } from './core/engine';
|
|
26
27
|
export { DEFAULT_CHECKPOINT_SIZE_WARNING_THRESHOLD, DEFAULT_MAX_NESTING_DEPTH, DEFAULT_POLL_INTERVAL_MS, DEFAULT_RETRY_POLICY, DEFAULT_VISIBILITY_TIMEOUT_MS, HISTORY_CIRCUIT_BREAKER_REASON, WorkflowBuilderError, query, schedule, signal, update, workflow, } from './core/types';
|
|
27
28
|
export type { ActivityArgsFor, ActivityCallOptions, ActivityCallable, ActivityContext, ActivityDefinition, ActivityEntryInput, ActivityFunction, ActivityMap, ActivityMapInput, ActivityObjectInput, ActivityResultFor, ActivityVerificationContext, ActivityVerificationPhase, ActivityVerificationResult, AnyActivityDefinition, AnyWorkflowDefinition, ArchiveAdapter, BuilderState, BuiltWorkflowDefinition, BulkCancelResult, BulkDeleteResult, BulkOperationAction, BulkOperationAuditEvent, BulkOperationCommitOptions, BulkOperationDryRunOptions, BulkOperationDryRunResult, BulkOperationError, BulkOperationFilterSummary, BulkOperationOptions, BulkOperationPrincipal, BulkOperationScopeSummary, BulkRetryFailedResult, BulkSignalAllCommitOptions, BulkSignalAllDryRunOptions, BulkSignalAllOptions, BulkSignalResult, BulkTagResult, Checkpoint, CheckpointState, CheckpointSummary, CompletedReviewEntry, CoordinatedUpdateResult, DefinitionSchema, Duration, EngineOptions, FailureCategory, ForkLineage, ForkOptions, HistoryPolicy, InferActivityEntries, InferActivityEntry, InferWorkflowEntries, InferWorkflowEntry, InitialBuilderState, LaunchMetadata, ListFilter, ListOptions, MarkBuilderState, NormalizeActivities, NormalizedActivityEntry, NormalizedRetentionPolicy, PaginatedResult, PayloadSizePolicy, PendingAsyncActivityInfo, PendingAsyncActivityListOptions, PendingAsyncActivityPage, PendingReviewEntry, PurgeResult, QueryDefinition, QueryMap, QueryShape, RegisteredWorkflowDefinition, RestartLineage, RetentionOverview, RetentionPolicy, RetryPolicy, ReviewDecision, ReviewListEntry, ReviewListFilter, ReviewStatus, ScheduleDefinition, ScheduleFilter, ScheduleOptions, ScheduleOverlapPolicy, ScheduleQueuedRun, ScheduleSpec, ScheduleState, ScheduleStatus, ScheduleSummary, ScheduleUpdateOptions, SearchAttributeDefinition, SearchAttributeHandle, SearchAttributeSchema, SearchAttributeValue, Serializer, SignalDefinition, SignalDeliveryOptions, SignalMap, SignalPayload, StartOptions, StartOrSignalOptions, StartOrSignalSignal, SubmitReviewOptions, TerminationReason, UpdateDefinition, UpdateMap, UpdatePayload, WorkerReplayOperationFailure, WorkerReplayOperationSignature, WorkflowAlreadyRegistered, WorkflowAtomicState, WorkflowAtomicStateOptions, WorkflowBuilder, WorkflowBuilderOptions, WorkflowConcurrencyOptions, WorkflowContext, WorkflowDefinition, WorkflowEvent, WorkflowFinalizerStatus, WorkflowFunction, WorkflowGenerator, WorkflowId, WorkflowKeyedRaceResult, WorkflowLogLevel, WorkflowLogRecord, WorkflowLogger, WorkflowRegistry, WorkflowReplay, WorkflowScheduleProvenance, WorkflowServicesResolution, WorkflowServicesResolverInfo, WorkflowServicesResolverLaunchOptions, WorkflowServicesResolverScheduleInfo, WorkflowSessionState, WorkflowSnapshot, WorkflowState, WorkflowStateNamespace, WorkflowStatus, WorkflowSummary, WorkflowTimelineEntry, WorkflowTimelineOperationDetail, WorkflowTimelineStatus, WorkflowTypeRetentionPolicy, } from './core/types';
|
|
28
29
|
export { AlertManager } from './alerting/index';
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,14 @@ export {
|
|
|
46
46
|
WorkflowTeardownPendingError,
|
|
47
47
|
WorkflowTypeNotRegisteredForRecoveryError
|
|
48
48
|
} from "./core/engine.js";
|
|
49
|
+
export {
|
|
50
|
+
OwnershipModeMismatchError,
|
|
51
|
+
WORKFLOW_CLAIM_LOST_WARNING_NAME,
|
|
52
|
+
WORKFLOW_WAKE_DISCARDED_WARNING_NAME,
|
|
53
|
+
WeftWorkflowClaimLostWarning,
|
|
54
|
+
WeftWorkflowWakeDiscardedWarning,
|
|
55
|
+
WorkflowClaimUnavailableError
|
|
56
|
+
} from "./core/engine.js";
|
|
49
57
|
export {
|
|
50
58
|
DEFAULT_CHECKPOINT_SIZE_WARNING_THRESHOLD,
|
|
51
59
|
DEFAULT_MAX_NESTING_DEPTH,
|
package/dist/indexeddb.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
async function O(G,J){return await G.get(J)!==null}async function*T(G,J,Q){for await(let[X]of G.scan(J,Q))yield X}async function R(G,J){let Q=0;for await(let X of T(G,J))Q++;return Q}async function h(G,J){let Q=[];for await(let X of T(G,J))Q.push({type:"delete",key:X});if(Q.length===0)return 0;return await G.batch(Q),Q.length}async function v(G,J,Q){let X=[];for await(let Y of T(G,J,Q))X.push({type:"delete",key:Y});if(X.length===0)return 0;return await G.batch(X),X.length}function E(G,J,Q){if(!G.capabilities()[J])throw Error(`Feature "${Q}" requires storage capability "${J}", but this storage backend does not provide it.`)}var P=1e4;class b extends Error{code="StorageBatchOperationLimitExceededError";cap=P;count;target;constructor(G,J){super(`${G} count ${J} exceeds MAX_BATCH_OPERATIONS (${P}).`);this.name="StorageBatchOperationLimitExceededError",this.target=G,this.count=J}}function W(G,J){if(J>P)throw new b(G,J)}function M(G){return G.length>0?G.slice(0,-1)+String.fromCharCode(G.charCodeAt(G.length-1)+1):"ÿ"}function m(G,J={}){if(J.gt!==void 0&&G<=J.gt)return!1;if(J.gte!==void 0&&G<J.gte)return!1;if(J.lt!==void 0&&G>=J.lt)return!1;if(J.lte!==void 0&&G>J.lte)return!1;return!0}function x(G,J){if(G===null||J===null)return G===J;if(G.byteLength!==J.byteLength)return!1;for(let Q=0;Q<G.byteLength;Q++)if(G[Q]!==J[Q])return!1;return!0}async function y(G,J){if(G.has)return G.has(J);return O(G,J)}function I(G,J,Q){if(G.keys)return G.keys(J,Q);return T(G,J,Q)}async function g(G,J){if(G.count)return G.count(J);return R(G,J)}async function k(G,J){if(G.deletePrefix)return G.deletePrefix(J);return h(G,J)}async function c(G,J,Q){if(W("conditionalBatch conditions",J.length),W("conditionalBatch operations",Q.length),E(G,"conditionalBatch","storageConditionalBatch"),!G.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return G.conditionalBatch(J,Q)}function d(G){if(G===void 0)return;if(typeof G!=="number"||!Number.isInteger(G)||G<0)throw Error("deleteRange limit must be a finite non-negative integer");return G===0?0:G}function A(G){let J={},Q=!1;for(let Y of["gt","gte","lt","lte"]){let Z=G[Y];if(Z===void 0)continue;if(typeof Z!=="string")throw Error("deleteRange bounds must be strings");J[Y]=Z,Q=!0}if(!Q)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let X=d(G.limit);if(X!==void 0)J.limit=X;return J}async function u(G,J,Q){let X=A(Q);if(G.deleteRange)return G.deleteRange(J,X);return v(G,J,X)}function a(G,J){let Q={key:G,open:!1};if(J.gte!==void 0&&J.gte>Q.key)Q.key=J.gte,Q.open=!1;if(J.gt!==void 0&&J.gt>=Q.key)Q.key=J.gt,Q.open=!0;return Q}function s(G,J){let Q={key:M(G),open:!0};if(J.lt!==void 0&&J.lt<=Q.key)Q.key=J.lt,Q.open=!0;if(J.lte!==void 0&&J.lte<Q.key)Q.key=J.lte,Q.open=!1;return Q}function w(G,J){let Q=a(G,J),X=s(G,J);if(Q.key>X.key||Q.key===X.key&&(Q.open||X.open))return null;return{lower:Q,upper:X}}function q(G){return G.replaceAll(/:+$/g,"")}function n(G,J){let Q=q(G),X=q(J);if(Q.length===0)return X;if(X.length===0)return Q;return`${Q}:${X}`}class C{#J;#Q;constructor(G,J){this.#J=G,this.#Q=q(J)}#G(G){if(this.#Q.length===0)return G;return G.length===0?`${this.#Q}:`:`${this.#Q}:${G}`}#X(G){return G.map((J)=>{if(J.type==="put")return{type:"put",key:this.#G(J.key),value:J.value};return{type:"delete",key:this.#G(J.key)}})}#Y(G){if(this.#Q.length===0)return G;return G.slice(this.#Q.length+1)}#Z(G){let J={};if(G.limit!==void 0)J.limit=G.limit;if(G.gt!==void 0)J.gt=this.#G(G.gt);if(G.gte!==void 0)J.gte=this.#G(G.gte);if(G.lt!==void 0)J.lt=this.#G(G.lt);if(G.lte!==void 0)J.lte=this.#G(G.lte);return J}#$(G={}){let J=this.#Z(G);if(G.reverse!==void 0)J.reverse=G.reverse;return J}#U(G){return this.#Z(G)}capabilities(){return this.#J.capabilities()}scoped(G){return new C(this.#J,n(this.#Q,G))}async get(G){return this.#J.get(this.#G(G))}async put(G,J){await this.#J.put(this.#G(G),J)}async delete(G){await this.#J.delete(this.#G(G))}async*scan(G,J){for await(let[Q,X]of this.#J.scan(this.#G(G),this.#$(J)))yield[this.#Y(Q),X]}async batch(G){W("batch operations",G.length),await this.#J.batch(this.#X(G))}async conditionalBatch(G,J){return c(this.#J,G.map((Q)=>({key:this.#G(Q.key),expectedValue:Q.expectedValue})),this.#X(J))}async has(G){return y(this.#J,this.#G(G))}async deletePrefix(G){return k(this.#J,this.#G(G))}async deleteRange(G,J){let Q=this.#U(A(J));return u(this.#J,this.#G(G),Q)}async*keys(G,J){for await(let Q of I(this.#J,this.#G(G),this.#$(J)))yield this.#Y(Q)}async count(G){return g(this.#J,this.#G(G))}[Symbol.dispose](){this.#J[Symbol.dispose]()}}function f(G,J){return new C(G,J)}var U="kv";function i(G=globalThis){let{indexedDB:J,IDBKeyRange:Q}=G;if(J===void 0||Q===void 0)throw Error("IndexedDBStorage requires both indexedDB and IDBKeyRange runtime globals.");return{indexedDB:J,IDBKeyRange:Q}}function K(G){return new Promise((J,Q)=>{G.onsuccess=()=>J(G.result),G.onerror=()=>Q(G.error)})}function t(G,J){let Q=null,X=null,Y=null,Z=($,H)=>{let F=$??Error(H);if(X){let L=X;Q=null,X=null,L(F);return}Y=F};return G.onsuccess=()=>{if(!Q)return;let $=Q;Q=null,X=null,$(G.result)},G.onerror=()=>{Z(G.error,"IndexedDB cursor request failed.")},J.onerror=()=>{Z(J.error,"IndexedDB transaction failed.")},J.onabort=()=>{Z(J.error,"IndexedDB transaction aborted.")},()=>{return new Promise(($,H)=>{if(Y){let F=Y;Y=null,H(F);return}if(Q=$,X=H,G.readyState==="done"){let F=Q;Q=null,X=null,F?.(G.result)}})}}async function*l(G,J,Q,X,Y,Z){let{limit:$,reverse:H}=X,F=M(Q),L=J.bound(Q,F,!1,!0),z=H?"prev":"next",B=G.transaction(U,"readonly"),V=B.objectStore(U),D=Y(V,L,z),_=t(D,B),j=0,S=!1;try{let N=await _();while(N){if($!==void 0&&j>=$)break;let p=N.key;if(m(p,X))yield Z(N),j++;N.continue(),N=await _()}S=!0}finally{if(!S)try{B.abort()}catch{}}}class r{#J;#Q=null;#G;#X;constructor(G="weft",J=i()){this.#J=G,this.#X=J,this.#G=this.#Y()}capabilities(){return{persistence:"local",readAfterWrite:"linearizable",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:!0,boundedRangeDelete:!0}}#Y(){let G=this.#X.indexedDB.open(this.#J,1);return G.onupgradeneeded=()=>{let J=G.result;if(!J.objectStoreNames.contains(U))J.createObjectStore(U)},K(G).then((J)=>{return this.#Q=J,J})}async get(G){let X=(await this.#G).transaction(U,"readonly").objectStore(U),Y=await K(X.get(G));return Y===void 0?null:new Uint8Array(Y)}async put(G,J){let Y=(await this.#G).transaction(U,"readwrite").objectStore(U);await K(Y.put(J,G))}async delete(G){let X=(await this.#G).transaction(U,"readwrite").objectStore(U);await K(X.delete(G))}async has(G){let X=(await this.#G).transaction(U,"readonly").objectStore(U);return await K(X.count(G))>0}async deletePrefix(G){let J=await this.#G,Q=M(G),X=this.#X.IDBKeyRange.bound(G,Q,!1,!0);return new Promise((Y,Z)=>{let $=J.transaction(U,"readwrite"),H=$.objectStore(U),F=0,L=H.count(X);L.onsuccess=()=>{F=L.result,H.delete(X)},$.oncomplete=()=>Y(F),$.onerror=()=>Z($.error)})}async deleteRange(G,J){let Q=A(J),X=w(G,Q);if(X===null)return 0;let Y=this.#X.IDBKeyRange.bound(X.lower.key,X.upper.key,X.lower.open,X.upper.open),Z=await this.#G,{limit:$}=Q;return new Promise((H,F)=>{let L=Z.transaction(U,"readwrite"),z=L.objectStore(U),B=0;if($===void 0){let V=z.count(Y);V.onsuccess=()=>{B=V.result,z.delete(Y)}}else{let V=z.openCursor(Y,"next");V.onsuccess=()=>{let D=V.result;if(D===null||B>=$)return;if(D.delete(),B++,B<$)D.continue()}}L.oncomplete=()=>H(B),L.onerror=()=>F(L.error)})}async*scan(G,J={}){let Q=await this.#G;yield*l(Q,this.#X.IDBKeyRange,G,J,(X,Y,Z)=>X.openCursor(Y,Z),(X)=>[X.key,new Uint8Array(X.value)])}async batch(G){if(W("batch operations",G.length),G.length===0)return;let J=await this.#G;return new Promise((Q,X)=>{let Y=J.transaction(U,"readwrite"),Z=Y.objectStore(U);for(let $ of G)if($.type==="put")Z.put($.value,$.key);else Z.delete($.key);Y.oncomplete=()=>Q(),Y.onerror=()=>X(Y.error)})}async conditionalBatch(G,J){W("conditionalBatch conditions",G.length),W("conditionalBatch operations",J.length);let Q=await this.#G;return new Promise((X,Y)=>{let Z=Q.transaction(U,"readwrite"),$=Z.objectStore(U),H=!1,F=!1,L=(V,D)=>{if(H)return;H=!0,Y(V??Error(D))};Z.oncomplete=()=>{if(H)return;H=!0,X(!0)},Z.onerror=()=>{L(Z.error,"IndexedDB conditionalBatch transaction failed.")},Z.onabort=()=>{if(H)return;if(H=!0,F){X(!1);return}Y(Z.error??Error("IndexedDB conditionalBatch transaction aborted."))};let z=()=>{for(let V of J)if(V.type==="put")$.put(V.value,V.key);else $.delete(V.key)},B=(V)=>{if(V>=G.length){z();return}let D=G[V],_=$.get(D.key);_.onsuccess=()=>{let j=_.result,S=j===void 0?null:new Uint8Array(j);if(!x(S,D.expectedValue)){F=!0,Z.abort();return}B(V+1)},_.onerror=()=>{L(_.error,"IndexedDB conditionalBatch condition check failed.")}};B(0)})}async*keys(G,J={}){let Q=await this.#G;yield*l(Q,this.#X.IDBKeyRange,G,J,(X,Y,Z)=>X.openKeyCursor(Y,Z),(X)=>X.key)}async count(G){let J=await this.#G,Q=M(G),Y=J.transaction(U,"readonly").objectStore(U);return K(Y.count(this.#X.IDBKeyRange.bound(G,Q,!1,!0)))}scoped(G){return f(this,G)}[Symbol.dispose](){if(this.#Q)this.#Q.close(),this.#Q=null}}export{r as IndexedDBStorage};
|
|
1
|
+
async function E(U,Y){return await U.get(Y)!==null}async function*P(U,Y,Q){for await(let[Z]of U.scan(Y,Q))yield Z}async function h(U,Y){let Q=0;for await(let Z of P(U,Y))Q++;return Q}async function v(U,Y){let Q=[];for await(let Z of P(U,Y))Q.push({type:"delete",key:Z});if(Q.length===0)return 0;return await U.batch(Q),Q.length}async function b(U,Y,Q){let Z=[];for await(let $ of P(U,Y,Q))Z.push({type:"delete",key:$});if(Z.length===0)return 0;return await U.batch(Z),Z.length}function m(U,Y,Q){if(!U.capabilities()[Y])throw Error(`Feature "${Q}" requires storage capability "${Y}", but this storage backend does not provide it.`)}var x="default";function X(U){return encodeURIComponent(U)}var y={workflowOwnerEpoch:(U)=>`wf-owner-epoch:${X(U)}`,workflowOwnerHolder:(U)=>`wf-owner-holder:${X(U)}`,ownershipModeMarker:()=>"ownership-mode-marker"};var O=1e4;class g extends Error{code="StorageBatchOperationLimitExceededError";cap=O;count;target;constructor(U,Y){super(`${U} count ${Y} exceeds MAX_BATCH_OPERATIONS (${O}).`);this.name="StorageBatchOperationLimitExceededError",this.target=U,this.count=Y}}function z(U,Y){if(Y>O)throw new g(U,Y)}function j(U){return U.length>0?U.slice(0,-1)+String.fromCharCode(U.charCodeAt(U.length-1)+1):"ÿ"}function k(U,Y={}){if(Y.gt!==void 0&&U<=Y.gt)return!1;if(Y.gte!==void 0&&U<Y.gte)return!1;if(Y.lt!==void 0&&U>=Y.lt)return!1;if(Y.lte!==void 0&&U>Y.lte)return!1;return!0}function c(U,Y){if(U===null||Y===null)return U===Y;if(U.byteLength!==Y.byteLength)return!1;for(let Q=0;Q<U.byteLength;Q++)if(U[Q]!==Y[Q])return!1;return!0}async function u(U,Y){if(U.has)return U.has(Y);return E(U,Y)}function w(U,Y,Q){if(U.keys)return U.keys(Y,Q);return P(U,Y,Q)}async function f(U,Y){if(U.count)return U.count(Y);return h(U,Y)}async function l(U,Y){if(U.deletePrefix)return U.deletePrefix(Y);return v(U,Y)}async function p(U,Y,Q){if(z("conditionalBatch conditions",Y.length),z("conditionalBatch operations",Q.length),m(U,"conditionalBatch","storageConditionalBatch"),!U.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return U.conditionalBatch(Y,Q)}var D=(U)=>String(U).padStart(16,"0"),t="0",r="1",I=(U,Y,Q,Z)=>`sig:${X(U)}:${X(Y)}:${Z}:${X(Q)}`,zU={workflow:(U)=>`wf:${X(U)}`,checkpoint:(U)=>`wf:${X(U)}:ckpt`,checkpointHistory:(U,Y)=>`wf:${X(U)}:ckpt:${String(Y).padStart(10,"0")}`,timelinePrefix:(U)=>`wf:${X(U)}:timeline:`,timeline:(U,Y)=>`wf:${X(U)}:timeline:${String(Y).padStart(10,"0")}`,schedule:(U)=>`schedule:${X(U)}`,scheduleTick:(U,Y)=>`schedule-due:${String(U).padStart(16,"0")}:${X(Y)}`,scheduleRun:(U)=>`schedule-run:${X(U)}`,scheduleRunLink:(U)=>`schedule-run-link:${X(U)}`,scheduleRunBySchedulePrefix:(U)=>`schedule-run-by-schedule:${X(U)}:`,scheduleRunBySchedule:(U,Y)=>`schedule-run-by-schedule:${X(U)}:${X(Y)}`,operation:(U,Y,Q)=>`op:${U}:${D(Y)}:${Q}`,operationInflight:(U)=>`op:inflight:${U}`,operationQueued:(U)=>`op:queued:${U}`,operationResolved:(U)=>`op:resolved:${U}`,bulkOperationAuditPrefix:()=>"audit:bulk:",bulkOperationAudit:(U,Y,Q)=>`audit:bulk:${D(U)}:${X(Y)}:${X(Q)}`,operationResolvedByTimePrefix:()=>"op:resolved-by-time:",operationResolvedByTime:(U,Y)=>`op:resolved-by-time:${D(U)}:${X(Y)}`,asyncActivity:(U,Y)=>`async-act:v1:${X(U)}:${X(Y)}`,asyncActivityResolution:(U,Y)=>`async-act:v1:${X(U)}:${X(Y)}:resolution`,activityReconciliationPrefix:(U)=>`actrec:v1:${X(U)}:`,activityReconciliation:(U,Y,Q)=>`actrec:v1:${X(U)}:${X(Y)}:${Q}`,eventPrefix:(U)=>`ev:${X(U)}:`,event:(U,Y)=>`ev:${X(U)}:${String(Y).padStart(10,"0")}`,eventHead:(U)=>`ev:${X(U)}:head`,eventWatermark:(U)=>`ev:${X(U)}:watermark`,fleetEventPrefix:()=>"fleet-event:",fleetEvent:(U)=>`fleet-event:${String(U).padStart(10,"0")}`,fleetEventTail:()=>"fleet-event-tail",fleetEventByWorkflowPrefix:(U)=>`fleet-event-by-workflow:${X(U)}:`,fleetEventByWorkflow:(U,Y)=>`fleet-event-by-workflow:${X(U)}:${String(Y).padStart(10,"0")}`,signal:(U,Y,Q)=>I(U,Y,Q,r),startSignal:(U,Y,Q)=>I(U,Y,Q,t),signalSequence:(U)=>`sigseq:v1:${X(U)}`,signalAcceptedResponsePrefix:(U)=>`sigres:v1:${X(U)}:`,signalAcceptedResponse:(U,Y,Q)=>`sigres:v1:${X(U)}:${X(Y)}:${X(Q)}`,deadline:(U,Y)=>`wf-deadline:${D(U)}:${X(Y)}`,terminalCleanup:(U,Y)=>`wf-cleanup:${D(U)}:${X(Y)}`,teardownTimer:(U,Y)=>`wf-teardown:${D(U)}:${X(Y)}`,delayedStart:(U,Y)=>`wf-delayed:${D(U)}:${X(Y)}`,terminalWorkflowPrefix:()=>"wf-terminal:",terminalWorkflow:(U,Y)=>`wf-terminal:${D(U)}:${X(Y)}`,attribute:(U)=>`attr:${X(U)}`,attributeIndex:(U,Y,Q)=>`idx:${U}:${Y}:${X(Q)}`,tagIndex:(U,Y)=>`tag:${X(U)}:${X(Y)}`,updatePrefix:(U)=>`upd:${X(U)}:`,update:(U,Y)=>`upd:${X(U)}:${Y}`,updateResponse:(U)=>`upr:${U}`,updateIdempotency:(U,Y)=>`upk:${X(U)}:${Y}`,startIdempotency:(U)=>`start-idem:${X(U)}`,startIdempotencySignalId:(U)=>`start-idem:${U}`,livenessPrefix:()=>"liveness:",liveness:(U)=>`liveness:${X(U)}`,leasePrefix:()=>"lease:",leaseEpoch:()=>"lease:epoch",leaseHolder:()=>"lease:holder",...y,budget:(U,Y,Q)=>`budget:${U}:${Y}:${Q}`,review:(U,Y)=>`review:${X(U)}:${Y}`,workflowHeaders:(U)=>`wf-headers:${X(U)}`,childCancellationPrefix:(U)=>`child-cancel:${X(U)}:`,childCancellation:(U,Y)=>`child-cancel:${X(U)}:${X(Y)}`,childWorkflowByParentPrefix:(U,Y)=>`child-by-parent:${X(U)}:${Y===void 0?"":`${X(Y)}:`}`,childWorkflowByParent:(U,Y,Q)=>`child-by-parent:${X(U)}:${Y===void 0?"":`${X(Y)}:`}${X(Q)}`,terminalCleanupNeeded:(U)=>`wf-cleanup-needed:${X(U)}`,workflowConcurrency:(U,Y)=>`wf-concurrency:${X(U)}:${X(Y)}`,workflowConcurrencyHolder:(U)=>`wf-concurrency-holder:${X(U)}`,workflowHasServices:(U)=>`wf-has-services:${X(U)}`,finalizerState:(U)=>`wf-finalizer-state:${X(U)}`,teardownOwed:(U)=>`wf-teardown-needed:${X(U)}`,teardownSucceeded:(U)=>`wf-teardown-succeeded:${X(U)}`,teardownDeadLetter:(U)=>`wf-teardown-deadletter:${X(U)}`,offload:(U,Y)=>`offload:${X(U)}:${Y}`,archive:(U,Y)=>`archive:${X(U)}:${Y}`,stateExecution:(U,Y)=>`state:execution:${X(U)}:${X(Y)}`,stateWorkflow:(U,Y)=>`state:workflow-scope:${x}:${X(U)}:${X(Y)}`,streamChunkPrefix:(U,Y)=>`blob:${X(U)}:${Y}:chunk:`,streamChunk:(U,Y,Q)=>`blob:${X(U)}:${Y}:chunk:${String(Q).padStart(10,"0")}`,streamTail:(U,Y)=>`blob:${X(U)}:${Y}:tail`,streamMetadata:(U,Y)=>`blob:${X(U)}:${Y}:meta`,budgetCharged:(U)=>`budget-charged:${U}`,toolEffect:(U,Y,Q)=>`tool-effect:${X(U)}:${Y}:${Q}`,workflowVisibilityStatus:(U,Y)=>`wf-idx-status:${X(U)}:${X(Y)}`,workflowVisibilityType:(U,Y)=>`wf-idx-type:${X(U)}:${X(Y)}`,workflowVisibilityCreated:(U,Y)=>`wf-idx-created:${D(U)}:${X(Y)}`,workflowVisibilityUpdated:(U,Y)=>`wf-idx-updated:${D(U)}:${X(Y)}`,workflowVisibilityDeadline:(U,Y)=>`wf-idx-deadline:${D(U)}:${X(Y)}`,workflowVisibilityManifest:(U)=>`wf-idx-manifest:${X(U)}`,workflowVisibilityMetaVersion:()=>"wf-idx-meta:version",workflowVisibilityMetaBuiltAt:()=>"wf-idx-meta:built-at",workflowVisibilityMetaCursor:()=>"wf-idx-meta:cursor"};function o(U){if(U===void 0)return;if(typeof U!=="number"||!Number.isInteger(U)||U<0)throw Error("deleteRange limit must be a finite non-negative integer");return U===0?0:U}function S(U){let Y={},Q=!1;for(let $ of["gt","gte","lt","lte"]){let J=U[$];if(J===void 0)continue;if(typeof J!=="string")throw Error("deleteRange bounds must be strings");Y[$]=J,Q=!0}if(!Q)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let Z=o(U.limit);if(Z!==void 0)Y.limit=Z;return Y}async function d(U,Y,Q){let Z=S(Q);if(U.deleteRange)return U.deleteRange(Y,Z);return b(U,Y,Z)}function e(U,Y){let Q={key:U,open:!1};if(Y.gte!==void 0&&Y.gte>Q.key)Q.key=Y.gte,Q.open=!1;if(Y.gt!==void 0&&Y.gt>=Q.key)Q.key=Y.gt,Q.open=!0;return Q}function UU(U,Y){let Q={key:j(U),open:!0};if(Y.lt!==void 0&&Y.lt<=Q.key)Q.key=Y.lt,Q.open=!0;if(Y.lte!==void 0&&Y.lte<Q.key)Q.key=Y.lte,Q.open=!1;return Q}function a(U,Y){let Q=e(U,Y),Z=UU(U,Y);if(Q.key>Z.key||Q.key===Z.key&&(Q.open||Z.open))return null;return{lower:Q,upper:Z}}function C(U){return U.replaceAll(/:+$/g,"")}function YU(U,Y){let Q=C(U),Z=C(Y);if(Q.length===0)return Z;if(Z.length===0)return Q;return`${Q}:${Z}`}class R{#Y;#Q;constructor(U,Y){this.#Y=U,this.#Q=C(Y)}#U(U){if(this.#Q.length===0)return U;return U.length===0?`${this.#Q}:`:`${this.#Q}:${U}`}#X(U){return U.map((Y)=>{if(Y.type==="put")return{type:"put",key:this.#U(Y.key),value:Y.value};return{type:"delete",key:this.#U(Y.key)}})}#Z(U){if(this.#Q.length===0)return U;return U.slice(this.#Q.length+1)}#$(U){let Y={};if(U.limit!==void 0)Y.limit=U.limit;if(U.gt!==void 0)Y.gt=this.#U(U.gt);if(U.gte!==void 0)Y.gte=this.#U(U.gte);if(U.lt!==void 0)Y.lt=this.#U(U.lt);if(U.lte!==void 0)Y.lte=this.#U(U.lte);return Y}#J(U={}){let Y=this.#$(U);if(U.reverse!==void 0)Y.reverse=U.reverse;return Y}#G(U){return this.#$(U)}capabilities(){return this.#Y.capabilities()}scoped(U){return new R(this.#Y,YU(this.#Q,U))}async get(U){return this.#Y.get(this.#U(U))}async put(U,Y){await this.#Y.put(this.#U(U),Y)}async delete(U){await this.#Y.delete(this.#U(U))}async*scan(U,Y){for await(let[Q,Z]of this.#Y.scan(this.#U(U),this.#J(Y)))yield[this.#Z(Q),Z]}async batch(U){z("batch operations",U.length),await this.#Y.batch(this.#X(U))}async conditionalBatch(U,Y){return p(this.#Y,U.map((Q)=>({key:this.#U(Q.key),expectedValue:Q.expectedValue})),this.#X(Y))}async has(U){return u(this.#Y,this.#U(U))}async deletePrefix(U){return l(this.#Y,this.#U(U))}async deleteRange(U,Y){let Q=this.#G(S(Y));return d(this.#Y,this.#U(U),Q)}async*keys(U,Y){for await(let Q of w(this.#Y,this.#U(U),this.#J(Y)))yield this.#Z(Q)}async count(U){return f(this.#Y,this.#U(U))}[Symbol.dispose](){this.#Y[Symbol.dispose]()}}function s(U,Y){return new R(U,Y)}var F="kv";function QU(U=globalThis){let{indexedDB:Y,IDBKeyRange:Q}=U;if(Y===void 0||Q===void 0)throw Error("IndexedDBStorage requires both indexedDB and IDBKeyRange runtime globals.");return{indexedDB:Y,IDBKeyRange:Q}}function N(U){return new Promise((Y,Q)=>{U.onsuccess=()=>Y(U.result),U.onerror=()=>Q(U.error)})}function XU(U,Y){let Q=null,Z=null,$=null,J=(G,H)=>{let V=G??Error(H);if(Z){let B=Z;Q=null,Z=null,B(V);return}$=V};return U.onsuccess=()=>{if(!Q)return;let G=Q;Q=null,Z=null,G(U.result)},U.onerror=()=>{J(U.error,"IndexedDB cursor request failed.")},Y.onerror=()=>{J(Y.error,"IndexedDB transaction failed.")},Y.onabort=()=>{J(Y.error,"IndexedDB transaction aborted.")},()=>{return new Promise((G,H)=>{if($){let V=$;$=null,H(V);return}if(Q=G,Z=H,U.readyState==="done"){let V=Q;Q=null,Z=null,V?.(U.result)}})}}async function*n(U,Y,Q,Z,$,J){let{limit:G,reverse:H}=Z,V=j(Q),B=Y.bound(Q,V,!1,!0),M=H?"prev":"next",W=U.transaction(F,"readonly"),L=W.objectStore(F),_=$(L,B,M),K=XU(_,W),T=0,q=!1;try{let A=await K();while(A){if(G!==void 0&&T>=G)break;let i=A.key;if(k(i,Z))yield J(A),T++;A.continue(),A=await K()}q=!0}finally{if(!q)try{W.abort()}catch{}}}class ZU{#Y;#Q=null;#U;#X;constructor(U="weft",Y=QU()){this.#Y=U,this.#X=Y,this.#U=this.#Z()}capabilities(){return{persistence:"local",readAfterWrite:"linearizable",scanConsistency:"best-effort",atomicBatch:!0,conditionalBatch:!0,boundedRangeDelete:!0}}#Z(){let U=this.#X.indexedDB.open(this.#Y,1);return U.onupgradeneeded=()=>{let Y=U.result;if(!Y.objectStoreNames.contains(F))Y.createObjectStore(F)},N(U).then((Y)=>{return this.#Q=Y,Y})}async get(U){let Z=(await this.#U).transaction(F,"readonly").objectStore(F),$=await N(Z.get(U));return $===void 0?null:new Uint8Array($)}async put(U,Y){let $=(await this.#U).transaction(F,"readwrite").objectStore(F);await N($.put(Y,U))}async delete(U){let Z=(await this.#U).transaction(F,"readwrite").objectStore(F);await N(Z.delete(U))}async has(U){let Z=(await this.#U).transaction(F,"readonly").objectStore(F);return await N(Z.count(U))>0}async deletePrefix(U){let Y=await this.#U,Q=j(U),Z=this.#X.IDBKeyRange.bound(U,Q,!1,!0);return new Promise(($,J)=>{let G=Y.transaction(F,"readwrite"),H=G.objectStore(F),V=0,B=H.count(Z);B.onsuccess=()=>{V=B.result,H.delete(Z)},G.oncomplete=()=>$(V),G.onerror=()=>J(G.error)})}async deleteRange(U,Y){let Q=S(Y),Z=a(U,Q);if(Z===null)return 0;let $=this.#X.IDBKeyRange.bound(Z.lower.key,Z.upper.key,Z.lower.open,Z.upper.open),J=await this.#U,{limit:G}=Q;return new Promise((H,V)=>{let B=J.transaction(F,"readwrite"),M=B.objectStore(F),W=0;if(G===void 0){let L=M.count($);L.onsuccess=()=>{W=L.result,M.delete($)}}else{let L=M.openCursor($,"next");L.onsuccess=()=>{let _=L.result;if(_===null||W>=G)return;if(_.delete(),W++,W<G)_.continue()}}B.oncomplete=()=>H(W),B.onerror=()=>V(B.error)})}async*scan(U,Y={}){let Q=await this.#U;yield*n(Q,this.#X.IDBKeyRange,U,Y,(Z,$,J)=>Z.openCursor($,J),(Z)=>[Z.key,new Uint8Array(Z.value)])}async batch(U){if(z("batch operations",U.length),U.length===0)return;let Y=await this.#U;return new Promise((Q,Z)=>{let $=Y.transaction(F,"readwrite"),J=$.objectStore(F);for(let G of U)if(G.type==="put")J.put(G.value,G.key);else J.delete(G.key);$.oncomplete=()=>Q(),$.onerror=()=>Z($.error)})}async conditionalBatch(U,Y){z("conditionalBatch conditions",U.length),z("conditionalBatch operations",Y.length);let Q=await this.#U;return new Promise((Z,$)=>{let J=Q.transaction(F,"readwrite"),G=J.objectStore(F),H=!1,V=!1,B=(L,_)=>{if(H)return;H=!0,$(L??Error(_))};J.oncomplete=()=>{if(H)return;H=!0,Z(!0)},J.onerror=()=>{B(J.error,"IndexedDB conditionalBatch transaction failed.")},J.onabort=()=>{if(H)return;if(H=!0,V){Z(!1);return}$(J.error??Error("IndexedDB conditionalBatch transaction aborted."))};let M=()=>{for(let L of Y)if(L.type==="put")G.put(L.value,L.key);else G.delete(L.key)},W=(L)=>{if(L>=U.length){M();return}let _=U[L],K=G.get(_.key);K.onsuccess=()=>{let T=K.result,q=T===void 0?null:new Uint8Array(T);if(!c(q,_.expectedValue)){V=!0,J.abort();return}W(L+1)},K.onerror=()=>{B(K.error,"IndexedDB conditionalBatch condition check failed.")}};W(0)})}async*keys(U,Y={}){let Q=await this.#U;yield*n(Q,this.#X.IDBKeyRange,U,Y,(Z,$,J)=>Z.openKeyCursor($,J),(Z)=>Z.key)}async count(U){let Y=await this.#U,Q=j(U),$=Y.transaction(F,"readonly").objectStore(F);return N($.count(this.#X.IDBKeyRange.bound(U,Q,!1,!0)))}scoped(U){return s(this,U)}[Symbol.dispose](){if(this.#Q)this.#Q.close(),this.#Q=null}}export{ZU as IndexedDBStorage};
|