@effect-app/infra 4.0.0-beta.254 → 4.0.0-beta.255
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/CHANGELOG.md +7 -0
- package/dist/CUPS.d.ts +2 -2
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/WorkflowEngineCosmos.d.ts +28 -0
- package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
- package/dist/WorkflowEngineCosmos.js +449 -0
- package/package.json +5 -5
- package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
package/CHANGELOG.md
CHANGED
package/dist/CUPS.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import * as Effect from "effect-app/Effect";
|
|
|
5
5
|
import * as Layer from "effect-app/Layer";
|
|
6
6
|
import * as Option from "effect-app/Option";
|
|
7
7
|
import * as S from "effect-app/Schema";
|
|
8
|
-
export declare const PrinterId: S.
|
|
8
|
+
export declare const PrinterId: S.NonEmptyString255Schema;
|
|
9
9
|
export type PrinterId = S.NonEmptyString255;
|
|
10
10
|
declare const CUPSError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
11
11
|
readonly _tag: "CUPSError";
|
|
@@ -54,4 +54,4 @@ export declare class CUPS extends CUPS_base {
|
|
|
54
54
|
static readonly Fake: Layer.Layer<CUPS, never, never>;
|
|
55
55
|
}
|
|
56
56
|
export {};
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
57
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ1VQUy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL0NVUFMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssV0FBVyxFQUFZLE1BQU0sNEJBQTRCLENBQUE7QUFFdkUsT0FBTyxLQUFLLE1BQU0sTUFBTSxtQkFBbUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFBO0FBQzdDLE9BQU8sS0FBSyxNQUFNLE1BQU0sbUJBQW1CLENBQUE7QUFDM0MsT0FBTyxLQUFLLEtBQUssTUFBTSxrQkFBa0IsQ0FBQTtBQUN6QyxPQUFPLEtBQUssTUFBTSxNQUFNLG1CQUFtQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxDQUFDLE1BQU0sbUJBQW1CLENBQUE7QUFVdEMsZUFBTyxNQUFNLFNBQVMsMkJBQXNCLENBQUE7QUFDNUMsTUFBTSxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsaUJBQWlCLENBQUE7Ozs7QUFXM0MscUJBQWEsU0FBVSxTQUFRLGVBQThCO0lBQzNELFFBQVEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFBO0lBQ3hCLFFBQVEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFBO0lBQ3hCLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sR0FBRyxTQUFTLENBQUE7SUFDMUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsT0FBTyxHQUFHLElBQUksR0FBRyxTQUFTLENBQUE7SUFDbEQsUUFBUSxDQUFDLE1BQU0sRUFBRSxPQUFPLEdBQUcsU0FBUyxDQUFBO0lBQ3BDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLFNBQVMsQ0FBQTtJQUNuQyxRQUFRLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxTQUFTLENBQUE7SUFDbkMsUUFBUSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUE7Q0FDeEIsQ0FBQztDQUFHO0FBcURMLGVBQU8sTUFBTSxjQUFjLG1DQVV6QixDQUFBO0FBR0YsZUFBTyxNQUFNLG9CQUFvQixvVUFBNEIsQ0FBQTtBQUM3RCxlQUFPLE1BQU0sK0JBQStCLFdBQVksV0FBVyxZQUFZLFdBQVcsNkZBQ3RDLENBQUE7QUF5QnBELGVBQU8sTUFBTSxVQUFVOztFQVFyQixDQUFBOztvQkFNeUIsV0FBVyxhQUFhLFNBQVMsY0FBYyxNQUFNLEVBQUU7Ozs7MEJBU3RELE1BQU0sYUFBYSxTQUFTLGNBQWMsTUFBTSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFiOUUscUJBQWEsSUFBSyxTQUFRLFNBcUJ4QjtJQUNBLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxrQ0ErQm5CO0NBQ0YifQ==
|
package/dist/CUPS.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CUPS.d.ts","sourceRoot":"","sources":["../src/CUPS.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AAEvE,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,CAAC,MAAM,mBAAmB,CAAA;AAUtC,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"CUPS.d.ts","sourceRoot":"","sources":["../src/CUPS.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAY,MAAM,4BAA4B,CAAA;AAEvE,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAA;AAC3C,OAAO,KAAK,CAAC,MAAM,mBAAmB,CAAA;AAUtC,eAAO,MAAM,SAAS,2BAAsB,CAAA;AAC5C,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,iBAAiB,CAAA;;;;AAW3C,qBAAa,SAAU,SAAQ,eAA8B;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CACxB,CAAC;CAAG;AAqDL,eAAO,MAAM,cAAc,mCAUzB,CAAA;AAGF,eAAO,MAAM,oBAAoB,oUAA4B,CAAA;AAC7D,eAAO,MAAM,+BAA+B,WAAY,WAAW,YAAY,WAAW,6FACtC,CAAA;AAyBpD,eAAO,MAAM,UAAU;;EAQrB,CAAA;;oBAMyB,WAAW,aAAa,SAAS,cAAc,MAAM,EAAE;;;;0BAStD,MAAM,aAAa,SAAS,cAAc,MAAM,EAAE;;;;;;;;;;;;;;;;;;AAb9E,qBAAa,IAAK,SAAQ,SAqBxB;IACA,MAAM,CAAC,QAAQ,CAAC,IAAI,kCA+BnB;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Layer from "effect-app/Layer";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
3
|
+
import * as Redacted from "effect/Redacted";
|
|
4
|
+
import { WorkflowEngine } from "effect/unstable/workflow/WorkflowEngine";
|
|
5
|
+
export interface WorkflowEngineCosmosConfig {
|
|
6
|
+
readonly url: Redacted.Redacted<string>;
|
|
7
|
+
readonly dbName: string;
|
|
8
|
+
readonly prefix?: string;
|
|
9
|
+
/** Lease duration before claim considered stale. Default 30s. */
|
|
10
|
+
readonly leaseTtl?: Duration.Duration;
|
|
11
|
+
/** Renewal cadence — should be < leaseTtl. Default 10s. */
|
|
12
|
+
readonly heartbeatInterval?: Duration.Duration;
|
|
13
|
+
/** Cadence for scanning stale leases. Default 15s. Set to `Duration.zero` to disable. */
|
|
14
|
+
readonly recoveryInterval?: Duration.Duration;
|
|
15
|
+
/** Cadence for scanning due clocks. Default 5s. Set to `Duration.zero` to disable. */
|
|
16
|
+
readonly clockPollInterval?: Duration.Duration;
|
|
17
|
+
/** Stable worker identity; defaults to a random UUID per process. */
|
|
18
|
+
readonly workerId?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Cosmos DB backed `WorkflowEngine` layer.
|
|
22
|
+
*
|
|
23
|
+
* Per-execution writes use TransactionalBatch (same partition key) and OCC
|
|
24
|
+
* via `_etag`/IfMatch, giving first-writer-wins semantics for activity
|
|
25
|
+
* results, durable-deferred completions, and exec-state transitions.
|
|
26
|
+
*/
|
|
27
|
+
export declare const layerCosmos: (cfg: WorkflowEngineCosmosConfig) => Layer.Layer<WorkflowEngine>;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV29ya2Zsb3dFbmdpbmVDb3Ntb3MuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9Xb3JrZmxvd0VuZ2luZUNvc21vcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFzQkEsT0FBTyxLQUFLLEtBQUssTUFBTSxrQkFBa0IsQ0FBQTtBQUd6QyxPQUFPLEtBQUssUUFBUSxNQUFNLGlCQUFpQixDQUFBO0FBSTNDLE9BQU8sS0FBSyxRQUFRLE1BQU0saUJBQWlCLENBQUE7QUFJM0MsT0FBTyxFQUE0QixjQUFjLEVBQW9CLE1BQU0seUNBQXlDLENBQUE7QUFNcEgsTUFBTSxXQUFXLDBCQUEwQjtJQUN6QyxRQUFRLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDdkMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUE7SUFDdkIsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQTtJQUN4QixpRUFBaUU7SUFDakUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUE7SUFDckMsMkRBQTJEO0lBQzNELFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUE7SUFDOUMseUZBQXlGO0lBQ3pGLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUE7SUFDN0Msc0ZBQXNGO0lBQ3RGLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUE7SUFDOUMscUVBQXFFO0lBQ3JFLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxNQUFNLENBQUE7Q0FDM0I7QUFzakJEOzs7Ozs7R0FNRztBQUNILGVBQU8sTUFBTSxXQUFXLFFBQVMsMEJBQTBCLEtBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBR1IsQ0FBQSJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowEngineCosmos.d.ts","sourceRoot":"","sources":["../src/WorkflowEngineCosmos.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAA;AAGzC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAI3C,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAI3C,OAAO,EAA4B,cAAc,EAAoB,MAAM,yCAAyC,CAAA;AAMpH,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;IACrC,2DAA2D;IAC3D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;IAC9C,yFAAyF;IACzF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;IAC7C,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAA;IAC9C,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAsjBD;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,QAAS,0BAA0B,KAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAGR,CAAA"}
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cosmos DB backed {@link WorkflowEngine} implementation.
|
|
3
|
+
*
|
|
4
|
+
* Persists workflow state in a single container partitioned by `executionId`
|
|
5
|
+
* so per-execution writes can be issued through Cosmos TransactionalBatch
|
|
6
|
+
* (atomic for ops sharing the same partition key). Optimistic concurrency
|
|
7
|
+
* is enforced with `_etag` + `IfMatch` on Replace operations and with
|
|
8
|
+
* create-only ops in batches for first-writer-wins semantics on activity
|
|
9
|
+
* results and durable-deferred completions.
|
|
10
|
+
*
|
|
11
|
+
* Crash recovery: each driver holds a time-bound lease (`worker` +
|
|
12
|
+
* `leaseExpiresAt`) on the exec doc and renews it via a heartbeat fiber.
|
|
13
|
+
* A scope-bound recovery poller queries for exec docs whose lease has
|
|
14
|
+
* lapsed and re-drives them in the local process, picking up persisted
|
|
15
|
+
* activity results from where the crashed driver left off.
|
|
16
|
+
*
|
|
17
|
+
* Durable clocks: `scheduleClock` writes a clock doc (`fireAt`,
|
|
18
|
+
* `deferredName`) and arms an in-process timer. A cross-partition clock
|
|
19
|
+
* poller fires any clock whose `fireAt` is due, completing the deferred
|
|
20
|
+
* idempotently (via create-only) and deleting the doc. Survives restarts.
|
|
21
|
+
*/
|
|
22
|
+
import * as Effect from "effect-app/Effect";
|
|
23
|
+
import * as Layer from "effect-app/Layer";
|
|
24
|
+
import * as Option from "effect-app/Option";
|
|
25
|
+
import { dropUndefinedT } from "effect-app/utils";
|
|
26
|
+
import * as Duration from "effect/Duration";
|
|
27
|
+
import * as Exit from "effect/Exit";
|
|
28
|
+
import * as Fiber from "effect/Fiber";
|
|
29
|
+
import * as FiberMap from "effect/FiberMap";
|
|
30
|
+
import * as Redacted from "effect/Redacted";
|
|
31
|
+
import * as Schedule from "effect/Schedule";
|
|
32
|
+
import * as Workflow from "effect/unstable/workflow/Workflow";
|
|
33
|
+
import { makeUnsafe, WorkflowEngine, WorkflowInstance } from "effect/unstable/workflow/WorkflowEngine";
|
|
34
|
+
import { randomUUID } from "node:crypto";
|
|
35
|
+
import { CosmosClient, CosmosClientLayer } from "./cosmos-client.js";
|
|
36
|
+
import { OptimisticConcurrencyException } from "./errors.js";
|
|
37
|
+
import { annotateCosmosResponse, annotateDb } from "./otel.js";
|
|
38
|
+
const execId = "exec";
|
|
39
|
+
const activityKey = (name, attempt) => `activity::${name}::${attempt}`;
|
|
40
|
+
const deferredKey = (name) => `deferred::${name}`;
|
|
41
|
+
const clockKey = (name) => `clock::${name}`;
|
|
42
|
+
const isOptimisticStatus = (code) => code === 409 || code === 412 || code === 404;
|
|
43
|
+
const makeCosmosWorkflowEngine = Effect.fnUntraced(function* (cfg) {
|
|
44
|
+
const { db } = yield* CosmosClient;
|
|
45
|
+
const containerId = `${cfg.prefix ?? ""}workflow-engine`;
|
|
46
|
+
yield* Effect.promise(() => db.containers.createIfNotExists({
|
|
47
|
+
id: containerId,
|
|
48
|
+
partitionKey: { paths: ["/_partitionKey"], version: 2 }
|
|
49
|
+
}));
|
|
50
|
+
const container = db.container(containerId);
|
|
51
|
+
const scope = yield* Effect.scope;
|
|
52
|
+
const workerId = cfg.workerId ?? randomUUID();
|
|
53
|
+
const leaseTtl = cfg.leaseTtl ?? Duration.seconds(30);
|
|
54
|
+
const heartbeatInterval = cfg.heartbeatInterval ?? Duration.seconds(10);
|
|
55
|
+
const recoveryInterval = cfg.recoveryInterval ?? Duration.seconds(15);
|
|
56
|
+
const clockPollInterval = cfg.clockPollInterval ?? Duration.seconds(5);
|
|
57
|
+
const annotate = (operation, executionId) => annotateDb({
|
|
58
|
+
operation,
|
|
59
|
+
system: "cosmosdb",
|
|
60
|
+
collection: containerId,
|
|
61
|
+
entity: "workflow",
|
|
62
|
+
extra: executionId !== undefined
|
|
63
|
+
? { "azure.cosmosdb.operation.partition_key": executionId, "app.entity.id": executionId }
|
|
64
|
+
: undefined
|
|
65
|
+
});
|
|
66
|
+
const workflows = new Map();
|
|
67
|
+
const locals = new Map();
|
|
68
|
+
const clocks = yield* FiberMap.make();
|
|
69
|
+
// --- Cosmos primitives -------------------------------------------------
|
|
70
|
+
const readExec = (executionId) => Effect
|
|
71
|
+
.gen(function* () {
|
|
72
|
+
const resp = yield* Effect.promise(() => container.item(execId, executionId).read());
|
|
73
|
+
yield* annotateCosmosResponse({ requestCharge: resp.requestCharge, statusCode: resp.statusCode });
|
|
74
|
+
return Option.fromNullishOr(resp.resource).pipe(Option.map((r) => ({ ...r, _etag: resp.etag })));
|
|
75
|
+
})
|
|
76
|
+
.pipe(annotate("readExec", executionId));
|
|
77
|
+
const replaceExec = (doc) => Effect
|
|
78
|
+
.gen(function* () {
|
|
79
|
+
const resp = yield* Effect.promise(() => container.item(execId, doc._partitionKey).replace(doc, {
|
|
80
|
+
accessCondition: { type: "IfMatch", condition: doc._etag ?? "" }
|
|
81
|
+
}));
|
|
82
|
+
yield* annotateCosmosResponse({ requestCharge: resp.requestCharge, statusCode: resp.statusCode });
|
|
83
|
+
if (isOptimisticStatus(resp.statusCode)) {
|
|
84
|
+
return yield* new OptimisticConcurrencyException({
|
|
85
|
+
type: "workflow.exec",
|
|
86
|
+
id: doc._partitionKey,
|
|
87
|
+
code: resp.statusCode
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return { ...doc, _etag: resp.etag };
|
|
91
|
+
})
|
|
92
|
+
.pipe(annotate("replaceExec", doc._partitionKey));
|
|
93
|
+
// Atomic create-or-noop using a single-op batch — returns true if created.
|
|
94
|
+
const createIfMissing = (body) => Effect.gen(function* () {
|
|
95
|
+
const resp = yield* Effect.promise(() => container.items.batch([{ operationType: "Create", resourceBody: body }], body._partitionKey));
|
|
96
|
+
const r = resp.result?.[0];
|
|
97
|
+
const code = r?.statusCode ?? 0;
|
|
98
|
+
if (code === 201)
|
|
99
|
+
return true;
|
|
100
|
+
if (code === 409)
|
|
101
|
+
return false;
|
|
102
|
+
return yield* Effect.die(new Error(`workflow-engine cosmos createIfMissing for ${body.id} failed: ${code}`));
|
|
103
|
+
});
|
|
104
|
+
const readPoint = (id, executionId) => Effect.promise(() => container.item(id, executionId).read()).pipe(Effect.map((r) => Option.fromNullishOr(r.resource)));
|
|
105
|
+
// --- Workflow result helpers ------------------------------------------
|
|
106
|
+
const completeExit = (state) => state.status === "complete" && state.completedExit
|
|
107
|
+
? Option.some(state.completedExit)
|
|
108
|
+
: Option.none();
|
|
109
|
+
// --- Lease / claim ----------------------------------------------------
|
|
110
|
+
const leaseActive = (state, now) => state.worker !== undefined
|
|
111
|
+
&& state.worker !== workerId
|
|
112
|
+
&& state.leaseExpiresAt !== undefined
|
|
113
|
+
&& Date.parse(state.leaseExpiresAt) > now;
|
|
114
|
+
/**
|
|
115
|
+
* Try to claim a lease on `state`. Returns the updated doc on success, `None`
|
|
116
|
+
* if another worker holds an active lease, or on OCC conflict (caller may
|
|
117
|
+
* retry by re-reading).
|
|
118
|
+
*/
|
|
119
|
+
const tryClaim = (state) => Effect.gen(function* () {
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
if (leaseActive(state, now))
|
|
122
|
+
return Option.none();
|
|
123
|
+
const updated = {
|
|
124
|
+
...state,
|
|
125
|
+
worker: workerId,
|
|
126
|
+
leaseExpiresAt: new Date(now + Duration.toMillis(leaseTtl)).toISOString()
|
|
127
|
+
};
|
|
128
|
+
return yield* replaceExec(updated).pipe(Effect.map(Option.some), Effect.catchTag("OptimisticConcurrencyException", () => Effect.succeed(Option.none())));
|
|
129
|
+
});
|
|
130
|
+
/**
|
|
131
|
+
* Renew lease until the local fiber stops or another worker takes the claim.
|
|
132
|
+
* Best-effort: failures are swallowed; loop simply retries on next tick.
|
|
133
|
+
*/
|
|
134
|
+
const heartbeat = (executionId) => Effect.gen(function* () {
|
|
135
|
+
while (true) {
|
|
136
|
+
yield* Effect.sleep(heartbeatInterval);
|
|
137
|
+
const local = locals.get(executionId);
|
|
138
|
+
const polled = local?.fiber?.pollUnsafe();
|
|
139
|
+
if (!local?.fiber || polled)
|
|
140
|
+
return;
|
|
141
|
+
const cur = yield* readExec(executionId).pipe(Effect.catchCause(() => Effect.succeed(Option.none())));
|
|
142
|
+
if (Option.isNone(cur))
|
|
143
|
+
continue;
|
|
144
|
+
const state = cur.value;
|
|
145
|
+
if (state.status === "complete" || state.worker !== workerId)
|
|
146
|
+
return;
|
|
147
|
+
yield* replaceExec({
|
|
148
|
+
...state,
|
|
149
|
+
leaseExpiresAt: new Date(Date.now() + Duration.toMillis(leaseTtl)).toISOString()
|
|
150
|
+
})
|
|
151
|
+
.pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void), Effect.catchCause(() => Effect.void));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
// --- Drive logic -------------------------------------------------------
|
|
155
|
+
const drive = (executionId, payload, parent, entry) => Effect.gen(function* () {
|
|
156
|
+
let local = locals.get(executionId);
|
|
157
|
+
if (local?.fiber) {
|
|
158
|
+
const polled = local.fiber.pollUnsafe();
|
|
159
|
+
const stillRunning = !polled;
|
|
160
|
+
const completedNotResume = polled && polled._tag === "Success" && polled.value._tag === "Complete";
|
|
161
|
+
if (stillRunning || completedNotResume)
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const stateOpt = yield* readExec(executionId);
|
|
165
|
+
if (Option.isNone(stateOpt) || stateOpt.value.status === "complete")
|
|
166
|
+
return;
|
|
167
|
+
// Best-effort claim: takes lease so recovery poller leaves us alone.
|
|
168
|
+
// Failure is tolerated — local fiber still drives; OCC guards persisted
|
|
169
|
+
// state so split-brain stays correct.
|
|
170
|
+
const claimed = yield* tryClaim(stateOpt.value);
|
|
171
|
+
const state = Option.isSome(claimed) ? claimed.value : stateOpt.value;
|
|
172
|
+
const instance = WorkflowInstance.initial(entry.workflow, executionId);
|
|
173
|
+
instance.interrupted = state.interrupted;
|
|
174
|
+
if (!local) {
|
|
175
|
+
local = { instance, fiber: undefined, parent };
|
|
176
|
+
locals.set(executionId, local);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
local.instance = instance;
|
|
180
|
+
}
|
|
181
|
+
const onComplete = Effect.fnUntraced(function* (result) {
|
|
182
|
+
const current = yield* readExec(executionId);
|
|
183
|
+
if (Option.isNone(current) || current.value.status === "complete")
|
|
184
|
+
return;
|
|
185
|
+
const isComplete = result._tag === "Complete";
|
|
186
|
+
yield* replaceExec({
|
|
187
|
+
...current.value,
|
|
188
|
+
status: isComplete ? "complete" : current.value.status,
|
|
189
|
+
suspended: result._tag === "Suspended",
|
|
190
|
+
interrupted: instance.interrupted,
|
|
191
|
+
completedExit: isComplete ? result : undefined,
|
|
192
|
+
// Release lease on completion so the doc isn't seen as orphaned.
|
|
193
|
+
worker: isComplete ? undefined : current.value.worker,
|
|
194
|
+
leaseExpiresAt: isComplete ? undefined : current.value.leaseExpiresAt
|
|
195
|
+
})
|
|
196
|
+
.pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
|
|
197
|
+
if (parent && isComplete) {
|
|
198
|
+
yield* Effect.forkIn(driveById(parent), scope);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
local.fiber = yield* entry.execute(payload, executionId).pipe(Effect.onExit(() => {
|
|
202
|
+
if (!instance.interrupted)
|
|
203
|
+
return Effect.void;
|
|
204
|
+
instance.suspended = false;
|
|
205
|
+
return Effect.withFiber((fiber) => Effect.interruptible(Fiber.interrupt(fiber)));
|
|
206
|
+
}), Workflow.intoResult, Effect.provideService(WorkflowInstance, instance), Effect.provideService(WorkflowEngine, engine), Effect.tap(onComplete), Effect.forkIn(entry.scope));
|
|
207
|
+
if (Option.isSome(claimed)) {
|
|
208
|
+
yield* Effect.forkIn(heartbeat(executionId), scope);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
const driveById = (executionId) => Effect.gen(function* () {
|
|
212
|
+
const stateOpt = yield* readExec(executionId);
|
|
213
|
+
if (Option.isNone(stateOpt))
|
|
214
|
+
return;
|
|
215
|
+
const state = stateOpt.value;
|
|
216
|
+
const entry = workflows.get(state.workflowName);
|
|
217
|
+
if (!entry)
|
|
218
|
+
return;
|
|
219
|
+
yield* drive(executionId, state.payload, state.parent, entry);
|
|
220
|
+
});
|
|
221
|
+
// --- Clock firing -----------------------------------------------------
|
|
222
|
+
// Persist deferred completion (first-writer-wins via createIfMissing),
|
|
223
|
+
// resume the workflow, then clean up the clock doc.
|
|
224
|
+
const fireClock = (doc) => Effect.gen(function* () {
|
|
225
|
+
const created = yield* createIfMissing({
|
|
226
|
+
id: deferredKey(doc.deferredName),
|
|
227
|
+
_partitionKey: doc._partitionKey,
|
|
228
|
+
type: "deferred",
|
|
229
|
+
exit: Exit.void
|
|
230
|
+
}).pipe(annotate("clockFire", doc._partitionKey));
|
|
231
|
+
if (created)
|
|
232
|
+
yield* driveById(doc._partitionKey);
|
|
233
|
+
yield* Effect.promise(() => container.item(doc.id, doc._partitionKey).delete()).pipe(Effect.catchCause(() => Effect.void));
|
|
234
|
+
});
|
|
235
|
+
// --- Encoded engine ----------------------------------------------------
|
|
236
|
+
const encoded = {
|
|
237
|
+
register: Effect.fnUntraced(function* (workflow, execute) {
|
|
238
|
+
workflows.set(workflow.name, {
|
|
239
|
+
workflow,
|
|
240
|
+
execute,
|
|
241
|
+
scope: yield* Effect.scope
|
|
242
|
+
});
|
|
243
|
+
}),
|
|
244
|
+
execute: Effect.fnUntraced(function* (workflow, options) {
|
|
245
|
+
const entry = workflows.get(workflow.name);
|
|
246
|
+
if (!entry) {
|
|
247
|
+
return yield* Effect.orDie(Effect.fail(`Workflow ${workflow.name} is not registered`));
|
|
248
|
+
}
|
|
249
|
+
const initial = {
|
|
250
|
+
id: execId,
|
|
251
|
+
_partitionKey: options.executionId,
|
|
252
|
+
type: "exec",
|
|
253
|
+
workflowName: workflow.name,
|
|
254
|
+
payload: options.payload,
|
|
255
|
+
parent: options.parent?.executionId,
|
|
256
|
+
status: "running",
|
|
257
|
+
suspended: false,
|
|
258
|
+
interrupted: false
|
|
259
|
+
};
|
|
260
|
+
const created = yield* createIfMissing(initial).pipe(annotate("execute.claim", options.executionId));
|
|
261
|
+
if (created || !locals.has(options.executionId)) {
|
|
262
|
+
yield* drive(options.executionId, options.payload, options.parent?.executionId, entry);
|
|
263
|
+
}
|
|
264
|
+
if (options.discard)
|
|
265
|
+
return undefined;
|
|
266
|
+
const local = locals.get(options.executionId);
|
|
267
|
+
if (local?.fiber) {
|
|
268
|
+
return (yield* Fiber.join(local.fiber));
|
|
269
|
+
}
|
|
270
|
+
// Foreign-owned execution: poll until exec doc reports complete.
|
|
271
|
+
while (true) {
|
|
272
|
+
const cur = yield* readExec(options.executionId);
|
|
273
|
+
if (Option.isSome(cur)) {
|
|
274
|
+
const c = completeExit(cur.value);
|
|
275
|
+
if (Option.isSome(c))
|
|
276
|
+
return c.value;
|
|
277
|
+
}
|
|
278
|
+
yield* Effect.sleep(Duration.millis(500));
|
|
279
|
+
}
|
|
280
|
+
}),
|
|
281
|
+
poll: (_workflow, executionId) => Effect.gen(function* () {
|
|
282
|
+
const local = locals.get(executionId);
|
|
283
|
+
if (local?.fiber) {
|
|
284
|
+
const exit = local.fiber.pollUnsafe();
|
|
285
|
+
if (!exit)
|
|
286
|
+
return Option.none();
|
|
287
|
+
if (exit._tag !== "Success")
|
|
288
|
+
return yield* Effect.die(exit.cause);
|
|
289
|
+
return Option.some(exit.value);
|
|
290
|
+
}
|
|
291
|
+
const state = yield* readExec(executionId);
|
|
292
|
+
if (Option.isNone(state))
|
|
293
|
+
return Option.none();
|
|
294
|
+
return completeExit(state.value);
|
|
295
|
+
}),
|
|
296
|
+
interrupt: Effect.fnUntraced(function* (_workflow, executionId) {
|
|
297
|
+
const local = locals.get(executionId);
|
|
298
|
+
if (local)
|
|
299
|
+
local.instance.interrupted = true;
|
|
300
|
+
const current = yield* readExec(executionId);
|
|
301
|
+
if (Option.isNone(current) || current.value.status === "complete")
|
|
302
|
+
return;
|
|
303
|
+
yield* replaceExec({ ...current.value, interrupted: true }).pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
|
|
304
|
+
yield* driveById(executionId);
|
|
305
|
+
}),
|
|
306
|
+
interruptUnsafe: Effect.fnUntraced(function* (_workflow, executionId) {
|
|
307
|
+
const local = locals.get(executionId);
|
|
308
|
+
if (local)
|
|
309
|
+
local.instance.interrupted = true;
|
|
310
|
+
const current = yield* readExec(executionId);
|
|
311
|
+
if (Option.isSome(current) && current.value.status !== "complete") {
|
|
312
|
+
yield* replaceExec({ ...current.value, interrupted: true }).pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
|
|
313
|
+
}
|
|
314
|
+
if (local?.fiber)
|
|
315
|
+
yield* Fiber.interrupt(local.fiber);
|
|
316
|
+
}),
|
|
317
|
+
resume: (_workflow, executionId) => driveById(executionId),
|
|
318
|
+
activityExecute: Effect.fnUntraced(function* (activity, attempt) {
|
|
319
|
+
const instance = yield* WorkflowInstance;
|
|
320
|
+
const id = activityKey(activity.name, attempt);
|
|
321
|
+
const existing = yield* readPoint(id, instance.executionId).pipe(annotate("activityRead", instance.executionId));
|
|
322
|
+
if (Option.isSome(existing)) {
|
|
323
|
+
const exit = existing.value.exit;
|
|
324
|
+
if (!(exit._tag === "Success" && exit.value._tag === "Suspended")) {
|
|
325
|
+
return yield* exit;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const activityInstance = WorkflowInstance.initial(instance.workflow, instance.executionId);
|
|
329
|
+
activityInstance.interrupted = instance.interrupted;
|
|
330
|
+
const exit = yield* activity.executeEncoded.pipe(Workflow.intoResult, Effect.provideService(WorkflowInstance, activityInstance), Effect.exit);
|
|
331
|
+
// First-writer-wins: if persistence loses the race, read back and use the persisted exit.
|
|
332
|
+
const persisted = yield* createIfMissing(dropUndefinedT({
|
|
333
|
+
id,
|
|
334
|
+
_partitionKey: instance.executionId,
|
|
335
|
+
type: "activity",
|
|
336
|
+
exit
|
|
337
|
+
}))
|
|
338
|
+
.pipe(annotate("activityPersist", instance.executionId));
|
|
339
|
+
if (persisted)
|
|
340
|
+
return yield* exit;
|
|
341
|
+
const winner = yield* readPoint(id, instance.executionId);
|
|
342
|
+
return Option.isSome(winner) ? yield* winner.value.exit : yield* exit;
|
|
343
|
+
}),
|
|
344
|
+
deferredResult: Effect.fnUntraced(function* (deferred) {
|
|
345
|
+
const instance = yield* WorkflowInstance;
|
|
346
|
+
const got = yield* readPoint(deferredKey(deferred.name), instance.executionId).pipe(annotate("deferredRead", instance.executionId));
|
|
347
|
+
return Option.map(got, (d) => d.exit);
|
|
348
|
+
}),
|
|
349
|
+
deferredDone: Effect.fnUntraced(function* (options) {
|
|
350
|
+
const created = yield* createIfMissing({
|
|
351
|
+
id: deferredKey(options.deferredName),
|
|
352
|
+
_partitionKey: options.executionId,
|
|
353
|
+
type: "deferred",
|
|
354
|
+
exit: options.exit
|
|
355
|
+
})
|
|
356
|
+
.pipe(annotate("deferredPersist", options.executionId));
|
|
357
|
+
if (!created)
|
|
358
|
+
return;
|
|
359
|
+
yield* driveById(options.executionId);
|
|
360
|
+
}),
|
|
361
|
+
scheduleClock: (workflow, options) => {
|
|
362
|
+
const fireAt = new Date(Date.now() + Duration.toMillis(options.clock.duration)).toISOString();
|
|
363
|
+
const clockDoc = {
|
|
364
|
+
id: clockKey(options.clock.name),
|
|
365
|
+
_partitionKey: options.executionId,
|
|
366
|
+
type: "clock",
|
|
367
|
+
workflowName: workflow.name,
|
|
368
|
+
deferredName: options.clock.deferred.name,
|
|
369
|
+
fireAt
|
|
370
|
+
};
|
|
371
|
+
return Effect.gen(function* () {
|
|
372
|
+
yield* createIfMissing(clockDoc).pipe(annotate("clockPersist", options.executionId));
|
|
373
|
+
// Fast-path in-process timer. If this process dies, the clock poller
|
|
374
|
+
// picks up the persisted doc and fires the deferred.
|
|
375
|
+
yield* fireClock(clockDoc).pipe(Effect.delay(options.clock.duration), FiberMap.run(clocks, `${options.executionId}/${options.clock.name}`, { onlyIfMissing: true }), Effect.asVoid);
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
const engine = makeUnsafe(encoded);
|
|
380
|
+
// --- Recovery poller --------------------------------------------------
|
|
381
|
+
// Scan for executions whose lease has lapsed (or was never set) and
|
|
382
|
+
// re-drive them locally. driveById will go through claim → fork fiber,
|
|
383
|
+
// resuming activities from persisted results.
|
|
384
|
+
if (Duration.toMillis(recoveryInterval) > 0) {
|
|
385
|
+
const recoverStep = Effect
|
|
386
|
+
.gen(function* () {
|
|
387
|
+
const nowIso = new Date().toISOString();
|
|
388
|
+
const stale = yield* Effect.promise(() => container
|
|
389
|
+
.items
|
|
390
|
+
.query({
|
|
391
|
+
query: "SELECT c._partitionKey, c.workflowName FROM c WHERE c.type = 'exec' AND c.status = 'running' AND (NOT IS_DEFINED(c.leaseExpiresAt) OR c.leaseExpiresAt <= @now)",
|
|
392
|
+
parameters: [{ name: "@now", value: nowIso }]
|
|
393
|
+
})
|
|
394
|
+
.fetchAll());
|
|
395
|
+
for (const row of stale.resources) {
|
|
396
|
+
if (!workflows.has(row.workflowName))
|
|
397
|
+
continue;
|
|
398
|
+
const local = locals.get(row._partitionKey);
|
|
399
|
+
if (local?.fiber && !local.fiber.pollUnsafe())
|
|
400
|
+
continue;
|
|
401
|
+
yield* Effect.forkIn(driveById(row._partitionKey), scope);
|
|
402
|
+
}
|
|
403
|
+
})
|
|
404
|
+
.pipe(annotate("recoveryScan"), Effect.catchCause(() => Effect.void));
|
|
405
|
+
yield* recoverStep.pipe(Effect.repeat(Schedule.spaced(recoveryInterval)), Effect.forkIn(scope));
|
|
406
|
+
}
|
|
407
|
+
// --- Clock poller -----------------------------------------------------
|
|
408
|
+
// Cross-partition scan for clocks whose fireAt is due. Fires the deferred
|
|
409
|
+
// via createIfMissing (idempotent) so multiple pollers across processes
|
|
410
|
+
// converge. Also acts as the restart recovery path for clocks scheduled
|
|
411
|
+
// before a crash.
|
|
412
|
+
if (Duration.toMillis(clockPollInterval) > 0) {
|
|
413
|
+
const clockStep = Effect
|
|
414
|
+
.gen(function* () {
|
|
415
|
+
const nowIso = new Date().toISOString();
|
|
416
|
+
const due = yield* Effect.promise(() => container
|
|
417
|
+
.items
|
|
418
|
+
.query({
|
|
419
|
+
query: "SELECT c.id, c._partitionKey, c.workflowName, c.deferredName FROM c WHERE c.type = 'clock' AND c.fireAt <= @now",
|
|
420
|
+
parameters: [{ name: "@now", value: nowIso }]
|
|
421
|
+
})
|
|
422
|
+
.fetchAll());
|
|
423
|
+
for (const row of due.resources) {
|
|
424
|
+
yield* Effect.forkIn(fireClock({
|
|
425
|
+
id: row.id,
|
|
426
|
+
_partitionKey: row._partitionKey,
|
|
427
|
+
type: "clock",
|
|
428
|
+
workflowName: row.workflowName,
|
|
429
|
+
deferredName: row.deferredName,
|
|
430
|
+
fireAt: nowIso
|
|
431
|
+
}), scope);
|
|
432
|
+
}
|
|
433
|
+
})
|
|
434
|
+
.pipe(annotate("clockScan"), Effect.catchCause(() => Effect.void));
|
|
435
|
+
yield* clockStep.pipe(Effect.repeat(Schedule.spaced(clockPollInterval)), Effect.forkIn(scope));
|
|
436
|
+
}
|
|
437
|
+
return engine;
|
|
438
|
+
});
|
|
439
|
+
/**
|
|
440
|
+
* Cosmos DB backed `WorkflowEngine` layer.
|
|
441
|
+
*
|
|
442
|
+
* Per-execution writes use TransactionalBatch (same partition key) and OCC
|
|
443
|
+
* via `_etag`/IfMatch, giving first-writer-wins semantics for activity
|
|
444
|
+
* results, durable-deferred completions, and exec-state transitions.
|
|
445
|
+
*/
|
|
446
|
+
export const layerCosmos = (cfg) => Layer
|
|
447
|
+
.effect(WorkflowEngine)(makeCosmosWorkflowEngine(cfg))
|
|
448
|
+
.pipe(Layer.provide(CosmosClientLayer(Redacted.value(cfg.url), cfg.dbName)));
|
|
449
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV29ya2Zsb3dFbmdpbmVDb3Ntb3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV29ya2Zsb3dFbmdpbmVDb3Ntb3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsT0FBTyxLQUFLLE1BQU0sTUFBTSxtQkFBbUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssS0FBSyxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sbUJBQW1CLENBQUE7QUFDM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ2pELE9BQU8sS0FBSyxRQUFRLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxLQUFLLElBQUksTUFBTSxhQUFhLENBQUE7QUFDbkMsT0FBTyxLQUFLLEtBQUssTUFBTSxjQUFjLENBQUE7QUFDckMsT0FBTyxLQUFLLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssUUFBUSxNQUFNLGlCQUFpQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxRQUFRLE1BQU0saUJBQWlCLENBQUE7QUFFM0MsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQ0FBbUMsQ0FBQTtBQUM3RCxPQUFPLEVBQWdCLFVBQVUsRUFBRSxjQUFjLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQTtBQUNwSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUNwRSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDNUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLFVBQVUsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQTJEOUQsTUFBTSxNQUFNLEdBQUcsTUFBZSxDQUFBO0FBQzlCLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBWSxF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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.255",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"proper-lockfile": "^4.1.2",
|
|
14
14
|
"pure-rand": "8.4.0",
|
|
15
15
|
"query-string": "^9.3.1",
|
|
16
|
-
"effect-app": "4.0.0-beta.
|
|
16
|
+
"effect-app": "4.0.0-beta.255"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@azure/cosmos": "^4.9.3",
|
|
20
20
|
"@azure/service-bus": "^7.9.5",
|
|
21
|
-
"@effect/sql-sqlite-node": "4.0.0-beta.
|
|
21
|
+
"@effect/sql-sqlite-node": "4.0.0-beta.71",
|
|
22
22
|
"@sentry/node": "10.51.0",
|
|
23
23
|
"@sentry/opentelemetry": "10.51.0",
|
|
24
24
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@azure/cosmos": "^4.9.3",
|
|
40
40
|
"@azure/service-bus": "^7.9.5",
|
|
41
|
-
"@effect/vitest": "^4.0.0-beta.
|
|
41
|
+
"@effect/vitest": "^4.0.0-beta.71",
|
|
42
42
|
"@sendgrid/helpers": "^8.0.0",
|
|
43
43
|
"@sendgrid/mail": "^8.1.6",
|
|
44
44
|
"@sentry/node": "10.51.0",
|
|
45
45
|
"@sentry/opentelemetry": "10.51.0",
|
|
46
|
-
"effect": "^4.0.0-beta.
|
|
46
|
+
"effect": "^4.0.0-beta.71",
|
|
47
47
|
"jwt-decode": "^4.0.0",
|
|
48
48
|
"redis": "^3.1.2",
|
|
49
49
|
"redlock": "^4.2.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-engine-cosmos.test.d.ts","sourceRoot":"","sources":["../workflow-engine-cosmos.test.ts"],"names":[],"mappings":""}
|