@swirls/looms 0.4.0 → 0.5.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/CHANGELOG.md +55 -0
- package/dist/actor/cell.d.ts +21 -2
- package/dist/actor/cell.js +15 -3
- package/dist/actor/host.d.ts +10 -2
- package/dist/actor/host.js +27 -4
- package/dist/actor/index.d.ts +2 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +3 -0
- package/dist/actor/routing.js +13 -2
- package/dist/agent/definitions-store.d.ts +1 -1
- package/dist/agent/definitions-store.js +1 -1
- package/dist/agent/definitions.d.ts +48 -0
- package/dist/agent/definitions.js +44 -0
- package/dist/agent/effects.d.ts +184 -0
- package/dist/agent/effects.js +172 -40
- package/dist/agent/events.d.ts +89 -0
- package/dist/agent/events.js +25 -0
- package/dist/agent/module.d.ts +412 -0
- package/dist/agent/module.js +5 -1
- package/dist/agent/scope.d.ts +88 -0
- package/dist/agent/threads.js +39 -3
- package/dist/agent/types.d.ts +4 -0
- package/dist/approval/effects.d.ts +40 -0
- package/dist/approval/module.d.ts +80 -0
- package/dist/client/client.d.ts +468 -119
- package/dist/client/client.js +214 -21
- package/dist/client/index.d.ts +1 -1
- package/dist/client/sse.d.ts +1 -1
- package/dist/client/sse.js +2 -2
- package/dist/cloudflare/durable-object.d.ts +66 -2
- package/dist/cloudflare/durable-object.js +96 -1
- package/dist/cloudflare/event-store.d.ts +7 -3
- package/dist/cloudflare/event-store.js +16 -3
- package/dist/cloudflare/index.d.ts +7 -1
- package/dist/cloudflare/index.js +7 -1
- package/dist/cloudflare/memory-queue.d.ts +18 -0
- package/dist/cloudflare/memory-queue.js +53 -0
- package/dist/cloudflare/queue-consumer.d.ts +52 -0
- package/dist/cloudflare/queue-consumer.js +102 -0
- package/dist/cloudflare/queue-message.d.ts +31 -0
- package/dist/cloudflare/queue-message.js +33 -0
- package/dist/cloudflare/queue-pull.d.ts +62 -0
- package/dist/cloudflare/queue-pull.js +130 -0
- package/dist/cloudflare/queue-worker.d.ts +39 -0
- package/dist/cloudflare/queue-worker.js +62 -0
- package/dist/cloudflare/r2-blob-store.d.ts +33 -0
- package/dist/cloudflare/r2-blob-store.js +60 -0
- package/dist/cloudflare/router.d.ts +4 -1
- package/dist/cloudflare/router.js +8 -3
- package/dist/cloudflare/websocket.d.ts +27 -0
- package/dist/cloudflare/websocket.js +215 -0
- package/dist/core/blob-offload.d.ts +21 -0
- package/dist/core/blob-offload.js +143 -0
- package/dist/core/blob-store.d.ts +45 -0
- package/dist/core/blob-store.js +164 -0
- package/dist/core/blobs.d.ts +37 -0
- package/dist/core/blobs.js +160 -0
- package/dist/core/definition-resolver.d.ts +40 -0
- package/dist/core/definition-resolver.js +129 -0
- package/dist/core/definition-store.d.ts +6 -0
- package/dist/core/definition-store.js +37 -1
- package/dist/core/effects.d.ts +86 -3
- package/dist/core/effects.js +99 -3
- package/dist/core/envelope.d.ts +9 -0
- package/dist/core/envelope.js +4 -0
- package/dist/core/event-codec.js +3 -0
- package/dist/core/fold.js +83 -1
- package/dist/core/ids.d.ts +2 -0
- package/dist/core/ids.js +4 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/launcher.d.ts +97 -0
- package/dist/core/launcher.js +67 -0
- package/dist/core/module-scope.d.ts +7 -3
- package/dist/core/module-scope.js +3 -0
- package/dist/core/module.d.ts +10 -0
- package/dist/core/projection.js +4 -0
- package/dist/core/protocol.d.ts +36 -1
- package/dist/core/protocol.js +35 -0
- package/dist/core/published.d.ts +2 -0
- package/dist/core/published.js +4 -1
- package/dist/core/replay.d.ts +96 -0
- package/dist/core/run-context.d.ts +33 -0
- package/dist/core/run-context.js +23 -0
- package/dist/core/sqlite-store.js +57 -5
- package/dist/core/state.d.ts +60 -0
- package/dist/core/state.js +19 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.js +7 -0
- package/dist/core/subscription.d.ts +97 -0
- package/dist/core/subscription.js +224 -0
- package/dist/core/thread.d.ts +7 -0
- package/dist/core/thread.js +1 -0
- package/dist/core/trace.d.ts +21 -0
- package/dist/core/trace.js +45 -0
- package/dist/core/worker-callback.d.ts +25 -1
- package/dist/debugger/app/assets/{index-CgDzWJg7.css → index-B7GdT1UA.css} +1 -1
- package/dist/debugger/app/assets/index-C31SnCuN.js +22 -0
- package/dist/debugger/app/assets/routes-DPA3O5AF.js +47 -0
- package/dist/debugger/app/index.html +2 -2
- package/dist/debugger/components/event-inspector.d.ts +3 -1
- package/dist/debugger/components/event-inspector.js +25 -4
- package/dist/debugger/components/event-stream.d.ts +4 -1
- package/dist/debugger/components/event-stream.js +2 -2
- package/dist/debugger/components/run-tree.d.ts +5 -2
- package/dist/debugger/components/run-tree.js +10 -4
- package/dist/debugger/context.d.ts +8 -1
- package/dist/debugger/context.js +15 -3
- package/dist/debugger/events/protocol-summarize.js +18 -3
- package/dist/debugger/index.d.ts +1 -1
- package/dist/debugger/index.js +1 -1
- package/dist/debugger/shell/debugger-shell.js +1 -1
- package/dist/debugger/shell/events-pane.js +4 -3
- package/dist/debugger/styles.css +1 -0
- package/dist/evaluator/definitions-store.d.ts +3 -4
- package/dist/evaluator/definitions-store.js +3 -3
- package/dist/evaluator/definitions.d.ts +4 -1
- package/dist/evaluator/definitions.js +5 -2
- package/dist/evaluator/effects.d.ts +74 -33
- package/dist/evaluator/effects.js +6 -2
- package/dist/evaluator/module.d.ts +150 -66
- package/dist/evaluator/module.js +7 -3
- package/dist/evaluator/threads.d.ts +2 -0
- package/dist/evaluator/threads.js +4 -0
- package/dist/projectors/event-log.d.ts +87 -0
- package/dist/projectors/event-log.js +396 -0
- package/dist/projectors/index-model.d.ts +12 -0
- package/dist/projectors/index-model.js +12 -3
- package/dist/projectors/memory.js +7 -0
- package/dist/projectors/postgres.d.ts +1 -0
- package/dist/projectors/postgres.js +32 -15
- package/dist/projectors/schema.d.ts +5 -0
- package/dist/projectors/schema.js +26 -1
- package/dist/projectors/sqlite.js +47 -19
- package/dist/projectors/with-projectors.d.ts +7 -1
- package/dist/projectors/with-projectors.js +13 -3
- package/dist/react/materialize.js +5 -1
- package/dist/react/react.d.ts +10 -2
- package/dist/react/react.js +43 -19
- package/dist/react/store.d.ts +11 -2
- package/dist/react/store.js +104 -12
- package/dist/react/tables.d.ts +4 -1
- package/dist/runtime/cancellation.d.ts +2 -1
- package/dist/runtime/cancellation.js +35 -2
- package/dist/runtime/child-run.d.ts +10 -0
- package/dist/runtime/child-run.js +58 -0
- package/dist/runtime/deadline-transition-planner.js +11 -2
- package/dist/runtime/dispatch-effect.d.ts +2 -2
- package/dist/runtime/dispatch-effect.js +43 -19
- package/dist/runtime/errors.d.ts +14 -1
- package/dist/runtime/errors.js +10 -0
- package/dist/runtime/filesystem-blob-store.d.ts +6 -0
- package/dist/runtime/filesystem-blob-store.js +59 -0
- package/dist/runtime/helpers.d.ts +15 -6
- package/dist/runtime/helpers.js +46 -6
- package/dist/runtime/index.d.ts +4 -2
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/local-effect-executor.d.ts +11 -2
- package/dist/runtime/local-effect-executor.js +80 -4
- package/dist/runtime/looms.d.ts +38 -4
- package/dist/runtime/looms.js +17 -3
- package/dist/runtime/repository.d.ts +5 -4
- package/dist/runtime/repository.js +5 -2
- package/dist/runtime/retry-policy.d.ts +5 -0
- package/dist/runtime/retry-policy.js +10 -2
- package/dist/runtime/run-start.d.ts +1 -1
- package/dist/runtime/run-start.js +10 -0
- package/dist/runtime/runtime.d.ts +2 -2
- package/dist/runtime/runtime.js +191 -68
- package/dist/runtime/server/auth.d.ts +3 -0
- package/dist/runtime/server/fetch-handler.d.ts +2 -2
- package/dist/runtime/server/fetch-handler.js +35 -4
- package/dist/runtime/server/grant.d.ts +49 -0
- package/dist/runtime/server/grant.js +177 -0
- package/dist/runtime/server/routes/effects.js +47 -5
- package/dist/runtime/server/routes/runs.js +6 -1
- package/dist/runtime/server/run-route.d.ts +18 -0
- package/dist/runtime/server/run-route.js +26 -0
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/sse.js +26 -4
- package/dist/runtime/subscription.d.ts +8 -0
- package/dist/runtime/subscription.js +23 -0
- package/dist/runtime/types.d.ts +87 -8
- package/dist/runtime/wake-engine.d.ts +4 -2
- package/dist/runtime/wake-engine.js +57 -6
- package/dist/runtime/worker-callbacks.d.ts +12 -2
- package/dist/runtime/worker-callbacks.js +102 -72
- package/dist/runtime/worker-effect-dispatch.d.ts +14 -5
- package/dist/runtime/worker-effect-dispatch.js +84 -18
- package/dist/schedule/debugger/index.d.ts +4 -0
- package/dist/schedule/debugger/index.js +11 -0
- package/dist/schedule/debugger/schedule-view.d.ts +3 -0
- package/dist/schedule/debugger/schedule-view.js +68 -0
- package/dist/schedule/debugger/summarize.d.ts +2 -0
- package/dist/schedule/debugger/summarize.js +43 -0
- package/dist/schedule/definitions-store.d.ts +10 -0
- package/dist/schedule/definitions-store.js +8 -0
- package/dist/schedule/definitions.d.ts +57 -0
- package/dist/schedule/definitions.js +30 -0
- package/dist/schedule/effects.d.ts +756 -0
- package/dist/schedule/effects.js +244 -0
- package/dist/schedule/ensure.d.ts +55 -0
- package/dist/schedule/ensure.js +109 -0
- package/dist/schedule/events.d.ts +116 -0
- package/dist/schedule/events.js +49 -0
- package/dist/schedule/index.d.ts +11 -0
- package/dist/schedule/index.js +11 -0
- package/dist/schedule/module.d.ts +1474 -0
- package/dist/schedule/module.js +22 -0
- package/dist/schedule/projections.d.ts +55 -0
- package/dist/schedule/projections.js +88 -0
- package/dist/schedule/scope.d.ts +121 -0
- package/dist/schedule/scope.js +7 -0
- package/dist/schedule/signals.d.ts +25 -0
- package/dist/schedule/signals.js +33 -0
- package/dist/schedule/specs.d.ts +59 -0
- package/dist/schedule/specs.js +231 -0
- package/dist/schedule/threads.d.ts +25 -0
- package/dist/schedule/threads.js +259 -0
- package/dist/testing/corpus-module.d.ts +34 -0
- package/dist/testing/corpus-module.js +87 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +5 -6
- package/dist/testing/replay-corpus.d.ts +22 -0
- package/dist/testing/replay-corpus.js +50 -0
- package/dist/workflow/definitions-store.d.ts +1 -1
- package/dist/workflow/definitions-store.js +1 -1
- package/dist/workflow/definitions.d.ts +14 -0
- package/dist/workflow/effects.d.ts +122 -0
- package/dist/workflow/effects.js +16 -6
- package/dist/workflow/events.d.ts +42 -0
- package/dist/workflow/events.js +4 -0
- package/dist/workflow/module.d.ts +345 -32
- package/dist/workflow/module.js +7 -3
- package/dist/workflow/scope.d.ts +42 -0
- package/dist/workflow/threads.d.ts +72 -0
- package/dist/workflow/threads.js +106 -38
- package/package.json +10 -1
- package/dist/debugger/app/assets/index-D--9esm9.js +0 -22
- package/dist/debugger/app/assets/routes-Dakrdusf.js +0 -47
package/dist/runtime/looms.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { type AnyRuntimeModule, type DebuggerHost, type DefinitionInput, type DefinitionRef, type EventEnvelope, type EventInput, type EventStore, type EventStoreTrimCoverage, type JsonValue, type SnapshotStore, type ProjectionDefinition, type ReplayStep, type RunState } from '@swirls/looms/core';
|
|
1
|
+
import { type AnyRuntimeModule, type DebuggerHost, type DefinitionInput, type DefinitionRef, type DefinitionResolver, type EventEnvelope, type EventInput, type BlobStore, type EventStore, type EventStoreTrimCoverage, type JsonValue, type SnapshotStore, type ProjectionDefinition, type ReplayStep, type RunLauncher, type RunState } from '@swirls/looms/core';
|
|
2
2
|
import type { RuntimeObserver } from './observer';
|
|
3
|
-
import { type EffectWorker, type LoomsRuntime, type RunOperationalStatus, type WakeScheduler, type WorkerCallbackInput } from './runtime';
|
|
3
|
+
import { type EffectWorker, type LoomsRuntime, type RunOperationalStatus, type StartRunArgs, type WakeScheduler, type WorkerCallbackInput, type WorkerCallbackResult } from './runtime';
|
|
4
4
|
import { type Authorize, type RunningServer } from './server';
|
|
5
5
|
export interface CreateLoomsOptions {
|
|
6
6
|
/** Runtime modules to enable. Pass `agent()`, `workflow()`, `approval()`, and/or your own. */
|
|
7
7
|
readonly modules?: readonly AnyRuntimeModule[];
|
|
8
|
+
/**
|
|
9
|
+
* Loads a definition that was not registered on a module. Registered definitions are checked
|
|
10
|
+
* first. A run pins the resolved version on its start event.
|
|
11
|
+
*/
|
|
12
|
+
readonly definitionResolver?: DefinitionResolver;
|
|
8
13
|
readonly store?: EventStore | Promise<EventStore> | (() => Promise<EventStore>);
|
|
9
14
|
readonly serve?: boolean | {
|
|
10
15
|
port?: number;
|
|
@@ -17,6 +22,11 @@ export interface CreateLoomsOptions {
|
|
|
17
22
|
readonly snapshotEvery?: number;
|
|
18
23
|
/** Defaults to the EventStore's attached store (S2) or an in-memory SnapshotStore. */
|
|
19
24
|
readonly snapshotStore?: SnapshotStore;
|
|
25
|
+
/**
|
|
26
|
+
* Content-addressed store for JSON values that would exceed the 1 MiB event limit or the
|
|
27
|
+
* 8 MiB snapshot limit. Reads resolve references before folds, projections, and callers see them.
|
|
28
|
+
*/
|
|
29
|
+
readonly blobStore?: BlobStore;
|
|
20
30
|
readonly trimAfterSnapshot?: {
|
|
21
31
|
keepSnapshots: number;
|
|
22
32
|
coverage?: (runId: string) => EventStoreTrimCoverage | Promise<EventStoreTrimCoverage>;
|
|
@@ -27,7 +37,11 @@ export interface CreateLoomsOptions {
|
|
|
27
37
|
readonly rescanTimers?: boolean;
|
|
28
38
|
/** Pluggable wake scheduler for timer waits. Defaults to an in-process Effect fiber scheduler. */
|
|
29
39
|
readonly scheduler?: WakeScheduler;
|
|
40
|
+
/** Starts runs from effect handlers. Defaults to launching into this runtime's own store. */
|
|
41
|
+
readonly launcher?: RunLauncher;
|
|
30
42
|
readonly worker?: EffectWorker;
|
|
43
|
+
/** Maximum concurrent in-flight worker effects dispatched per run (fairness guard). */
|
|
44
|
+
readonly maxInFlightWorkerEffects?: number;
|
|
31
45
|
/** Failure-isolated runtime observation sink. */
|
|
32
46
|
readonly observer?: RuntimeObserver;
|
|
33
47
|
/**
|
|
@@ -35,7 +49,8 @@ export interface CreateLoomsOptions {
|
|
|
35
49
|
* and operations routes return 503; `bearerAuth({ worker, operations })` enables them.
|
|
36
50
|
*
|
|
37
51
|
* A mounted debugger is authorized as `{ access: 'read', name: 'debugger' }`. Bearer tokens on
|
|
38
|
-
* reads block browser navigation
|
|
52
|
+
* reads block browser navigation. `grantAuth` covers a browser EventSource or WebSocket that can
|
|
53
|
+
* only send a query parameter or a subprotocol.
|
|
39
54
|
*/
|
|
40
55
|
readonly authorize?: Authorize;
|
|
41
56
|
/**
|
|
@@ -61,6 +76,9 @@ export interface Looms {
|
|
|
61
76
|
runId?: string;
|
|
62
77
|
threadId?: string;
|
|
63
78
|
idempotencyKey?: string;
|
|
79
|
+
attributes?: StartRunArgs['attributes'];
|
|
80
|
+
secrets?: StartRunArgs['secrets'];
|
|
81
|
+
trace?: StartRunArgs['trace'];
|
|
64
82
|
}): Promise<StartResult>;
|
|
65
83
|
/** Start a run by `{ kind, definitionName }` when you only have names (HTTP bodies, CLIs). */
|
|
66
84
|
startRun(args: {
|
|
@@ -71,6 +89,22 @@ export interface Looms {
|
|
|
71
89
|
runId?: string;
|
|
72
90
|
threadId?: string;
|
|
73
91
|
idempotencyKey?: string;
|
|
92
|
+
attributes?: StartRunArgs['attributes'];
|
|
93
|
+
secrets?: StartRunArgs['secrets'];
|
|
94
|
+
trace?: StartRunArgs['trace'];
|
|
95
|
+
}): Promise<StartResult>;
|
|
96
|
+
/** Commit a run's start and schedule a wake without waiting for it. */
|
|
97
|
+
launchRun(args: {
|
|
98
|
+
kind: string;
|
|
99
|
+
definitionName: string;
|
|
100
|
+
definitionVersion?: string;
|
|
101
|
+
input?: JsonValue;
|
|
102
|
+
runId?: string;
|
|
103
|
+
threadId?: string;
|
|
104
|
+
idempotencyKey?: string;
|
|
105
|
+
attributes?: StartRunArgs['attributes'];
|
|
106
|
+
secrets?: StartRunArgs['secrets'];
|
|
107
|
+
trace?: StartRunArgs['trace'];
|
|
74
108
|
}): Promise<StartResult>;
|
|
75
109
|
getRun(runId: string): Promise<RunState>;
|
|
76
110
|
getEvents(runId: string, options?: {
|
|
@@ -93,7 +127,7 @@ export interface Looms {
|
|
|
93
127
|
fork(sourceRunId: string, options?: {
|
|
94
128
|
runId?: string;
|
|
95
129
|
}): Promise<StartResult>;
|
|
96
|
-
workerCallback(runId: string, input: WorkerCallbackInput): Promise<
|
|
130
|
+
workerCallback(runId: string, input: WorkerCallbackInput): Promise<WorkerCallbackResult>;
|
|
97
131
|
fetch(req: Request): Promise<Response | null>;
|
|
98
132
|
serve(options?: {
|
|
99
133
|
port?: number;
|
package/dist/runtime/looms.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Data, Effect, Predicate } from 'effect';
|
|
2
|
-
import { EventStoreTag, makeMemoryEventStore, snapshotStoreOf, SnapshotStoreTag, } from '@swirls/looms/core';
|
|
2
|
+
import { EventStoreTag, makeMemoryEventStore, makeMemorySnapshotStore, snapshotStoreOf, withBlobOffload, SnapshotStoreTag, } from '@swirls/looms/core';
|
|
3
3
|
import { createRuntime, } from './runtime.js';
|
|
4
4
|
import { createFetchHandler, handlesPath, mountDebugger, serveHttp, } from './server.js';
|
|
5
5
|
class LoomsInitializationError extends Data.TaggedError('LoomsInitializationError') {
|
|
@@ -20,7 +20,7 @@ export function createLooms(options = {}) {
|
|
|
20
20
|
if (!initPromise) {
|
|
21
21
|
initPromise = Effect.runPromise(Effect.gen(function* () {
|
|
22
22
|
const configuredStore = options.store;
|
|
23
|
-
|
|
23
|
+
let store = !configuredStore
|
|
24
24
|
? yield* makeMemoryEventStore
|
|
25
25
|
: Predicate.isFunction(configuredStore)
|
|
26
26
|
? yield* Effect.tryPromise({
|
|
@@ -33,18 +33,28 @@ export function createLooms(options = {}) {
|
|
|
33
33
|
catch: (cause) => new LoomsInitializationError(cause),
|
|
34
34
|
})
|
|
35
35
|
: configuredStore;
|
|
36
|
+
if (options.blobStore) {
|
|
37
|
+
const snapshots = options.snapshotStore ?? snapshotStoreOf(store) ?? (yield* makeMemorySnapshotStore);
|
|
38
|
+
store = withBlobOffload(store, options.blobStore, { snapshots });
|
|
39
|
+
}
|
|
36
40
|
const runtime = createRuntime({
|
|
37
41
|
modules,
|
|
38
42
|
store,
|
|
39
43
|
maxWakeIterations: options.maxWakeIterations,
|
|
40
44
|
maxPendingRunOperations: options.maxPendingRunOperations,
|
|
41
45
|
snapshotEvery: options.snapshotEvery,
|
|
42
|
-
snapshotStore: options.
|
|
46
|
+
snapshotStore: options.blobStore
|
|
47
|
+
? snapshotStoreOf(store)
|
|
48
|
+
: (options.snapshotStore ?? snapshotStoreOf(store)),
|
|
43
49
|
trimAfterSnapshot: options.trimAfterSnapshot,
|
|
44
50
|
runCacheSize: options.runCacheSize,
|
|
45
51
|
scheduler: options.scheduler,
|
|
52
|
+
launcher: options.launcher,
|
|
53
|
+
localLauncher: options.launcher === undefined,
|
|
46
54
|
worker: options.worker,
|
|
55
|
+
maxInFlightWorkerEffects: options.maxInFlightWorkerEffects,
|
|
47
56
|
observer: options.observer,
|
|
57
|
+
definitionResolver: options.definitionResolver,
|
|
48
58
|
});
|
|
49
59
|
if (options.rescanTimers !== false) {
|
|
50
60
|
yield* runtime.rescanTimers.pipe(Effect.provideService(EventStoreTag, store), Effect.tapError(Effect.logError), Effect.ignore);
|
|
@@ -76,6 +86,7 @@ export function createLooms(options = {}) {
|
|
|
76
86
|
},
|
|
77
87
|
ready: () => getInit().then(({ store, runtime }) => ({ store, runtime })),
|
|
78
88
|
startRun: (args) => runEffect((i) => i.runtime.startRun(args)),
|
|
89
|
+
launchRun: (args) => runEffect((i) => i.runtime.launchRun(args)),
|
|
79
90
|
start: (definition, input, startOpts) => runEffect((i) => i.runtime.startRun({
|
|
80
91
|
kind: definition.kind,
|
|
81
92
|
definitionName: definition.name,
|
|
@@ -85,6 +96,9 @@ export function createLooms(options = {}) {
|
|
|
85
96
|
runId: startOpts?.runId,
|
|
86
97
|
threadId: startOpts?.threadId,
|
|
87
98
|
idempotencyKey: startOpts?.idempotencyKey,
|
|
99
|
+
attributes: startOpts?.attributes,
|
|
100
|
+
secrets: startOpts?.secrets,
|
|
101
|
+
trace: startOpts?.trace,
|
|
88
102
|
})),
|
|
89
103
|
getRun: (runId) => runEffect((i) => i.runtime.getRun(runId)),
|
|
90
104
|
getEvents: (runId, opts) => runEffect((i) => i.runtime.getEvents(runId, opts)),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
|
-
import { EventStoreTrimmedError, type AppendableEvent, type AppendResult, type ComposedRegistry, type EventEnvelope, type EventStore, type EventStoreAppendError, type EventStoreError, type EventStoreTrimCoverage, type EventStoreTruncationError, type RunCursor, type SnapshotStore } from '@swirls/looms/core';
|
|
2
|
+
import { EventStoreTrimmedError, type AppendableEvent, type AppendResult, type ComposedRegistry, type DefinitionResolveError, type DefinitionResolver, type EventEnvelope, type EventStore, type EventStoreAppendError, type EventStoreError, type EventStoreTrimCoverage, type EventStoreTruncationError, type RunCursor, type SnapshotStore } from '@swirls/looms/core';
|
|
3
3
|
import { RuntimeExecutionError } from './errors';
|
|
4
4
|
import { type RunCursorCache } from './helpers';
|
|
5
5
|
import { type RuntimeObserver } from './observer';
|
|
@@ -35,19 +35,20 @@ export interface RuntimeRepositoryOptions {
|
|
|
35
35
|
readonly runCache: RunCursorCache;
|
|
36
36
|
readonly executionContexts: RunExecutionContexts;
|
|
37
37
|
readonly observer?: RuntimeObserver;
|
|
38
|
+
readonly definitionResolver: DefinitionResolver;
|
|
38
39
|
}
|
|
39
40
|
export declare function createRuntimeRepository(options: RuntimeRepositoryOptions): {
|
|
40
41
|
appendObserved: (store: EventStore, runId: string, events: ReadonlyArray<AppendableEvent>, appendOptions?: Parameters<EventStore['append']>[2]) => Effect.Effect<AppendResult, EventStoreAppendError>;
|
|
41
|
-
commit: <A, E, R>(store: EventStore, runId: string, plan: (cursor: RunCursor) => Effect.Effect<CommitPlan<A>, E, R>) => Effect.Effect<CommitResult<A>, E | RuntimeExecutionError | EventStoreAppendError | EventStoreTruncationError | EventStoreTrimmedError | EventStoreError, R>;
|
|
42
|
+
commit: <A, E, R>(store: EventStore, runId: string, plan: (cursor: RunCursor) => Effect.Effect<CommitPlan<A>, E, R>) => Effect.Effect<CommitResult<A>, E | RuntimeExecutionError | EventStoreAppendError | EventStoreTruncationError | EventStoreTrimmedError | EventStoreError | DefinitionResolveError, R>;
|
|
42
43
|
liveAppends: {
|
|
43
44
|
push: (key: string, event: AppendableEvent) => Effect.Effect<void, LiveAppendError | EventStoreAppendError, never>;
|
|
44
45
|
drain: (key: string) => Effect.Effect<void>;
|
|
45
46
|
clear: (key?: string) => void;
|
|
46
47
|
size: () => number;
|
|
47
48
|
};
|
|
48
|
-
loadCursor: (store: EventStore, runId: string) => Effect.Effect<RunCursor, EventStoreTruncationError | EventStoreTrimmedError | EventStoreError>;
|
|
49
|
+
loadCursor: (store: EventStore, runId: string) => Effect.Effect<RunCursor, EventStoreTruncationError | EventStoreTrimmedError | EventStoreError | DefinitionResolveError>;
|
|
49
50
|
persistSnapshot: (store: EventStore, runId: string, cursor: RunCursor) => Effect.Effect<RunCursor>;
|
|
50
|
-
applyAppend: (store: EventStore, runId: string, cursor: RunCursor, batch: ReadonlyArray<AppendableEvent>, appendResult: AppendResult, commandRecords?: number) => Effect.Effect<RunCursor, EventStoreTruncationError | EventStoreTrimmedError | EventStoreError>;
|
|
51
|
+
applyAppend: (store: EventStore, runId: string, cursor: RunCursor, batch: ReadonlyArray<AppendableEvent>, appendResult: AppendResult, commandRecords?: number) => Effect.Effect<RunCursor, EventStoreTruncationError | EventStoreTrimmedError | EventStoreError | DefinitionResolveError>;
|
|
51
52
|
deleteCachedCursor: (runId: string) => void;
|
|
52
53
|
setCachedCursor: (runId: string, cursor: RunCursor) => void;
|
|
53
54
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Clock, Data, Effect, Option } from 'effect';
|
|
2
|
-
import { advanceCursor, assignSequences, createCoalescingAppender, emptyCursor, EventStoreTrimmedError, hashRunState, summarizeRun, trimEventStoreSafely, } from '@swirls/looms/core';
|
|
2
|
+
import { advanceCursor, assignSequences, createCoalescingAppender, emptyCursor, EventStoreTrimmedError, hashRunState, primePinnedDefinitions, summarizeRun, trimEventStoreSafely, } from '@swirls/looms/core';
|
|
3
3
|
import { RuntimeExecutionError } from './errors.js';
|
|
4
4
|
import { stripSeq } from './helpers.js';
|
|
5
5
|
import { notifyObserver } from './observer.js';
|
|
@@ -35,7 +35,7 @@ function readRemaining(store, runId, events, expectedTail) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
export function createRuntimeRepository(options) {
|
|
38
|
-
const { registry, snapshotStore, trimAfterSnapshot, keepSnapshots, runCache, executionContexts } = options;
|
|
38
|
+
const { registry, snapshotStore, trimAfterSnapshot, keepSnapshots, runCache, executionContexts, definitionResolver, } = options;
|
|
39
39
|
const headerFingerprints = new Map();
|
|
40
40
|
const observe = (event) => notifyObserver(options.observer, event);
|
|
41
41
|
const rememberHeader = (state) => {
|
|
@@ -99,6 +99,7 @@ export function createRuntimeRepository(options) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
delta = yield* readRemaining(store, runId, delta, expectedTail);
|
|
102
|
+
yield* primePinnedDefinitions(definitionResolver, delta);
|
|
102
103
|
return advanceCursor(cursor, delta, registry);
|
|
103
104
|
});
|
|
104
105
|
const loadCursorCold = (store, runId) => Effect.gen(function* () {
|
|
@@ -155,6 +156,7 @@ export function createRuntimeRepository(options) {
|
|
|
155
156
|
if (delta.length > 0) {
|
|
156
157
|
delta = yield* readRemaining(store, runId, delta);
|
|
157
158
|
}
|
|
159
|
+
yield* primePinnedDefinitions(definitionResolver, delta);
|
|
158
160
|
return advanceCursor(cursor, delta, registry);
|
|
159
161
|
});
|
|
160
162
|
const loadCursor = (store, runId) => Effect.gen(function* () {
|
|
@@ -249,6 +251,7 @@ export function createRuntimeRepository(options) {
|
|
|
249
251
|
next = yield* catchUp(store, runId, cursor, first.seq - 1);
|
|
250
252
|
}
|
|
251
253
|
}
|
|
254
|
+
yield* primePinnedDefinitions(definitionResolver, echo);
|
|
252
255
|
next = advanceCursor(next, echo, registry);
|
|
253
256
|
executionContexts.get(runId).liveCount = 0;
|
|
254
257
|
if (next.seq !== appendResult.tail) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type EventEnvelope, type EventOrigin, type OutstandingEffect, type RetryPolicy } from '@swirls/looms/core';
|
|
2
2
|
export declare function retryBackoff(retry: RetryPolicy, attempt: number): number;
|
|
3
|
+
/** Policy backoff, extended when the failed attempt asked to wait longer. */
|
|
4
|
+
export declare function retryDelay(retry: RetryPolicy, attempt: number, retryAfterMs?: number): number;
|
|
3
5
|
export interface AttemptFailurePlan {
|
|
4
6
|
readonly event: EventEnvelope;
|
|
5
7
|
readonly retrying: boolean;
|
|
@@ -13,4 +15,7 @@ export declare function planAttemptFailure(input: {
|
|
|
13
15
|
readonly now: number;
|
|
14
16
|
readonly retry: RetryPolicy | undefined;
|
|
15
17
|
readonly origin: EventOrigin;
|
|
18
|
+
/** Customer/domain failures must not be retried even when attempts remain. */
|
|
19
|
+
readonly nonRetryable?: boolean;
|
|
20
|
+
readonly retryAfterMs?: number;
|
|
16
21
|
}): AttemptFailurePlan;
|
|
@@ -5,10 +5,18 @@ export function retryBackoff(retry, attempt) {
|
|
|
5
5
|
const multiplier = Math.max(1, retry.backoffMultiplier ?? 2);
|
|
6
6
|
return Math.min(base * multiplier ** Math.max(0, attempt - 1), retry.maxBackoffMs ?? Number.MAX_SAFE_INTEGER);
|
|
7
7
|
}
|
|
8
|
+
/** Policy backoff, extended when the failed attempt asked to wait longer. */
|
|
9
|
+
export function retryDelay(retry, attempt, retryAfterMs) {
|
|
10
|
+
const backoff = retryBackoff(retry, attempt);
|
|
11
|
+
if (retryAfterMs === undefined || !Number.isFinite(retryAfterMs) || retryAfterMs < 0) {
|
|
12
|
+
return backoff;
|
|
13
|
+
}
|
|
14
|
+
return Math.max(backoff, retryAfterMs);
|
|
15
|
+
}
|
|
8
16
|
/** Schedule the next attempt when the retry policy allows one, otherwise fail the effect. */
|
|
9
17
|
export function planAttemptFailure(input) {
|
|
10
18
|
const { runId, item, attempt, error, retry } = input;
|
|
11
|
-
if (!retry || attempt >= retry.maxAttempts) {
|
|
19
|
+
if (input.nonRetryable || !retry || attempt >= retry.maxAttempts) {
|
|
12
20
|
return { event: createEffectFailedEvent(runId, item, error), retrying: false };
|
|
13
21
|
}
|
|
14
22
|
return {
|
|
@@ -18,7 +26,7 @@ export function planAttemptFailure(input) {
|
|
|
18
26
|
payload: {
|
|
19
27
|
effectId: item.effectId,
|
|
20
28
|
attempt,
|
|
21
|
-
nextAttemptAt: input.now +
|
|
29
|
+
nextAttemptAt: input.now + retryDelay(retry, attempt, input.retryAfterMs),
|
|
22
30
|
error,
|
|
23
31
|
},
|
|
24
32
|
threadId: item.threadId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
|
-
import type
|
|
2
|
+
import { type RunState } from '@swirls/looms/core';
|
|
3
3
|
import { RuntimeExecutionError, StartRunConflictError, type RunStartIdentity } from './errors';
|
|
4
4
|
export declare function assertSameDurableStart(runId: string, state: RunState, requested: RunStartIdentity): Effect.Effect<string, RuntimeExecutionError | StartRunConflictError>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Effect, Predicate } from 'effect';
|
|
2
|
+
import { sameStringRecord } from '@swirls/looms/core';
|
|
2
3
|
import { RuntimeExecutionError, StartRunConflictError } from './errors.js';
|
|
3
4
|
function canonicalJson(value) {
|
|
4
5
|
if (Array.isArray(value)) {
|
|
@@ -36,6 +37,15 @@ export function assertSameDurableStart(runId, state, requested) {
|
|
|
36
37
|
if (existing.idempotencyKey !== requested.idempotencyKey) {
|
|
37
38
|
mismatches.push('idempotencyKey');
|
|
38
39
|
}
|
|
40
|
+
if (canonicalJson(existing.launchedBy ?? null) !== canonicalJson(requested.launchedBy ?? null)) {
|
|
41
|
+
mismatches.push('launchedBy');
|
|
42
|
+
}
|
|
43
|
+
if (existing.correlationId !== requested.correlationId) {
|
|
44
|
+
mismatches.push('correlationId');
|
|
45
|
+
}
|
|
46
|
+
if (!sameStringRecord(existing.attributes ?? {}, requested.attributes)) {
|
|
47
|
+
mismatches.push('attributes');
|
|
48
|
+
}
|
|
39
49
|
return mismatches.length > 0
|
|
40
50
|
? Effect.fail(new StartRunConflictError(runId, requested, existing, mismatches))
|
|
41
51
|
: Effect.succeed(existing.rootThreadId);
|
|
@@ -4,7 +4,7 @@ export type { WakeScheduler } from './wake-scheduler';
|
|
|
4
4
|
export { createTimeoutScheduler } from './wake-scheduler';
|
|
5
5
|
export { DuplicateEffectDispatchError, ForkConflictError, MaxWakeIterationsError, RunNotFinishedError, RunNotFoundError, RunTerminalError, StartRunConflictError, } from './errors';
|
|
6
6
|
export { RunOverloadedError } from './ingress';
|
|
7
|
-
export type { CreateRuntimeOptions, EffectWorker, EffectWorkerTask, LoomsRuntime, RunOperationalStatus, StartResult, StartRunArgs, WakeError, } from './types';
|
|
8
|
-
export type { WorkerCallback, WorkerCallbackInput } from '@swirls/looms/core';
|
|
7
|
+
export type { CreateRuntimeOptions, EffectWorker, EffectWorkerDeadlines, EffectWorkerTask, LoomsRuntime, RunOperationalStatus, StartResult, StartRunArgs, WakeError, } from './types';
|
|
8
|
+
export type { WorkerCallback, WorkerCallbackInput, WorkerCallbackResult } from '@swirls/looms/core';
|
|
9
9
|
import type { CreateRuntimeOptions, LoomsRuntime } from './types';
|
|
10
10
|
export declare function createRuntime<const TModules extends readonly AnyRuntimeModule[]>(options: CreateRuntimeOptions<TModules>): LoomsRuntime<TModules>;
|