@sanoma-ai/workflows 0.7.0 → 0.8.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 +43 -12
- package/dist/apps-list.d.ts +90 -0
- package/dist/apps-list.js +109 -0
- package/dist/apps-list.js.map +1 -0
- package/dist/apps.d.ts +42 -0
- package/dist/apps.js +137 -0
- package/dist/apps.js.map +1 -0
- package/dist/call-workflow.js +5 -6
- package/dist/call-workflow.js.map +1 -1
- package/dist/call.js +6 -3
- package/dist/call.js.map +1 -1
- package/dist/cedar.d.ts +1 -1
- package/dist/cedar.js +6 -4
- package/dist/cedar.js.map +1 -1
- package/dist/change-steps.d.ts +10 -0
- package/dist/change-steps.js +204 -0
- package/dist/change-steps.js.map +1 -0
- package/dist/change-workflow.d.ts +54 -0
- package/dist/change-workflow.js +161 -0
- package/dist/change-workflow.js.map +1 -0
- package/dist/change.d.ts +121 -24
- package/dist/change.js +196 -17
- package/dist/change.js.map +1 -1
- package/dist/claims.d.ts +58 -0
- package/dist/claims.js +27 -0
- package/dist/claims.js.map +1 -0
- package/dist/client.d.ts +92 -0
- package/dist/client.js +268 -6
- package/dist/client.js.map +1 -1
- package/dist/collection.d.ts +6 -1
- package/dist/collection.js +11 -3
- package/dist/collection.js.map +1 -1
- package/dist/config.d.ts +56 -8
- package/dist/config.js +71 -29
- package/dist/config.js.map +1 -1
- package/dist/constructors.d.ts +37 -1
- package/dist/constructors.js +6 -2
- package/dist/constructors.js.map +1 -1
- package/dist/db.d.ts +21 -21
- package/dist/db.js +31 -54
- package/dist/db.js.map +1 -1
- package/dist/deadlines.d.ts +18 -12
- package/dist/deadlines.js +18 -24
- package/dist/deadlines.js.map +1 -1
- package/dist/define.d.ts +30 -14
- package/dist/define.js +9 -1
- package/dist/define.js.map +1 -1
- package/dist/demo.d.ts +15 -4
- package/dist/demo.js +27 -12
- package/dist/demo.js.map +1 -1
- package/dist/describe.d.ts +16 -2
- package/dist/describe.js +39 -4
- package/dist/describe.js.map +1 -1
- package/dist/direct.d.ts +4 -3
- package/dist/direct.js +7 -4
- package/dist/direct.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/fake.d.ts +26 -0
- package/dist/fake.js +123 -0
- package/dist/fake.js.map +1 -1
- package/dist/host.d.ts +2 -3
- package/dist/host.js +1 -1
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/lint.js +20 -6
- package/dist/lint.js.map +1 -1
- package/dist/op.d.ts +8 -1
- package/dist/op.js.map +1 -1
- package/dist/outline.js +13 -6
- package/dist/outline.js.map +1 -1
- package/dist/paths.d.ts +16 -0
- package/dist/paths.js +54 -2
- package/dist/paths.js.map +1 -1
- package/dist/person.d.ts +5 -0
- package/dist/person.js +3 -1
- package/dist/person.js.map +1 -1
- package/dist/resources.d.ts +7 -2
- package/dist/resources.js +27 -10
- package/dist/resources.js.map +1 -1
- package/dist/run.d.ts +7 -0
- package/dist/run.js.map +1 -1
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +10 -4
- package/dist/scenario.js.map +1 -1
- package/dist/scenarios.d.ts +1 -1
- package/dist/scenarios.js.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js +19 -5
- package/dist/sdk.js.map +1 -1
- package/dist/shared.d.ts +43 -2
- package/dist/shared.js +46 -4
- package/dist/shared.js.map +1 -1
- package/dist/sites.d.ts +26 -5
- package/dist/sites.js +56 -20
- package/dist/sites.js.map +1 -1
- package/dist/source.d.ts +179 -5
- package/dist/source.js +13 -0
- package/dist/source.js.map +1 -1
- package/dist/supervisor.d.ts +5 -4
- package/dist/supervisor.js +2 -11
- package/dist/supervisor.js.map +1 -1
- package/dist/version.d.ts +8 -0
- package/dist/version.js +21 -13
- package/dist/version.js.map +1 -1
- package/dist/wakeup-driver.d.ts +128 -0
- package/dist/wakeup-driver.js +216 -0
- package/dist/wakeup-driver.js.map +1 -0
- package/dist/wakeup-service.d.ts +4 -4
- package/dist/wakeup-service.js +19 -25
- package/dist/wakeup-service.js.map +1 -1
- package/dist/wakeup-type.d.ts +43 -0
- package/dist/wakeup-type.js +80 -0
- package/dist/wakeup-type.js.map +1 -0
- package/dist/wakeup.d.ts +1 -8
- package/dist/wakeup.js +2 -11
- package/dist/wakeup.js.map +1 -1
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +50 -7
- package/dist/worker.js.map +1 -1
- package/oxlint.json +3 -2
- package/package.json +3 -1
- package/src/apps-list.ts +119 -0
- package/src/apps.ts +162 -0
- package/src/call-workflow.ts +10 -2
- package/src/call.ts +6 -3
- package/src/cedar.ts +9 -7
- package/src/change-steps.ts +274 -0
- package/src/change-workflow.ts +198 -0
- package/src/change.ts +257 -27
- package/src/claims.ts +79 -0
- package/src/client.ts +320 -4
- package/src/collection.ts +22 -3
- package/src/config.ts +104 -35
- package/src/constructors.ts +8 -2
- package/src/db.ts +39 -66
- package/src/deadlines.ts +27 -30
- package/src/define.ts +31 -12
- package/src/demo.ts +55 -24
- package/src/describe.ts +67 -4
- package/src/direct.ts +9 -5
- package/src/errors.ts +3 -0
- package/src/fake.ts +137 -0
- package/src/host.ts +3 -4
- package/src/index.ts +22 -3
- package/src/lint.ts +21 -6
- package/src/op.ts +8 -1
- package/src/outline.ts +15 -6
- package/src/paths.ts +57 -2
- package/src/person.ts +4 -1
- package/src/resources.ts +31 -11
- package/src/run.ts +5 -0
- package/src/scenario.ts +14 -4
- package/src/scenarios.ts +1 -1
- package/src/sdk.ts +21 -7
- package/src/shared.ts +60 -5
- package/src/sites.ts +70 -24
- package/src/source.ts +168 -5
- package/src/supervisor.ts +7 -12
- package/src/version.ts +25 -16
- package/src/wakeup-driver.ts +270 -0
- package/src/wakeup-service.ts +21 -28
- package/src/wakeup-type.ts +90 -0
- package/src/wakeup.ts +6 -17
- package/src/worker.ts +48 -9
package/src/worker.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { DBOS, type ScheduledWorkflowFn } from "@dbos-inc/dbos-sdk";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
3
2
|
import { awaitApproval } from "./approvals.ts";
|
|
4
3
|
import { buildCtx, decideStart, isInfrastructureError, startHoldOf } from "./call.ts";
|
|
5
4
|
import { dbosStatusesOf } from "./client.ts";
|
|
6
5
|
import { declaredWakeup, type ResolvedConfig, resolveConfig, type SanomaConfig } from "./config.ts";
|
|
7
6
|
import { storedSecrets, watchCredentials } from "./credentials.ts";
|
|
8
|
-
import {
|
|
7
|
+
import { type Db, DBOS_DATABASE_OPTIONS, lazyPool, prepareDatabase, stampVersion } from "./db.ts";
|
|
9
8
|
import { deadlineRegistry, type Deadlines, idle, onOwnQueue, type SelfStop, stopWhenIdle } from "./deadlines.ts";
|
|
10
9
|
import type { WorkflowDefinition } from "./define.ts";
|
|
11
10
|
import { credentialsOf, unconfigured, unconfiguredSummary } from "./env.ts";
|
|
12
11
|
import { errorInfo, parseOrThrow, PolicyDeniedError } from "./errors.ts";
|
|
13
12
|
import { entry, ownedLedger, skipped, write, writeFailure } from "./ledger.ts";
|
|
14
|
-
import { dbosLogger, quietIfSandbox, setLogLevel, warn } from "./log.ts";
|
|
13
|
+
import { dbosLogger, info, quietIfSandbox, setLogLevel, warn } from "./log.ts";
|
|
15
14
|
import { lineStartsOf, readSource } from "./ast.ts";
|
|
16
15
|
import { callsOf, outlineWithSource } from "./outline.ts";
|
|
17
16
|
import { currentRun, type Run, type RunArgs, type WorkerState, type WorkflowOutline } from "./run.ts";
|
|
18
17
|
import { applyScheduled, nextScheduledFire, type ScheduledStarter, scheduledStarter } from "./schedules.ts";
|
|
19
18
|
import type { Source } from "./source.ts";
|
|
20
|
-
import { approverLabel, errorMessage, WORKFLOW_ACTION } from "./shared.ts";
|
|
19
|
+
import { approverLabel, CHANGE_WORKFLOW, errorMessage, WORKFLOW_ACTION } from "./shared.ts";
|
|
21
20
|
|
|
22
21
|
export interface Worker {
|
|
23
22
|
/**
|
|
@@ -85,8 +84,8 @@ export interface WorkerOptions {
|
|
|
85
84
|
/**
|
|
86
85
|
* Given, and with a wakeup declared, the worker stops itself when idle (`stopCheckMs`); without
|
|
87
86
|
* it, nobody would start another, so it never does. Called once the worker has stopped itself, with the deadline it registered with the
|
|
88
|
-
* wakeup (null for none)
|
|
89
|
-
*
|
|
87
|
+
* wakeup (null for none): a supervisor starts a fresh worker on the next write or wake, since a
|
|
88
|
+
* stopped one cannot launch again.
|
|
90
89
|
*/
|
|
91
90
|
onStopped?: (stopped: SelfStop) => void;
|
|
92
91
|
/**
|
|
@@ -145,6 +144,12 @@ export async function startWorker(config: SanomaConfig, options: WorkerOptions =
|
|
|
145
144
|
secrets: storedSecrets(() => secrets.db(), "sanoma"),
|
|
146
145
|
workflows: resolved.workflows,
|
|
147
146
|
outlines: new Map([...resolved.workflows].map(([name, wf]) => [name, outlineOf(wf)])),
|
|
147
|
+
// `registered` is filled below, before any run starts: every name of this config's is registered then.
|
|
148
|
+
startRun: async (name, runId, args) => {
|
|
149
|
+
const fn = registered.get(name) as unknown as ((args: RunArgs) => Promise<unknown>) | undefined;
|
|
150
|
+
if (!fn) throw new Error(`The worker has no workflow "${name}" to start`);
|
|
151
|
+
return DBOS.startWorkflow(fn, { workflowID: runId })(args);
|
|
152
|
+
},
|
|
148
153
|
stopped: false,
|
|
149
154
|
deadlines: deadlineRegistry(),
|
|
150
155
|
};
|
|
@@ -217,6 +222,8 @@ export async function startWorker(config: SanomaConfig, options: WorkerOptions =
|
|
|
217
222
|
);
|
|
218
223
|
}
|
|
219
224
|
}
|
|
225
|
+
// Change runs move to the latest version only: a rollback's worker, unless promoted, leaves them be.
|
|
226
|
+
if (isLatest) await carryChangeRuns(resolved, () => secrets.db());
|
|
220
227
|
await DBOS.registerQueue(resolved.queueName);
|
|
221
228
|
// The schedules are the latest version's: an older worker leaves them as the newer set them.
|
|
222
229
|
if (isLatest && options.schedules !== false) {
|
|
@@ -231,13 +238,10 @@ export async function startWorker(config: SanomaConfig, options: WorkerOptions =
|
|
|
231
238
|
warn(`the policies do not hold, so every call and start is refused:\n ${resolved.policyProblems.join("\n ")}`);
|
|
232
239
|
}
|
|
233
240
|
if (wakeup && options.onStopped) {
|
|
234
|
-
const owner = randomUUID();
|
|
235
|
-
await claimWakeup(await secrets.db(), owner);
|
|
236
241
|
const registerId = wakeup.type.wakeup!.register;
|
|
237
242
|
stopRule = stopWhenIdle({
|
|
238
243
|
// The row is one more of the runtime's tables: the secrets' pool, on the same database.
|
|
239
244
|
db: () => secrets.db(),
|
|
240
|
-
owner,
|
|
241
245
|
wakeup: wakeup.binding ?? wakeup.id,
|
|
242
246
|
// `resolveConfig` checked the operation is the config's (`checkWakeupOps`).
|
|
243
247
|
register: { op: resolved.ops.get(registerId)!, fn: resolved.drivers.get(registerId) },
|
|
@@ -286,6 +290,41 @@ function outlineOf(wf: WorkflowDefinition<any, any>): WorkflowOutline {
|
|
|
286
290
|
return { file: outline.file, lineStarts: lineStartsOf(source!), calls: callsOf(outline.nodes) };
|
|
287
291
|
}
|
|
288
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Takes over the unfinished change runs of other versions whose change code is this worker's,
|
|
295
|
+
* keeping each run's id, history and unread messages: a change's own deploy restarts the worker on
|
|
296
|
+
* the merged code, a new version, which DBOS would never give the run to. Each is stamped with this
|
|
297
|
+
* version (`stampVersion`), and a PENDING one queued again on the app's queue (`resumeWorkflows`);
|
|
298
|
+
* one stopped between the two is PENDING on this version, which DBOS's recovery takes. Not
|
|
299
|
+
* `rewindWorkflow`, which takes only a cancelled run and deletes its unread messages. It assumes one
|
|
300
|
+
* live worker per database, as a deploy does: an older one still running such a run runs it on
|
|
301
|
+
* until it stops. A failure is warned about, and the worker starts.
|
|
302
|
+
*/
|
|
303
|
+
async function carryChangeRuns({ appName, version, changeCode, queueName }: ResolvedConfig, db: () => Promise<Db>) {
|
|
304
|
+
try {
|
|
305
|
+
const runs = await DBOS.listWorkflows({
|
|
306
|
+
workflowName: CHANGE_WORKFLOW,
|
|
307
|
+
status: ["PENDING", "ENQUEUED"],
|
|
308
|
+
applicationName: appName,
|
|
309
|
+
attributes: { changeCode },
|
|
310
|
+
loadInput: false,
|
|
311
|
+
loadOutput: false,
|
|
312
|
+
});
|
|
313
|
+
const theirs = runs
|
|
314
|
+
.filter((r) => r.applicationVersion && r.applicationVersion !== version)
|
|
315
|
+
.map((r) => r.workflowID);
|
|
316
|
+
if (!theirs.length) return;
|
|
317
|
+
const carried = await stampVersion(await db(), theirs, version);
|
|
318
|
+
const pending = carried.filter((r) => r.pending).map((r) => r.id);
|
|
319
|
+
if (pending.length) await DBOS.resumeWorkflows(pending, { queueName });
|
|
320
|
+
if (carried.length) {
|
|
321
|
+
info(`carried ${carried.length} change run(s) onto version ${version}: ${carried.map((r) => r.id).join(", ")}`);
|
|
322
|
+
}
|
|
323
|
+
} catch (err) {
|
|
324
|
+
warn(`carrying the change runs of other versions onto ${version} failed, so they stay there: ${errorMessage(err)}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
289
328
|
/**
|
|
290
329
|
* Warns about unfinished runs this worker will never pick up: started on another version of
|
|
291
330
|
* the app, or queued on another queue (such as the single "sanoma" queue before queues were
|