@adonis-agora/durable 0.19.2 → 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/CHANGELOG.md +95 -0
- package/dist/src/codec-state-store.d.ts +2 -1
- package/dist/src/codec-state-store.d.ts.map +1 -1
- package/dist/src/codec-state-store.js +8 -0
- package/dist/src/codec-state-store.js.map +1 -1
- package/dist/src/control-plane-redis/index.d.ts +1 -1
- package/dist/src/control-plane-redis/index.d.ts.map +1 -1
- package/dist/src/control-plane-redis/index.js.map +1 -1
- package/dist/src/control-plane-redis/redis-control-plane.d.ts +70 -29
- package/dist/src/control-plane-redis/redis-control-plane.d.ts.map +1 -1
- package/dist/src/control-plane-redis/redis-control-plane.js +16 -6
- package/dist/src/control-plane-redis/redis-control-plane.js.map +1 -1
- package/dist/src/dashboard/index.d.ts +1 -1
- package/dist/src/dashboard/index.js +1 -1
- package/dist/src/engine.d.ts +10 -1
- package/dist/src/engine.d.ts.map +1 -1
- package/dist/src/engine.js +86 -18
- package/dist/src/engine.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces.d.ts +16 -0
- package/dist/src/interfaces.d.ts.map +1 -1
- package/dist/src/step-discovery.d.ts +3 -2
- package/dist/src/step-discovery.d.ts.map +1 -1
- package/dist/src/step-discovery.js +8 -5
- package/dist/src/step-discovery.js.map +1 -1
- package/dist/src/stores/lucid-schema.d.ts +18 -1
- package/dist/src/stores/lucid-schema.d.ts.map +1 -1
- package/dist/src/stores/lucid-schema.js +44 -1
- package/dist/src/stores/lucid-schema.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +2 -1
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +31 -0
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/testing/in-memory-state-store.d.ts +2 -1
- package/dist/src/testing/in-memory-state-store.d.ts.map +1 -1
- package/dist/src/testing/in-memory-state-store.js +12 -0
- package/dist/src/testing/in-memory-state-store.js.map +1 -1
- package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -1
- package/dist/src/testing-kit/state-store-conformance.js +47 -0
- package/dist/src/testing-kit/state-store-conformance.js.map +1 -1
- package/dist/src/transports/bullmq/bullmq-transport.d.ts.map +1 -1
- package/dist/src/transports/bullmq/bullmq-transport.js +1 -1
- package/dist/src/transports/bullmq/bullmq-transport.js.map +1 -1
- package/dist/src/workflow-discovery.d.ts +33 -3
- package/dist/src/workflow-discovery.d.ts.map +1 -1
- package/dist/src/workflow-discovery.js +40 -8
- package/dist/src/workflow-discovery.js.map +1 -1
- package/dist/src/workflow-ref.d.ts +25 -1
- package/dist/src/workflow-ref.d.ts.map +1 -1
- package/dist/src/workflow-ref.js +31 -0
- package/dist/src/workflow-ref.js.map +1 -1
- package/dist/stubs/database/migrations/create_durable_tables.stub +33 -89
- package/package.json +7 -4
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* string stays available for the cross-runtime case.
|
|
7
7
|
*/
|
|
8
8
|
import type { SingletonConfig } from './engine.js';
|
|
9
|
-
import type { ScheduledWorkflow } from './scheduler.js';
|
|
9
|
+
import type { ScheduledWorkflow, WorkflowScheduleConfig } from './scheduler.js';
|
|
10
10
|
/** Options for a workflow's `static workflow = { name, version, … }` config (see {@link BaseWorkflow}). */
|
|
11
11
|
export interface WorkflowOptions {
|
|
12
12
|
/** The registered workflow name (the cross-runtime identity, e.g. `order`). */
|
|
@@ -54,6 +54,30 @@ export declare function workflowMeta(target: unknown): WorkflowMeta | undefined;
|
|
|
54
54
|
* (not a registrable workflow) or no `static schedule`.
|
|
55
55
|
*/
|
|
56
56
|
export declare function workflowSchedules(target: unknown): ScheduledWorkflow[];
|
|
57
|
+
/**
|
|
58
|
+
* Class-decorator form of the colocated schedule — the same declaration `static schedule = {...}`
|
|
59
|
+
* makes, for codebases that prefer decorators:
|
|
60
|
+
*
|
|
61
|
+
* ```ts
|
|
62
|
+
* @Scheduled({ cron: '0 4 * * *', timezone: 'America/Sao_Paulo' })
|
|
63
|
+
* export default class CrawlWorkflow extends BaseWorkflow {
|
|
64
|
+
* static workflow = { name: 'crawl' }
|
|
65
|
+
* async run(ctx: WorkflowCtx) { … }
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* It only stamps `static schedule` on the class — normalization (key defaults, `workflow` fill-in)
|
|
70
|
+
* stays in {@link workflowSchedules}, so both authoring forms behave identically, including the
|
|
71
|
+
* requirement of a `static workflow` config (a decorated class without one is not registrable and
|
|
72
|
+
* its schedules are ignored, same as a bare `static schedule`).
|
|
73
|
+
*
|
|
74
|
+
* Composes: repeated `@Scheduled(...)` applications and an existing `static schedule` accumulate.
|
|
75
|
+
* Decorators apply bottom-up, so each application PREPENDS — the final array reads in **source
|
|
76
|
+
* order** (top decorator first, then lower ones, then the `static schedule` literal). With several
|
|
77
|
+
* schedules on one class, prefer explicit `key`s over the positional `${name}:${i}` defaults: the
|
|
78
|
+
* key is part of the deterministic run id, and reordering declarations would silently re-key them.
|
|
79
|
+
*/
|
|
80
|
+
export declare function Scheduled(config: WorkflowScheduleConfig | WorkflowScheduleConfig[]): ClassDecorator;
|
|
57
81
|
/** Structural shape of a workflow class — its `run(ctx, input)` carries the input/output types. */
|
|
58
82
|
export type WorkflowClass<TInput = unknown, TOutput = unknown> = abstract new (...args: never[]) => {
|
|
59
83
|
run(ctx: never, input: TInput): Promise<TOutput> | TOutput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-ref.d.ts","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"workflow-ref.d.ts","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,2GAA2G;AAC3G,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,sGAAsG;AACtG,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,CAOtE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,iBAAiB,EAAE,CAWtE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,GACxD,cAAc,CAUhB;AAED,mGAAmG;AACnG,MAAM,MAAM,aAAa,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,QAAQ,MACvE,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,yGAAyG;AACzG,MAAM,MAAM,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,IACvD,MAAM,GACN,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,uDAAuD;AACvD,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MACjD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;CAC1C,GACG,CAAC,GACD,OAAO,CAAC;AAEZ,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,MAClD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb;IACH,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;CACxC,GACG,OAAO,CAAC,CAAC,CAAC,GACV,OAAO,CAAC;AAEZ;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CASrD"}
|
package/dist/src/workflow-ref.js
CHANGED
|
@@ -46,6 +46,37 @@ export function workflowSchedules(target) {
|
|
|
46
46
|
key: s.key ?? (arr.length > 1 ? `${meta.name}:${i}` : meta.name),
|
|
47
47
|
}));
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Class-decorator form of the colocated schedule — the same declaration `static schedule = {...}`
|
|
51
|
+
* makes, for codebases that prefer decorators:
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* @Scheduled({ cron: '0 4 * * *', timezone: 'America/Sao_Paulo' })
|
|
55
|
+
* export default class CrawlWorkflow extends BaseWorkflow {
|
|
56
|
+
* static workflow = { name: 'crawl' }
|
|
57
|
+
* async run(ctx: WorkflowCtx) { … }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* It only stamps `static schedule` on the class — normalization (key defaults, `workflow` fill-in)
|
|
62
|
+
* stays in {@link workflowSchedules}, so both authoring forms behave identically, including the
|
|
63
|
+
* requirement of a `static workflow` config (a decorated class without one is not registrable and
|
|
64
|
+
* its schedules are ignored, same as a bare `static schedule`).
|
|
65
|
+
*
|
|
66
|
+
* Composes: repeated `@Scheduled(...)` applications and an existing `static schedule` accumulate.
|
|
67
|
+
* Decorators apply bottom-up, so each application PREPENDS — the final array reads in **source
|
|
68
|
+
* order** (top decorator first, then lower ones, then the `static schedule` literal). With several
|
|
69
|
+
* schedules on one class, prefer explicit `key`s over the positional `${name}:${i}` defaults: the
|
|
70
|
+
* key is part of the deterministic run id, and reordering declarations would silently re-key them.
|
|
71
|
+
*/
|
|
72
|
+
export function Scheduled(config) {
|
|
73
|
+
return (target) => {
|
|
74
|
+
const cls = target;
|
|
75
|
+
const existing = cls.schedule === undefined ? [] : Array.isArray(cls.schedule) ? cls.schedule : [cls.schedule];
|
|
76
|
+
const added = Array.isArray(config) ? config : [config];
|
|
77
|
+
cls.schedule = [...added, ...existing];
|
|
78
|
+
};
|
|
79
|
+
}
|
|
49
80
|
/**
|
|
50
81
|
* Resolve a {@link WorkflowRef} to its registered workflow name: a string is returned as-is; a
|
|
51
82
|
* workflow class is resolved via the name on its `static workflow` config. Throws if a class carries
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-ref.js","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkCH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAI,MAAyC,CAAC,QAAQ,CAAC;IACnE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5E,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,GAAG,GAAI,MAA2E,CAAC,QAAQ,CAAC;IAClG,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,GAAG,CAAC;QACJ,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;KACjE,CAAC,CAAC,CAAC;AACN,CAAC;AAgCD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,IAAI,2EAA2E,CACtG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"workflow-ref.js","sourceRoot":"","sources":["../../src/workflow-ref.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkCH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,IAAI,OAAO,MAAM,KAAK,UAAU;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,MAAM,GAAI,MAAyC,CAAC,QAAQ,CAAC;IACnE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5E,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,GAAG,GAAI,MAA2E,CAAC,QAAQ,CAAC;IAClG,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,GAAG,CAAC;QACJ,QAAQ,EAAE,IAAI,CAAC,IAAI;QACnB,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;KACjE,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,SAAS,CACvB,MAAyD;IAEzD,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,MAAM,GAAG,GAAG,MAEX,CAAC;QACF,MAAM,QAAQ,GACZ,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChG,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACxD,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC;AACJ,CAAC;AAgCD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAAgB;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACxC,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACrC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,IAAI,2EAA2E,CACtG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -2,102 +2,46 @@
|
|
|
2
2
|
exports({ to: app.migrationsPath(`${new Date().getTime()}_create_durable_tables.ts`) })
|
|
3
3
|
}}}
|
|
4
4
|
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
5
|
+
import db from '@adonisjs/lucid/services/db'
|
|
6
|
+
import { createDurableTables, dropDurableTables } from '@adonis-agora/durable'
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
|
-
* Durable workflow tables for the @adonis-agora/durable `lucid` state store: runs, step checkpoints,
|
|
8
|
-
* search-attribute side-table, signal waiters, buffered signals and buffered events.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Durable workflow tables for the @adonis-agora/durable `lucid` state store: runs, step checkpoints,
|
|
10
|
+
* the search-attribute side-table, signal waiters, buffered signals and buffered events.
|
|
11
|
+
*
|
|
12
|
+
* This migration DELEGATES to the library instead of reproducing its DDL. The schema belongs to the
|
|
13
|
+
* library — `LucidStateStore` decides what columns it reads and writes — so a hand-copied snapshot
|
|
14
|
+
* here can only ever be right until the next release. It was wrong before: the stub shipped without
|
|
15
|
+
* `last_heartbeat_at` / `heartbeat_progress`, which the store writes on every step beat, and nothing
|
|
16
|
+
* failed only because the provider's boot-time `ensureSchema()` silently `ALTER`ed them in. Calling
|
|
17
|
+
* `createDurableTables` makes that drift impossible rather than merely tested for.
|
|
18
|
+
*
|
|
19
|
+
* `createDurableTables` is idempotent (`hasTable` / `hasColumn` guarded) and additive-only, so it is
|
|
20
|
+
* safe to run against a database that already has some or all of the tables.
|
|
21
|
+
*
|
|
22
|
+
* `db` (the `Database` manager from `@adonisjs/lucid/services/db`) rather than `this.db`:
|
|
23
|
+
* `createDurableTables` needs `db.connection(name).schema`, and the `this.db` a migration gets is a
|
|
24
|
+
* `QueryClientContract` — one already-resolved client, with no `.connection()`. `this.db` still
|
|
25
|
+
* supplies the connection NAME, so `node ace migration:run --connection=x` provisions the tables on
|
|
26
|
+
* connection `x` and not on the default.
|
|
11
27
|
*/
|
|
12
28
|
export default class extends BaseSchema {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
table.bigInteger('wake_at')
|
|
24
|
-
table.string('locked_by')
|
|
25
|
-
table.bigInteger('locked_until')
|
|
26
|
-
table.integer('recovery_attempts')
|
|
27
|
-
table.text('tags')
|
|
28
|
-
table.text('search_attributes')
|
|
29
|
-
table.integer('priority')
|
|
30
|
-
table.bigInteger('created_at').notNullable()
|
|
31
|
-
table.bigInteger('updated_at').notNullable()
|
|
32
|
-
table.index(['status'], 'durable_runs_status_idx')
|
|
33
|
-
table.index(['status', 'wake_at'], 'durable_runs_due_idx')
|
|
34
|
-
table.index(['namespace', 'status', 'created_at'], 'durable_runs_namespace_idx')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
this.schema.createTable('durable_step_checkpoints', (table) => {
|
|
38
|
-
table.string('run_id').notNullable()
|
|
39
|
-
table.integer('seq').notNullable()
|
|
40
|
-
table.string('name').notNullable()
|
|
41
|
-
table.string('kind').notNullable()
|
|
42
|
-
table.string('step_id').notNullable()
|
|
43
|
-
table.string('status').notNullable()
|
|
44
|
-
table.text('input')
|
|
45
|
-
table.text('output')
|
|
46
|
-
table.text('error')
|
|
47
|
-
table.text('events')
|
|
48
|
-
table.integer('attempts').notNullable()
|
|
49
|
-
table.string('worker_group')
|
|
50
|
-
table.bigInteger('wake_at')
|
|
51
|
-
table.string('parallel_group')
|
|
52
|
-
table.bigInteger('enqueued_at')
|
|
53
|
-
table.bigInteger('started_at').notNullable()
|
|
54
|
-
table.bigInteger('finished_at').notNullable()
|
|
55
|
-
table.primary(['run_id', 'seq'])
|
|
56
|
-
table.index(['run_id', 'name'], 'durable_checkpoints_name_idx')
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
this.schema.createTable('durable_run_attributes', (table) => {
|
|
60
|
-
table.string('run_id').notNullable()
|
|
61
|
-
table.string('key').notNullable()
|
|
62
|
-
table.string('str_value')
|
|
63
|
-
table.double('num_value')
|
|
64
|
-
table.primary(['run_id', 'key'])
|
|
65
|
-
table.index(['key', 'num_value'], 'durable_run_attributes_num_idx')
|
|
66
|
-
table.index(['key', 'str_value'], 'durable_run_attributes_str_idx')
|
|
67
|
-
})
|
|
29
|
+
/**
|
|
30
|
+
* REQUIRED, not a preference. The DDL below runs through the `Database` manager, which checks out
|
|
31
|
+
* its OWN connection from the pool — it is not part of the transaction the migrator would otherwise
|
|
32
|
+
* open for this migration. With `pool: { max: 1 }` (Adonis's own SQLite guidance) that transaction
|
|
33
|
+
* would hold the only connection while `createDurableTables` waited for a free one, and the
|
|
34
|
+
* migration would hang until the acquire timeout. Nothing is lost by opting out: the statements were
|
|
35
|
+
* never inside that transaction anyway, and re-running an interrupted `createDurableTables` is a
|
|
36
|
+
* no-op.
|
|
37
|
+
*/
|
|
38
|
+
static disableTransactions = true
|
|
68
39
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
table.string('run_id').notNullable()
|
|
72
|
-
table.integer('seq').notNullable()
|
|
73
|
-
table.string('parallel_group')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
this.schema.createTable('durable_buffered_signals', (table) => {
|
|
77
|
-
table.increments('id').primary()
|
|
78
|
-
table.string('token').notNullable()
|
|
79
|
-
table.text('payload')
|
|
80
|
-
table.index(['token'], 'durable_buffered_signals_token_idx')
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// Reliable (buffered) events: a publish matching no live waiter keeps ONE copy here, consumed by
|
|
84
|
-
// the first future matching `waitForEvent`. Keyed by `name` (many waiters share a name with
|
|
85
|
-
// different `match`); `id` is the caller-minted PK; `published_at` is epoch-ms.
|
|
86
|
-
this.schema.createTable('durable_buffered_events', (table) => {
|
|
87
|
-
table.string('id').primary()
|
|
88
|
-
table.string('name').notNullable()
|
|
89
|
-
table.text('payload')
|
|
90
|
-
table.bigInteger('published_at').notNullable()
|
|
91
|
-
table.index(['name', 'published_at'], 'durable_buffered_events_name_idx')
|
|
92
|
-
})
|
|
40
|
+
async up() {
|
|
41
|
+
await createDurableTables(db, this.db.connectionName)
|
|
93
42
|
}
|
|
94
43
|
|
|
95
44
|
async down() {
|
|
96
|
-
this.
|
|
97
|
-
this.schema.dropTableIfExists('durable_buffered_signals')
|
|
98
|
-
this.schema.dropTableIfExists('durable_signal_waiters')
|
|
99
|
-
this.schema.dropTableIfExists('durable_run_attributes')
|
|
100
|
-
this.schema.dropTableIfExists('durable_step_checkpoints')
|
|
101
|
-
this.schema.dropTableIfExists('durable_workflow_runs')
|
|
45
|
+
await dropDurableTables(db, this.db.connectionName)
|
|
102
46
|
}
|
|
103
47
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonis-agora/durable",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Durable cross-app workflows for AdonisJS — deterministic replay engine, AdonisJS binding, ace commands, dashboard, OpenTelemetry, Telescope, testing harness and Redis admission, all in one package. Part of the Agora ecosystem.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -158,6 +158,7 @@
|
|
|
158
158
|
"@opentelemetry/api": "^1.9.0",
|
|
159
159
|
"@opentelemetry/context-async-hooks": "^1.30.0",
|
|
160
160
|
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
161
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
161
162
|
"@types/node": "^20.0.0",
|
|
162
163
|
"better-sqlite3": "^11.0.0",
|
|
163
164
|
"bullmq": "^5.0.0",
|
|
@@ -168,7 +169,7 @@
|
|
|
168
169
|
"zod": "^3.25.0"
|
|
169
170
|
},
|
|
170
171
|
"engines": {
|
|
171
|
-
"node": ">=20.6.0"
|
|
172
|
+
"node": ">=20.6.0 <23"
|
|
172
173
|
},
|
|
173
174
|
"keywords": [
|
|
174
175
|
"adonisjs",
|
|
@@ -184,10 +185,12 @@
|
|
|
184
185
|
"agora"
|
|
185
186
|
],
|
|
186
187
|
"scripts": {
|
|
187
|
-
"build": "tsc -p tsconfig.json && pnpm run copy:stubs",
|
|
188
|
+
"build": "pnpm run clean && tsc -p tsconfig.build.json && pnpm run copy:stubs && pnpm run check:dist",
|
|
189
|
+
"check:dist": "node ../../scripts/assert-build-output.mjs dist src/index.js",
|
|
190
|
+
"clean": "rm -rf dist",
|
|
188
191
|
"copy:stubs": "mkdir -p dist/stubs/config dist/stubs/database/migrations dist/stubs/make/workflow dist/assets && cp stubs/config/durable.stub dist/stubs/config/durable.stub && cp stubs/config/durable_dashboard.stub dist/stubs/config/durable_dashboard.stub && cp -r stubs/database/migrations/. dist/stubs/database/migrations/ && cp stubs/make/workflow/main.stub dist/stubs/make/workflow/main.stub && cp assets/dashboard.html dist/assets/dashboard.html",
|
|
189
192
|
"test": "vitest run --passWithNoTests",
|
|
190
193
|
"test:watch": "vitest",
|
|
191
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
194
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.tests.json"
|
|
192
195
|
}
|
|
193
196
|
}
|