@smthrs/run-store 0.0.0-stage → 1.0.0-rc.4
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 +112 -0
- package/LICENSE +21 -0
- package/README.md +195 -2
- package/dist/cjs/AttemptStore.d.ts +359 -0
- package/dist/cjs/AttemptStore.d.ts.map +1 -0
- package/dist/cjs/AttemptStore.js +731 -0
- package/dist/cjs/AttemptStore.js.map +7 -0
- package/dist/cjs/Heartbeat.d.ts +46 -0
- package/dist/cjs/Heartbeat.d.ts.map +1 -0
- package/dist/cjs/Heartbeat.js +28 -0
- package/dist/cjs/Heartbeat.js.map +7 -0
- package/dist/cjs/Migrations.d.ts +42 -0
- package/dist/cjs/Migrations.d.ts.map +1 -0
- package/dist/cjs/Migrations.js +55 -0
- package/dist/cjs/Migrations.js.map +7 -0
- package/dist/cjs/Ownership.d.ts +275 -0
- package/dist/cjs/Ownership.d.ts.map +1 -0
- package/dist/cjs/Ownership.js +129 -0
- package/dist/cjs/Ownership.js.map +7 -0
- package/dist/cjs/RunStore.d.ts +571 -0
- package/dist/cjs/RunStore.d.ts.map +1 -0
- package/dist/cjs/RunStore.js +1079 -0
- package/dist/cjs/RunStore.js.map +7 -0
- package/dist/cjs/RunStoreMetrics.d.ts +151 -0
- package/dist/cjs/RunStoreMetrics.d.ts.map +1 -0
- package/dist/cjs/RunStoreMetrics.js +91 -0
- package/dist/cjs/RunStoreMetrics.js.map +7 -0
- package/dist/cjs/index.d.ts +47 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +43 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/Boundary.d.ts +80 -0
- package/dist/cjs/internal/Boundary.d.ts.map +1 -0
- package/dist/cjs/internal/Boundary.js +92 -0
- package/dist/cjs/internal/Boundary.js.map +7 -0
- package/dist/cjs/internal/Companion.d.ts +44 -0
- package/dist/cjs/internal/Companion.d.ts.map +1 -0
- package/dist/cjs/internal/Companion.js +50 -0
- package/dist/cjs/internal/Companion.js.map +7 -0
- package/dist/cjs/internal/SpanOutcome.d.ts +37 -0
- package/dist/cjs/internal/SpanOutcome.d.ts.map +1 -0
- package/dist/cjs/internal/SpanOutcome.js +62 -0
- package/dist/cjs/internal/SpanOutcome.js.map +7 -0
- package/dist/cjs/migrations/0001_initial.d.ts +15 -0
- package/dist/cjs/migrations/0001_initial.d.ts.map +1 -0
- package/dist/cjs/migrations/0001_initial.js +110 -0
- package/dist/cjs/migrations/0001_initial.js.map +7 -0
- package/dist/cjs/migrations/0002_lineage.d.ts +27 -0
- package/dist/cjs/migrations/0002_lineage.d.ts.map +1 -0
- package/dist/cjs/migrations/0002_lineage.js +43 -0
- package/dist/cjs/migrations/0002_lineage.js.map +7 -0
- package/dist/cjs/migrations/0003_execution_revisions.d.ts +15 -0
- package/dist/cjs/migrations/0003_execution_revisions.d.ts.map +1 -0
- package/dist/cjs/migrations/0003_execution_revisions.js +77 -0
- package/dist/cjs/migrations/0003_execution_revisions.js.map +7 -0
- package/dist/cjs/migrations/0004_waiting_request.d.ts +32 -0
- package/dist/cjs/migrations/0004_waiting_request.d.ts.map +1 -0
- package/dist/cjs/migrations/0004_waiting_request.js +42 -0
- package/dist/cjs/migrations/0004_waiting_request.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/TestRunStore.d.ts +17 -0
- package/dist/cjs/test/TestRunStore.d.ts.map +1 -0
- package/dist/cjs/test/TestRunStore.js +42 -0
- package/dist/cjs/test/TestRunStore.js.map +7 -0
- package/dist/esm/AttemptStore.d.ts +359 -0
- package/dist/esm/AttemptStore.d.ts.map +1 -0
- package/dist/esm/AttemptStore.js +835 -0
- package/dist/esm/AttemptStore.js.map +1 -0
- package/dist/esm/Heartbeat.d.ts +46 -0
- package/dist/esm/Heartbeat.d.ts.map +1 -0
- package/dist/esm/Heartbeat.js +46 -0
- package/dist/esm/Heartbeat.js.map +1 -0
- package/dist/esm/Migrations.d.ts +42 -0
- package/dist/esm/Migrations.d.ts.map +1 -0
- package/dist/esm/Migrations.js +56 -0
- package/dist/esm/Migrations.js.map +1 -0
- package/dist/esm/Ownership.d.ts +275 -0
- package/dist/esm/Ownership.d.ts.map +1 -0
- package/dist/esm/Ownership.js +299 -0
- package/dist/esm/Ownership.js.map +1 -0
- package/dist/esm/RunStore.d.ts +571 -0
- package/dist/esm/RunStore.d.ts.map +1 -0
- package/dist/esm/RunStore.js +1287 -0
- package/dist/esm/RunStore.js.map +1 -0
- package/dist/esm/RunStoreMetrics.d.ts +151 -0
- package/dist/esm/RunStoreMetrics.d.ts.map +1 -0
- package/dist/esm/RunStoreMetrics.js +120 -0
- package/dist/esm/RunStoreMetrics.js.map +1 -0
- package/dist/esm/index.d.ts +47 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +47 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/Boundary.d.ts +80 -0
- package/dist/esm/internal/Boundary.d.ts.map +1 -0
- package/dist/esm/internal/Boundary.js +109 -0
- package/dist/esm/internal/Boundary.js.map +1 -0
- package/dist/esm/internal/Companion.d.ts +44 -0
- package/dist/esm/internal/Companion.d.ts.map +1 -0
- package/dist/esm/internal/Companion.js +53 -0
- package/dist/esm/internal/Companion.js.map +1 -0
- package/dist/esm/internal/SpanOutcome.d.ts +37 -0
- package/dist/esm/internal/SpanOutcome.d.ts.map +1 -0
- package/dist/esm/internal/SpanOutcome.js +48 -0
- package/dist/esm/internal/SpanOutcome.js.map +1 -0
- package/dist/esm/migrations/0001_initial.d.ts +15 -0
- package/dist/esm/migrations/0001_initial.d.ts.map +1 -0
- package/dist/esm/migrations/0001_initial.js +88 -0
- package/dist/esm/migrations/0001_initial.js.map +1 -0
- package/dist/esm/migrations/0002_lineage.d.ts +27 -0
- package/dist/esm/migrations/0002_lineage.d.ts.map +1 -0
- package/dist/esm/migrations/0002_lineage.js +33 -0
- package/dist/esm/migrations/0002_lineage.js.map +1 -0
- package/dist/esm/migrations/0003_execution_revisions.d.ts +15 -0
- package/dist/esm/migrations/0003_execution_revisions.d.ts.map +1 -0
- package/dist/esm/migrations/0003_execution_revisions.js +58 -0
- package/dist/esm/migrations/0003_execution_revisions.js.map +1 -0
- package/dist/esm/migrations/0004_waiting_request.d.ts +32 -0
- package/dist/esm/migrations/0004_waiting_request.d.ts.map +1 -0
- package/dist/esm/migrations/0004_waiting_request.js +37 -0
- package/dist/esm/migrations/0004_waiting_request.js.map +1 -0
- package/dist/esm/test/TestRunStore.d.ts +17 -0
- package/dist/esm/test/TestRunStore.d.ts.map +1 -0
- package/dist/esm/test/TestRunStore.js +19 -0
- package/dist/esm/test/TestRunStore.js.map +1 -0
- package/docs/README.md +142 -0
- package/docs/api.md +901 -0
- package/docs/concepts/durable-values.md +140 -0
- package/docs/concepts/execution-revisions.md +53 -0
- package/docs/concepts/fencing.md +146 -0
- package/docs/concepts/leases.md +154 -0
- package/docs/concepts/liveness-evidence.md +142 -0
- package/docs/guides/cancel-a-run.md +156 -0
- package/docs/guides/claim-and-finish-a-run.md +175 -0
- package/docs/guides/compose-the-stores.md +142 -0
- package/docs/guides/observe-outcomes.md +182 -0
- package/docs/guides/record-step-attempts.md +170 -0
- package/docs/guides/recover-a-stalled-run.md +173 -0
- package/docs/guides/testing.md +141 -0
- package/docs/installation.md +109 -0
- package/docs/quickstart.md +201 -0
- package/docs/troubleshooting.md +255 -0
- package/package.json +183 -3
- package/src/AttemptStore.ts +1195 -0
- package/src/Heartbeat.ts +47 -0
- package/src/Migrations.ts +59 -0
- package/src/Ownership.ts +407 -0
- package/src/RunStore.ts +2063 -0
- package/src/RunStoreMetrics.ts +165 -0
- package/src/index.ts +51 -0
- package/src/internal/Boundary.ts +130 -0
- package/src/internal/Companion.ts +64 -0
- package/src/internal/SpanOutcome.ts +71 -0
- package/src/migrations/0001_initial.ts +114 -0
- package/src/migrations/0002_lineage.ts +38 -0
- package/src/migrations/0003_execution_revisions.ts +69 -0
- package/src/migrations/0004_waiting_request.ts +39 -0
- package/src/test/TestRunStore.ts +22 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var index_exports = {};
|
|
30
|
+
__export(index_exports, {
|
|
31
|
+
AttemptStore: () => AttemptStore,
|
|
32
|
+
Migrations: () => Migrations,
|
|
33
|
+
Ownership: () => Ownership,
|
|
34
|
+
RunStore: () => RunStore,
|
|
35
|
+
RunStoreMetrics: () => RunStoreMetrics
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
var RunStore = __toESM(require("./RunStore.js"), 1);
|
|
39
|
+
var RunStoreMetrics = __toESM(require("./RunStoreMetrics.js"), 1);
|
|
40
|
+
var Ownership = __toESM(require("./Ownership.js"), 1);
|
|
41
|
+
var AttemptStore = __toESM(require("./AttemptStore.js"), 1);
|
|
42
|
+
var Migrations = __toESM(require("./Migrations.js"), 1);
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Durable run state: what is running now, and who owns it.\n *\n * `RunStore` and `AttemptStore` hold the executable authoritative state that\n * recovery reads; `Ownership` supplies the liveness evidence and heartbeat\n * supervision that arbitrate it. The fencing token they trade in, `OwnerId`,\n * is defined by `@smthrs/journal`, because the journal is what it fences, and\n * is re-exported from `Ownership` here, so importing it needs no second\n * package.\n *\n * This entry point is browser-bundleable: every service here is written\n * against the driver-neutral `@smthrs/database` contract. The test double,\n * which binds a Node SQLite database, lives under an explicit subpath:\n *\n * ```ts\n * import { AttemptStore, Ownership, RunStore } from \"@smthrs/run-store\"\n * import * as TestRunStore from \"@smthrs/run-store/test/TestRunStore\"\n * ```\n *\n * @since 0.1.0\n */\n\n/**\n * @category services\n * @since 0.1.0\n */\nexport * as RunStore from \"./RunStore.ts\"\n\n/**\n * @category metrics\n * @since 0.1.0\n */\nexport * as RunStoreMetrics from \"./RunStoreMetrics.ts\"\n\n/**\n * @category ownership\n * @since 0.1.0\n */\nexport * as Ownership from \"./Ownership.ts\"\n\n/**\n * @category services\n * @since 0.1.0\n */\nexport * as AttemptStore from \"./AttemptStore.ts\"\n\n/**\n * @category migrations\n * @since 0.1.0\n */\nexport * as Migrations from \"./Migrations.ts\"\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BA,eAA0B;AAM1B,sBAAiC;AAMjC,gBAA2B;AAM3B,mBAA8B;AAM9B,iBAA4B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inert text and JSON admission for values crossing run-store boundaries.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0-rc.0
|
|
5
|
+
* @private
|
|
6
|
+
*/
|
|
7
|
+
import * as BoundedJson from "@smthrs/canonical/BoundedJson";
|
|
8
|
+
/**
|
|
9
|
+
* Maximum UTF-16 length of one durable identifier.
|
|
10
|
+
*
|
|
11
|
+
* @since 1.0.0-rc.0
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export declare const maximumIdentifierLength = 1024;
|
|
15
|
+
/**
|
|
16
|
+
* Resource limits for one admitted JSON tree.
|
|
17
|
+
*
|
|
18
|
+
* @since 1.0.0-rc.0
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
export type JsonLimits = Omit<BoundedJson.Limits, "maxTotalMembers">;
|
|
22
|
+
/**
|
|
23
|
+
* Detached JSON value accepted by the persistence boundary.
|
|
24
|
+
*
|
|
25
|
+
* @since 1.0.0-rc.0
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
export type Json = BoundedJson.Json;
|
|
29
|
+
/**
|
|
30
|
+
* Compares admitted JSON trees while ignoring object key order.
|
|
31
|
+
*
|
|
32
|
+
* Array order remains significant. `undefined` represents an absent optional
|
|
33
|
+
* tree and equals only `undefined`.
|
|
34
|
+
*
|
|
35
|
+
* @since 1.0.0-rc.0
|
|
36
|
+
* @private
|
|
37
|
+
*/
|
|
38
|
+
export declare const sameJson: (left: Json | undefined, right: Json | undefined) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Result of admitting or refusing an unknown JSON candidate.
|
|
41
|
+
*
|
|
42
|
+
* @since 1.0.0-rc.0
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
export type JsonResult = {
|
|
46
|
+
readonly ok: true;
|
|
47
|
+
readonly value: Json;
|
|
48
|
+
readonly bytes: number;
|
|
49
|
+
} | {
|
|
50
|
+
readonly ok: false;
|
|
51
|
+
readonly complaint: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Whether text has a complete UTF-16 encoding and contains no NUL.
|
|
55
|
+
*
|
|
56
|
+
* @since 1.0.0-rc.0
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
export declare const isDurableText: (value: unknown, maximum?: number) => value is string;
|
|
60
|
+
/**
|
|
61
|
+
* Copies an inert JSON tree with a cumulative member budget for run state.
|
|
62
|
+
* @private
|
|
63
|
+
* @since 1.0.0
|
|
64
|
+
*/
|
|
65
|
+
export declare const admitJson: (input: unknown, limits: JsonLimits) => JsonResult;
|
|
66
|
+
/**
|
|
67
|
+
* Parses and bounds JSON text while preserving the caller's original bytes.
|
|
68
|
+
*
|
|
69
|
+
* @since 1.0.0-rc.0
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
export declare const admitJsonText: (input: unknown, limits: JsonLimits) => {
|
|
73
|
+
readonly ok: true;
|
|
74
|
+
readonly value: string;
|
|
75
|
+
readonly json: Json;
|
|
76
|
+
} | {
|
|
77
|
+
readonly ok: false;
|
|
78
|
+
readonly complaint: string;
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=Boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Boundary.d.ts","sourceRoot":"","sources":["../../../src/internal/Boundary.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,WAAW,MAAM,+BAA+B,CAAA;AAE5D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,OAAQ,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAA;AAEnC;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,GAAI,MAAM,IAAI,GAAG,SAAS,EAAE,OAAO,IAAI,GAAG,SAAS,KAAG,OAqB1E,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,EAAE,gBAAiC,KAAG,KAAK,IAAI,MAU1F,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,OAAO,EAAE,QAAQ,UAAU,KAAG,UAG9D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,OAAO,EACd,QAAQ,UAAU,KAEhB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAenD,CAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var Boundary_exports = {};
|
|
30
|
+
__export(Boundary_exports, {
|
|
31
|
+
admitJson: () => admitJson,
|
|
32
|
+
admitJsonText: () => admitJsonText,
|
|
33
|
+
isDurableText: () => isDurableText,
|
|
34
|
+
maximumIdentifierLength: () => maximumIdentifierLength,
|
|
35
|
+
sameJson: () => sameJson
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(Boundary_exports);
|
|
38
|
+
var BoundedJson = __toESM(require("@smthrs/canonical/BoundedJson"), 1);
|
|
39
|
+
const maximumIdentifierLength = 1024;
|
|
40
|
+
const sameJson = (left, right) => {
|
|
41
|
+
if (left === right) return true;
|
|
42
|
+
if (left === void 0 || right === void 0) return false;
|
|
43
|
+
if (left === null || right === null) return false;
|
|
44
|
+
if (typeof left !== "object" || typeof right !== "object") return false;
|
|
45
|
+
if (Array.isArray(left)) {
|
|
46
|
+
if (!Array.isArray(right) || left.length !== right.length) return false;
|
|
47
|
+
for (let index = 0; index < left.length; index++) {
|
|
48
|
+
if (!sameJson(left[index], right[index])) return false;
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(right)) return false;
|
|
53
|
+
const leftObject = left;
|
|
54
|
+
const rightObject = right;
|
|
55
|
+
const leftKeys = Object.keys(leftObject);
|
|
56
|
+
if (leftKeys.length !== Object.keys(rightObject).length) return false;
|
|
57
|
+
for (const key of leftKeys) {
|
|
58
|
+
if (!Object.hasOwn(rightObject, key) || !sameJson(leftObject[key], rightObject[key])) return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
62
|
+
const isDurableText = (value, maximum = maximumIdentifierLength) => {
|
|
63
|
+
if (typeof value !== "string" || value.length === 0 || value.length > maximum || value.includes("\0")) return false;
|
|
64
|
+
for (let index = 0; index < value.length; index++) {
|
|
65
|
+
const unit = value.charCodeAt(index);
|
|
66
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
67
|
+
const low = value.charCodeAt(++index);
|
|
68
|
+
if (!(low >= 56320 && low <= 57343)) return false;
|
|
69
|
+
} else if (unit >= 56320 && unit <= 57343) return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
};
|
|
73
|
+
const admitJson = (input, limits) => {
|
|
74
|
+
const result = BoundedJson.admit(input, { ...limits, maxTotalMembers: limits.maxMembers });
|
|
75
|
+
return result.ok ? result : { ok: false, complaint: result.complaint };
|
|
76
|
+
};
|
|
77
|
+
const admitJsonText = (input, limits) => {
|
|
78
|
+
if (typeof input !== "string" || input.length === 0) return { ok: false, complaint: "must be non-empty JSON text" };
|
|
79
|
+
let parsed;
|
|
80
|
+
try {
|
|
81
|
+
parsed = JSON.parse(input);
|
|
82
|
+
} catch {
|
|
83
|
+
return { ok: false, complaint: "must be valid JSON text" };
|
|
84
|
+
}
|
|
85
|
+
const admitted = admitJson(parsed, limits);
|
|
86
|
+
if (!admitted.ok) return admitted;
|
|
87
|
+
if (limits.maxBytes !== void 0 && new TextEncoder().encode(input).byteLength > limits.maxBytes) {
|
|
88
|
+
return { ok: false, complaint: "exceeds the JSON byte limit" };
|
|
89
|
+
}
|
|
90
|
+
return { ok: true, value: input, json: admitted.value };
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=Boundary.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/internal/Boundary.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Inert text and JSON admission for values crossing run-store boundaries.\n *\n * @since 1.0.0-rc.0\n * @private\n */\n\nimport * as BoundedJson from \"@smthrs/canonical/BoundedJson\"\n\n/**\n * Maximum UTF-16 length of one durable identifier.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const maximumIdentifierLength = 1_024\n\n/**\n * Resource limits for one admitted JSON tree.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport type JsonLimits = Omit<BoundedJson.Limits, \"maxTotalMembers\">\n\n/**\n * Detached JSON value accepted by the persistence boundary.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport type Json = BoundedJson.Json\n\n/**\n * Compares admitted JSON trees while ignoring object key order.\n *\n * Array order remains significant. `undefined` represents an absent optional\n * tree and equals only `undefined`.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const sameJson = (left: Json | undefined, right: Json | undefined): boolean => {\n if (left === right) return true\n if (left === undefined || right === undefined) return false\n if (left === null || right === null) return false\n if (typeof left !== \"object\" || typeof right !== \"object\") return false\n if (Array.isArray(left)) {\n if (!Array.isArray(right) || left.length !== right.length) return false\n for (let index = 0; index < left.length; index++) {\n if (!sameJson(left[index], right[index])) return false\n }\n return true\n }\n if (Array.isArray(right)) return false\n const leftObject = left as { readonly [key: string]: Json }\n const rightObject = right as { readonly [key: string]: Json }\n const leftKeys = Object.keys(leftObject)\n if (leftKeys.length !== Object.keys(rightObject).length) return false\n for (const key of leftKeys) {\n if (!Object.hasOwn(rightObject, key) || !sameJson(leftObject[key], rightObject[key])) return false\n }\n return true\n}\n\n/**\n * Result of admitting or refusing an unknown JSON candidate.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport type JsonResult =\n | { readonly ok: true; readonly value: Json; readonly bytes: number }\n | { readonly ok: false; readonly complaint: string }\n\n/**\n * Whether text has a complete UTF-16 encoding and contains no NUL.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const isDurableText = (value: unknown, maximum = maximumIdentifierLength): value is string => {\n if (typeof value !== \"string\" || value.length === 0 || value.length > maximum || value.includes(\"\\0\")) return false\n for (let index = 0; index < value.length; index++) {\n const unit = value.charCodeAt(index)\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const low = value.charCodeAt(++index)\n if (!(low >= 0xdc00 && low <= 0xdfff)) return false\n } else if (unit >= 0xdc00 && unit <= 0xdfff) return false\n }\n return true\n}\n\n/**\n * Copies an inert JSON tree with a cumulative member budget for run state.\n * @private\n * @since 1.0.0\n */\nexport const admitJson = (input: unknown, limits: JsonLimits): JsonResult => {\n const result = BoundedJson.admit(input, { ...limits, maxTotalMembers: limits.maxMembers })\n return result.ok ? result : { ok: false, complaint: result.complaint }\n}\n\n/**\n * Parses and bounds JSON text while preserving the caller's original bytes.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const admitJsonText = (\n input: unknown,\n limits: JsonLimits\n):\n | { readonly ok: true; readonly value: string; readonly json: Json }\n | { readonly ok: false; readonly complaint: string } =>\n{\n if (typeof input !== \"string\" || input.length === 0) return { ok: false, complaint: \"must be non-empty JSON text\" }\n let parsed: unknown\n try {\n parsed = JSON.parse(input) as unknown\n } catch {\n return { ok: false, complaint: \"must be valid JSON text\" }\n }\n const admitted = admitJson(parsed, limits)\n if (!admitted.ok) return admitted\n if (limits.maxBytes !== undefined && new TextEncoder().encode(input).byteLength > limits.maxBytes) {\n return { ok: false, complaint: \"exceeds the JSON byte limit\" }\n }\n return { ok: true, value: input, json: admitted.value }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,kBAA6B;AAQtB,MAAM,0BAA0B;AA2BhC,MAAM,WAAW,CAAC,MAAwB,UAAqC;AACpF,MAAI,SAAS,MAAO,QAAO;AAC3B,MAAI,SAAS,UAAa,UAAU,OAAW,QAAO;AACtD,MAAI,SAAS,QAAQ,UAAU,KAAM,QAAO;AAC5C,MAAI,OAAO,SAAS,YAAY,OAAO,UAAU,SAAU,QAAO;AAClE,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,KAAK,WAAW,MAAM,OAAQ,QAAO;AAClE,aAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AAChD,UAAI,CAAC,SAAS,KAAK,KAAK,GAAG,MAAM,KAAK,CAAC,EAAG,QAAO;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,WAAW,OAAO,KAAK,UAAU;AACvC,MAAI,SAAS,WAAW,OAAO,KAAK,WAAW,EAAE,OAAQ,QAAO;AAChE,aAAW,OAAO,UAAU;AAC1B,QAAI,CAAC,OAAO,OAAO,aAAa,GAAG,KAAK,CAAC,SAAS,WAAW,GAAG,GAAG,YAAY,GAAG,CAAC,EAAG,QAAO;AAAA,EAC/F;AACA,SAAO;AACT;AAkBO,MAAM,gBAAgB,CAAC,OAAgB,UAAU,4BAA6C;AACnG,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,KAAK,MAAM,SAAS,WAAW,MAAM,SAAS,IAAI,EAAG,QAAO;AAC9G,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AACjD,UAAM,OAAO,MAAM,WAAW,KAAK;AACnC,QAAI,QAAQ,SAAU,QAAQ,OAAQ;AACpC,YAAM,MAAM,MAAM,WAAW,EAAE,KAAK;AACpC,UAAI,EAAE,OAAO,SAAU,OAAO,OAAS,QAAO;AAAA,IAChD,WAAW,QAAQ,SAAU,QAAQ,MAAQ,QAAO;AAAA,EACtD;AACA,SAAO;AACT;AAOO,MAAM,YAAY,CAAC,OAAgB,WAAmC;AAC3E,QAAM,SAAS,YAAY,MAAM,OAAO,EAAE,GAAG,QAAQ,iBAAiB,OAAO,WAAW,CAAC;AACzF,SAAO,OAAO,KAAK,SAAS,EAAE,IAAI,OAAO,WAAW,OAAO,UAAU;AACvE;AAQO,MAAM,gBAAgB,CAC3B,OACA,WAIF;AACE,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,EAAG,QAAO,EAAE,IAAI,OAAO,WAAW,8BAA8B;AAClH,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,KAAK;AAAA,EAC3B,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,WAAW,0BAA0B;AAAA,EAC3D;AACA,QAAM,WAAW,UAAU,QAAQ,MAAM;AACzC,MAAI,CAAC,SAAS,GAAI,QAAO;AACzB,MAAI,OAAO,aAAa,UAAa,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,aAAa,OAAO,UAAU;AACjG,WAAO,EAAE,IAAI,OAAO,WAAW,8BAA8B;AAAA,EAC/D;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,OAAO,MAAM,SAAS,MAAM;AACxD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run store's companion journal stream.
|
|
3
|
+
*
|
|
4
|
+
* Facts the run store records about a run go to the run's `run-store`
|
|
5
|
+
* companion stream (`JournalEvent.companionRunId`), never to the run's own
|
|
6
|
+
* stream: engine, control, and time-travel consumers read that stream by
|
|
7
|
+
* position, and a rewind or compaction of it must not truncate a store fact.
|
|
8
|
+
*
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
import { type JournalError } from "@smthrs/journal/Journal";
|
|
13
|
+
import { Effect } from "effect";
|
|
14
|
+
/**
|
|
15
|
+
* The companion stream name.
|
|
16
|
+
*
|
|
17
|
+
* @since 1.0.0
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
export declare const stream = "run-store";
|
|
21
|
+
/**
|
|
22
|
+
* The producer every run-store fact is appended under.
|
|
23
|
+
*
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
* @private
|
|
26
|
+
*/
|
|
27
|
+
export declare const sourceId = "flows.run-store";
|
|
28
|
+
/**
|
|
29
|
+
* Appends one fact to the run's companion stream through the journal in the
|
|
30
|
+
* caller's context.
|
|
31
|
+
*
|
|
32
|
+
* The journal is resolved at call time: the ordinary composition builds the
|
|
33
|
+
* store beside the journal (`Layer.mergeAll(SqlJournal.layer(...),
|
|
34
|
+
* RunStore.layer)`), so the journal reaches the store only through the
|
|
35
|
+
* caller's context. A caller running without a journal records nothing. The
|
|
36
|
+
* append is unfenced — the store arbitrated the change in the same serialized
|
|
37
|
+
* transaction — and joins that transaction as a savepoint, so a rolled-back
|
|
38
|
+
* change leaves no fact.
|
|
39
|
+
*
|
|
40
|
+
* @since 1.0.0
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
export declare const append: (runId: string, eventType: string, payload: Readonly<Record<string, unknown>>) => Effect.Effect<void, JournalError>;
|
|
44
|
+
//# sourceMappingURL=Companion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Companion.d.ts","sourceRoot":"","sources":["../../../src/internal/Companion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEpE,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,MAAM,cAAc,CAAA;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,oBAAoB,CAAA;AAEzC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,GACjB,OAAO,MAAM,EACb,WAAW,MAAM,EACjB,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KACzC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAYP,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var Companion_exports = {};
|
|
30
|
+
__export(Companion_exports, {
|
|
31
|
+
append: () => append,
|
|
32
|
+
sourceId: () => sourceId,
|
|
33
|
+
stream: () => stream
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(Companion_exports);
|
|
36
|
+
var import_Journal = require("@smthrs/journal/Journal");
|
|
37
|
+
var JournalEvent = __toESM(require("@smthrs/journal/JournalEvent"), 1);
|
|
38
|
+
var import_effect = require("effect");
|
|
39
|
+
const stream = "run-store";
|
|
40
|
+
const sourceId = "flows.run-store";
|
|
41
|
+
const append = (runId, eventType, payload) => import_effect.Effect.flatMap(import_effect.Effect.serviceOption(import_Journal.Journal), (journal) => import_effect.Option.isNone(journal) ? import_effect.Effect.void : journal.value.emitDurableUnfenced(
|
|
42
|
+
new JournalEvent.Input({
|
|
43
|
+
runId: JournalEvent.companionRunId(stream, runId),
|
|
44
|
+
sourceId,
|
|
45
|
+
eventType,
|
|
46
|
+
payload: { runId, ...payload },
|
|
47
|
+
meta: { runId }
|
|
48
|
+
})
|
|
49
|
+
).pipe(import_effect.Effect.asVoid));
|
|
50
|
+
//# sourceMappingURL=Companion.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/internal/Companion.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The run store's companion journal stream.\n *\n * Facts the run store records about a run go to the run's `run-store`\n * companion stream (`JournalEvent.companionRunId`), never to the run's own\n * stream: engine, control, and time-travel consumers read that stream by\n * position, and a rewind or compaction of it must not truncate a store fact.\n *\n * @since 1.0.0\n * @private\n */\n\nimport { Journal, type JournalError } from \"@smthrs/journal/Journal\"\nimport * as JournalEvent from \"@smthrs/journal/JournalEvent\"\nimport { Effect, Option } from \"effect\"\n\n/**\n * The companion stream name.\n *\n * @since 1.0.0\n * @private\n */\nexport const stream = \"run-store\"\n\n/**\n * The producer every run-store fact is appended under.\n *\n * @since 1.0.0\n * @private\n */\nexport const sourceId = \"flows.run-store\"\n\n/**\n * Appends one fact to the run's companion stream through the journal in the\n * caller's context.\n *\n * The journal is resolved at call time: the ordinary composition builds the\n * store beside the journal (`Layer.mergeAll(SqlJournal.layer(...),\n * RunStore.layer)`), so the journal reaches the store only through the\n * caller's context. A caller running without a journal records nothing. The\n * append is unfenced \u2014 the store arbitrated the change in the same serialized\n * transaction \u2014 and joins that transaction as a savepoint, so a rolled-back\n * change leaves no fact.\n *\n * @since 1.0.0\n * @private\n */\nexport const append = (\n runId: string,\n eventType: string,\n payload: Readonly<Record<string, unknown>>\n): Effect.Effect<void, JournalError> =>\n Effect.flatMap(Effect.serviceOption(Journal), (journal) =>\n Option.isNone(journal)\n ? Effect.void\n : journal.value.emitDurableUnfenced(\n new JournalEvent.Input({\n runId: JournalEvent.companionRunId(stream, runId),\n sourceId: sourceId as JournalEvent.SourceId,\n eventType,\n payload: { runId, ...payload },\n meta: { runId }\n })\n ).pipe(Effect.asVoid))\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,qBAA2C;AAC3C,mBAA8B;AAC9B,oBAA+B;AAQxB,MAAM,SAAS;AAQf,MAAM,WAAW;AAiBjB,MAAM,SAAS,CACpB,OACA,WACA,YAEA,qBAAO,QAAQ,qBAAO,cAAc,sBAAO,GAAG,CAAC,YAC7C,qBAAO,OAAO,OAAO,IACjB,qBAAO,OACP,QAAQ,MAAM;AAAA,EACd,IAAI,aAAa,MAAM;AAAA,IACrB,OAAO,aAAa,eAAe,QAAQ,KAAK;AAAA,IAChD;AAAA,IACA;AAAA,IACA,SAAS,EAAE,OAAO,GAAG,QAAQ;AAAA,IAC7B,MAAM,EAAE,MAAM;AAAA,EAChB,CAAC;AACH,EAAE,KAAK,qBAAO,MAAM,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closes every store operation span with an `outcome` attribute, so a trace
|
|
3
|
+
* viewer never sees a span that ended without saying how. `RunStore` and
|
|
4
|
+
* `AttemptStore` share these observers so the guide can describe one rule.
|
|
5
|
+
*
|
|
6
|
+
* @since 1.0.0-rc.0
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Metric from "effect/Metric";
|
|
11
|
+
/**
|
|
12
|
+
* Observes a store operation's exit onto its span, and, when the operation
|
|
13
|
+
* has an outcome-keyed counter, updates it in the same observation: the
|
|
14
|
+
* domain tag (`claimed`, `fence_lost`) on success, `failure` or `interrupt`
|
|
15
|
+
* otherwise, so a span never closes without saying how and a failed write
|
|
16
|
+
* still lands in the counter. `exitMetric` is the counter view carrying every
|
|
17
|
+
* attribute but `outcome`, which this observer adds for a non-success exit.
|
|
18
|
+
* `Effect.onExit` only reads the exit; the value, cause, and interruption
|
|
19
|
+
* propagate byte-identically.
|
|
20
|
+
*
|
|
21
|
+
* @since 1.0.0-rc.0
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
export declare const observeOutcome: <A extends {
|
|
25
|
+
readonly _tag: string;
|
|
26
|
+
}>(metricOf?: ((outcome: A) => Metric.Metric<number, Metric.CounterState<number>>) | undefined, exitMetric?: Metric.Metric<number, Metric.CounterState<number>> | undefined) => <E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
27
|
+
/**
|
|
28
|
+
* `observeOutcome` for operations whose success carries no domain outcome
|
|
29
|
+
* tag: `create` inserts or fails, `get` returns the row or fails, and
|
|
30
|
+
* `acknowledgeCancel` reports whether the guarded update matched. The span
|
|
31
|
+
* still closes with `success`, `failure`, or `interrupt`.
|
|
32
|
+
*
|
|
33
|
+
* @since 1.0.0-rc.0
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
export declare const observeExit: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
37
|
+
//# sourceMappingURL=SpanOutcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpanOutcome.d.ts","sourceRoot":"","sources":["../../../src/internal/SpanOutcome.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AASvC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAChE,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,EAC3F,aAAa,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,MAE5E,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAe1D,CAAA;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAOxF,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var SpanOutcome_exports = {};
|
|
30
|
+
__export(SpanOutcome_exports, {
|
|
31
|
+
observeExit: () => observeExit,
|
|
32
|
+
observeOutcome: () => observeOutcome
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(SpanOutcome_exports);
|
|
35
|
+
var Cause = __toESM(require("effect/Cause"), 1);
|
|
36
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
37
|
+
var Metric = __toESM(require("effect/Metric"), 1);
|
|
38
|
+
const outcomeValue = (tag) => tag.replace(/(?<=[a-z0-9])(?=[A-Z])/g, "_").toLowerCase();
|
|
39
|
+
const causeOutcome = (cause) => Cause.hasInterruptsOnly(cause) ? "interrupt" : "failure";
|
|
40
|
+
const observeOutcome = (metricOf, exitMetric) => (effect) => effect.pipe(
|
|
41
|
+
Effect.onExit((exit) => {
|
|
42
|
+
if (exit._tag === "Success") {
|
|
43
|
+
return Effect.annotateCurrentSpan({ outcome: outcomeValue(exit.value._tag) }).pipe(
|
|
44
|
+
Effect.andThen(metricOf === void 0 ? Effect.void : Metric.update(metricOf(exit.value), 1))
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const outcome = causeOutcome(exit.cause);
|
|
48
|
+
return Effect.annotateCurrentSpan({ outcome }).pipe(
|
|
49
|
+
Effect.andThen(
|
|
50
|
+
exitMetric === void 0 ? Effect.void : Metric.update(Metric.withAttributes(exitMetric, { outcome }), 1)
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
const observeExit = (effect) => effect.pipe(
|
|
56
|
+
Effect.onExit(
|
|
57
|
+
(exit) => Effect.annotateCurrentSpan({
|
|
58
|
+
outcome: exit._tag === "Success" ? "success" : causeOutcome(exit.cause)
|
|
59
|
+
})
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
//# sourceMappingURL=SpanOutcome.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/internal/SpanOutcome.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Closes every store operation span with an `outcome` attribute, so a trace\n * viewer never sees a span that ended without saying how. `RunStore` and\n * `AttemptStore` share these observers so the guide can describe one rule.\n *\n * @since 1.0.0-rc.0\n * @private\n */\n\nimport * as Cause from \"effect/Cause\"\nimport * as Effect from \"effect/Effect\"\nimport * as Metric from \"effect/Metric\"\n\n/** Maps a PascalCase outcome tag to its snake_case span attribute. */\nconst outcomeValue = (tag: string): string => tag.replace(/(?<=[a-z0-9])(?=[A-Z])/g, \"_\").toLowerCase()\n\n/** Classifies a non-success exit for the span `outcome` attribute. */\nconst causeOutcome = <E>(cause: Cause.Cause<E>): \"failure\" | \"interrupt\" =>\n Cause.hasInterruptsOnly(cause) ? \"interrupt\" : \"failure\"\n\n/**\n * Observes a store operation's exit onto its span, and, when the operation\n * has an outcome-keyed counter, updates it in the same observation: the\n * domain tag (`claimed`, `fence_lost`) on success, `failure` or `interrupt`\n * otherwise, so a span never closes without saying how and a failed write\n * still lands in the counter. `exitMetric` is the counter view carrying every\n * attribute but `outcome`, which this observer adds for a non-success exit.\n * `Effect.onExit` only reads the exit; the value, cause, and interruption\n * propagate byte-identically.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const observeOutcome = <A extends { readonly _tag: string }>(\n metricOf?: ((outcome: A) => Metric.Metric<number, Metric.CounterState<number>>) | undefined,\n exitMetric?: Metric.Metric<number, Metric.CounterState<number>> | undefined\n) =>\n<E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.onExit((exit) => {\n if (exit._tag === \"Success\") {\n return Effect.annotateCurrentSpan({ outcome: outcomeValue(exit.value._tag) }).pipe(\n Effect.andThen(metricOf === undefined ? Effect.void : Metric.update(metricOf(exit.value), 1))\n )\n }\n const outcome = causeOutcome(exit.cause)\n return Effect.annotateCurrentSpan({ outcome }).pipe(\n Effect.andThen(\n exitMetric === undefined ? Effect.void : Metric.update(Metric.withAttributes(exitMetric, { outcome }), 1)\n )\n )\n })\n )\n\n/**\n * `observeOutcome` for operations whose success carries no domain outcome\n * tag: `create` inserts or fails, `get` returns the row or fails, and\n * `acknowledgeCancel` reports whether the guarded update matched. The span\n * still closes with `success`, `failure`, or `interrupt`.\n *\n * @since 1.0.0-rc.0\n * @private\n */\nexport const observeExit = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.onExit((exit) =>\n Effect.annotateCurrentSpan({\n outcome: exit._tag === \"Success\" ? \"success\" : causeOutcome(exit.cause)\n })\n )\n )\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,YAAuB;AACvB,aAAwB;AACxB,aAAwB;AAGxB,MAAM,eAAe,CAAC,QAAwB,IAAI,QAAQ,2BAA2B,GAAG,EAAE,YAAY;AAGtG,MAAM,eAAe,CAAI,UACvB,MAAM,kBAAkB,KAAK,IAAI,cAAc;AAe1C,MAAM,iBAAiB,CAC5B,UACA,eAEF,CAAO,WACL,OAAO;AAAA,EACL,OAAO,OAAO,CAAC,SAAS;AACtB,QAAI,KAAK,SAAS,WAAW;AAC3B,aAAO,OAAO,oBAAoB,EAAE,SAAS,aAAa,KAAK,MAAM,IAAI,EAAE,CAAC,EAAE;AAAA,QAC5E,OAAO,QAAQ,aAAa,SAAY,OAAO,OAAO,OAAO,OAAO,SAAS,KAAK,KAAK,GAAG,CAAC,CAAC;AAAA,MAC9F;AAAA,IACF;AACA,UAAM,UAAU,aAAa,KAAK,KAAK;AACvC,WAAO,OAAO,oBAAoB,EAAE,QAAQ,CAAC,EAAE;AAAA,MAC7C,OAAO;AAAA,QACL,eAAe,SAAY,OAAO,OAAO,OAAO,OAAO,OAAO,eAAe,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC;AAAA,MAC1G;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAWK,MAAM,cAAc,CAAU,WACnC,OAAO;AAAA,EACL,OAAO;AAAA,IAAO,CAAC,SACb,OAAO,oBAAoB;AAAA,MACzB,SAAS,KAAK,SAAS,YAAY,YAAY,aAAa,KAAK,KAAK;AAAA,IACxE,CAAC;AAAA,EACH;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initial durable run and attempt schema.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
8
|
+
/**
|
|
9
|
+
* Creates the `flows_runs` and `flows_attempts` tables and their indexes.
|
|
10
|
+
*
|
|
11
|
+
* @category migrations
|
|
12
|
+
* @since 0.1.0
|
|
13
|
+
*/
|
|
14
|
+
export declare const initial: Effect.Effect<void, unknown, SqlClient.SqlClient>;
|
|
15
|
+
//# sourceMappingURL=0001_initial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0001_initial.d.ts","sourceRoot":"","sources":["../../../src/migrations/0001_initial.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,SAAS,CAiGpE,CAAA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var initial_exports = {};
|
|
30
|
+
__export(initial_exports, {
|
|
31
|
+
initial: () => initial
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(initial_exports);
|
|
34
|
+
var Dialect = __toESM(require("@smthrs/database/Dialect"), 1);
|
|
35
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
36
|
+
var SqlClient = __toESM(require("effect/unstable/sql/SqlClient"), 1);
|
|
37
|
+
const initial = Effect.gen(function* () {
|
|
38
|
+
const sql = yield* SqlClient.SqlClient;
|
|
39
|
+
yield* sql`CREATE TABLE flows_runs (
|
|
40
|
+
${Dialect.rowId(sql)}
|
|
41
|
+
run_id TEXT PRIMARY KEY CHECK (length(run_id) > 0),
|
|
42
|
+
status TEXT NOT NULL,
|
|
43
|
+
created_at_ms ${Dialect.integer(sql)} NOT NULL CHECK (${Dialect.isInteger(sql, sql`created_at_ms`)} AND created_at_ms >= 0 AND created_at_ms <= 9007199254740991),
|
|
44
|
+
started_at_ms ${Dialect.integer(sql)} CHECK (started_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`started_at_ms`)} AND started_at_ms >= 0 AND started_at_ms <= 9007199254740991)),
|
|
45
|
+
finished_at_ms ${Dialect.integer(sql)} CHECK (finished_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`finished_at_ms`)} AND finished_at_ms >= 0 AND finished_at_ms <= 9007199254740991)),
|
|
46
|
+
owner_host_id TEXT,
|
|
47
|
+
owner_pid ${Dialect.integer(sql)},
|
|
48
|
+
owner_nonce TEXT,
|
|
49
|
+
heartbeat_at_ms ${Dialect.integer(sql)} CHECK (heartbeat_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`heartbeat_at_ms`)} AND heartbeat_at_ms >= 0 AND heartbeat_at_ms <= 9007199254740991)),
|
|
50
|
+
claim_host_id TEXT,
|
|
51
|
+
claim_pid ${Dialect.integer(sql)},
|
|
52
|
+
claim_nonce TEXT,
|
|
53
|
+
claimed_at_ms ${Dialect.integer(sql)} CHECK (claimed_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`claimed_at_ms`)} AND claimed_at_ms >= 0 AND claimed_at_ms <= 9007199254740991)),
|
|
54
|
+
parent_run_id TEXT CHECK (parent_run_id IS NULL OR length(parent_run_id) > 0),
|
|
55
|
+
cancel_requested_at_ms ${Dialect.integer(sql)} CHECK (cancel_requested_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`cancel_requested_at_ms`)} AND cancel_requested_at_ms >= 0 AND cancel_requested_at_ms <= 9007199254740991)),
|
|
56
|
+
waiting_reason TEXT CHECK (waiting_reason IS NULL OR length(waiting_reason) > 0),
|
|
57
|
+
waiting_wake_at_ms ${Dialect.integer(sql)} CHECK (waiting_wake_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`waiting_wake_at_ms`)} AND waiting_wake_at_ms >= 0 AND waiting_wake_at_ms <= 9007199254740991)),
|
|
58
|
+
waiting_token TEXT CHECK (waiting_token IS NULL OR length(waiting_token) > 0),
|
|
59
|
+
state_json TEXT NOT NULL CHECK (${Dialect.jsonValid(sql, sql`state_json`)}),
|
|
60
|
+
CHECK (status IN ('pending', 'running', 'suspended', 'completed', 'failed', 'cancelled')),
|
|
61
|
+
CHECK (
|
|
62
|
+
(
|
|
63
|
+
status = 'running' AND
|
|
64
|
+
owner_host_id IS NOT NULL AND
|
|
65
|
+
length(owner_host_id) > 0 AND
|
|
66
|
+
owner_pid IS NOT NULL AND
|
|
67
|
+
${Dialect.isInteger(sql, sql`owner_pid`)} AND owner_pid >= 0 AND
|
|
68
|
+
owner_nonce IS NOT NULL AND
|
|
69
|
+
length(owner_nonce) > 0 AND
|
|
70
|
+
heartbeat_at_ms IS NOT NULL
|
|
71
|
+
) OR (
|
|
72
|
+
status <> 'running' AND
|
|
73
|
+
owner_host_id IS NULL AND
|
|
74
|
+
owner_pid IS NULL AND
|
|
75
|
+
owner_nonce IS NULL AND
|
|
76
|
+
heartbeat_at_ms IS NULL
|
|
77
|
+
)
|
|
78
|
+
),
|
|
79
|
+
CHECK (
|
|
80
|
+
(claim_host_id IS NULL AND claim_pid IS NULL AND claim_nonce IS NULL AND claimed_at_ms IS NULL) OR
|
|
81
|
+
(claim_host_id IS NOT NULL AND length(claim_host_id) > 0 AND
|
|
82
|
+
claim_pid IS NOT NULL AND ${Dialect.isInteger(sql, sql`claim_pid`)} AND claim_pid >= 0 AND
|
|
83
|
+
claim_nonce IS NOT NULL AND length(claim_nonce) > 0 AND claimed_at_ms IS NOT NULL)
|
|
84
|
+
),
|
|
85
|
+
CHECK (
|
|
86
|
+
(waiting_reason IS NULL AND waiting_wake_at_ms IS NULL AND waiting_token IS NULL) OR
|
|
87
|
+
waiting_reason IS NOT NULL
|
|
88
|
+
),
|
|
89
|
+
FOREIGN KEY (parent_run_id) REFERENCES flows_runs (run_id)
|
|
90
|
+
)`;
|
|
91
|
+
yield* sql`CREATE INDEX flows_runs_parent_run_id_idx ON flows_runs (parent_run_id)`;
|
|
92
|
+
yield* sql`CREATE INDEX flows_runs_cancel_requested_idx ON flows_runs (cancel_requested_at_ms) WHERE cancel_requested_at_ms IS NOT NULL`;
|
|
93
|
+
yield* sql`CREATE INDEX flows_runs_waiting_reason_wake_at_idx ON flows_runs (waiting_reason, waiting_wake_at_ms) WHERE waiting_reason IS NOT NULL`;
|
|
94
|
+
yield* sql`CREATE TABLE flows_attempts (
|
|
95
|
+
run_id TEXT NOT NULL CHECK (length(run_id) > 0),
|
|
96
|
+
step_key_digest TEXT NOT NULL CHECK (length(step_key_digest) > 0),
|
|
97
|
+
attempt ${Dialect.integer(sql)} NOT NULL CHECK (${Dialect.isInteger(sql, sql`attempt`)} AND attempt >= 0 AND attempt <= 9007199254740991),
|
|
98
|
+
state TEXT NOT NULL CHECK (length(state) > 0),
|
|
99
|
+
started_at_ms ${Dialect.integer(sql)} NOT NULL CHECK (${Dialect.isInteger(sql, sql`started_at_ms`)} AND started_at_ms >= 0 AND started_at_ms <= 9007199254740991),
|
|
100
|
+
finished_at_ms ${Dialect.integer(sql)} CHECK (finished_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`finished_at_ms`)} AND finished_at_ms >= 0 AND finished_at_ms <= 9007199254740991)),
|
|
101
|
+
heartbeat_at_ms ${Dialect.integer(sql)} CHECK (heartbeat_at_ms IS NULL OR (${Dialect.isInteger(sql, sql`heartbeat_at_ms`)} AND heartbeat_at_ms >= 0 AND heartbeat_at_ms <= 9007199254740991)),
|
|
102
|
+
checkpoint_json TEXT CHECK (checkpoint_json IS NULL OR ${Dialect.jsonValid(sql, sql`checkpoint_json`)}),
|
|
103
|
+
error_json TEXT CHECK (error_json IS NULL OR ${Dialect.jsonValid(sql, sql`error_json`)}),
|
|
104
|
+
outcome_json TEXT CHECK (outcome_json IS NULL OR ${Dialect.jsonValid(sql, sql`outcome_json`)}),
|
|
105
|
+
meta_json TEXT NOT NULL CHECK (${Dialect.jsonValid(sql, sql`meta_json`)}),
|
|
106
|
+
PRIMARY KEY (run_id, step_key_digest, attempt),
|
|
107
|
+
FOREIGN KEY (run_id) REFERENCES flows_runs (run_id)
|
|
108
|
+
)`;
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=0001_initial.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/migrations/0001_initial.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Initial durable run and attempt schema.\n *\n * @since 0.1.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\n/**\n * Creates the `flows_runs` and `flows_attempts` tables and their indexes.\n *\n * @category migrations\n * @since 0.1.0\n */\nexport const initial: Effect.Effect<void, unknown, SqlClient.SqlClient> = Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n\n yield* sql`CREATE TABLE flows_runs (\n ${Dialect.rowId(sql)}\n run_id TEXT PRIMARY KEY CHECK (length(run_id) > 0),\n status TEXT NOT NULL,\n created_at_ms ${Dialect.integer(sql)} NOT NULL CHECK (${\n Dialect.isInteger(sql, sql`created_at_ms`)\n } AND created_at_ms >= 0 AND created_at_ms <= 9007199254740991),\n started_at_ms ${Dialect.integer(sql)} CHECK (started_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`started_at_ms`)\n } AND started_at_ms >= 0 AND started_at_ms <= 9007199254740991)),\n finished_at_ms ${Dialect.integer(sql)} CHECK (finished_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`finished_at_ms`)\n } AND finished_at_ms >= 0 AND finished_at_ms <= 9007199254740991)),\n owner_host_id TEXT,\n owner_pid ${Dialect.integer(sql)},\n owner_nonce TEXT,\n heartbeat_at_ms ${Dialect.integer(sql)} CHECK (heartbeat_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`heartbeat_at_ms`)\n } AND heartbeat_at_ms >= 0 AND heartbeat_at_ms <= 9007199254740991)),\n claim_host_id TEXT,\n claim_pid ${Dialect.integer(sql)},\n claim_nonce TEXT,\n claimed_at_ms ${Dialect.integer(sql)} CHECK (claimed_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`claimed_at_ms`)\n } AND claimed_at_ms >= 0 AND claimed_at_ms <= 9007199254740991)),\n parent_run_id TEXT CHECK (parent_run_id IS NULL OR length(parent_run_id) > 0),\n cancel_requested_at_ms ${Dialect.integer(sql)} CHECK (cancel_requested_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`cancel_requested_at_ms`)\n } AND cancel_requested_at_ms >= 0 AND cancel_requested_at_ms <= 9007199254740991)),\n waiting_reason TEXT CHECK (waiting_reason IS NULL OR length(waiting_reason) > 0),\n waiting_wake_at_ms ${Dialect.integer(sql)} CHECK (waiting_wake_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`waiting_wake_at_ms`)\n } AND waiting_wake_at_ms >= 0 AND waiting_wake_at_ms <= 9007199254740991)),\n waiting_token TEXT CHECK (waiting_token IS NULL OR length(waiting_token) > 0),\n state_json TEXT NOT NULL CHECK (${Dialect.jsonValid(sql, sql`state_json`)}),\n CHECK (status IN ('pending', 'running', 'suspended', 'completed', 'failed', 'cancelled')),\n CHECK (\n (\n status = 'running' AND\n owner_host_id IS NOT NULL AND\n length(owner_host_id) > 0 AND\n owner_pid IS NOT NULL AND\n ${Dialect.isInteger(sql, sql`owner_pid`)} AND owner_pid >= 0 AND\n owner_nonce IS NOT NULL AND\n length(owner_nonce) > 0 AND\n heartbeat_at_ms IS NOT NULL\n ) OR (\n status <> 'running' AND\n owner_host_id IS NULL AND\n owner_pid IS NULL AND\n owner_nonce IS NULL AND\n heartbeat_at_ms IS NULL\n )\n ),\n CHECK (\n (claim_host_id IS NULL AND claim_pid IS NULL AND claim_nonce IS NULL AND claimed_at_ms IS NULL) OR\n (claim_host_id IS NOT NULL AND length(claim_host_id) > 0 AND\n claim_pid IS NOT NULL AND ${Dialect.isInteger(sql, sql`claim_pid`)} AND claim_pid >= 0 AND\n claim_nonce IS NOT NULL AND length(claim_nonce) > 0 AND claimed_at_ms IS NOT NULL)\n ),\n CHECK (\n (waiting_reason IS NULL AND waiting_wake_at_ms IS NULL AND waiting_token IS NULL) OR\n waiting_reason IS NOT NULL\n ),\n FOREIGN KEY (parent_run_id) REFERENCES flows_runs (run_id)\n )`\n\n yield* sql`CREATE INDEX flows_runs_parent_run_id_idx ON flows_runs (parent_run_id)`\n yield* sql`CREATE INDEX flows_runs_cancel_requested_idx ON flows_runs (cancel_requested_at_ms) WHERE cancel_requested_at_ms IS NOT NULL`\n yield* sql`CREATE INDEX flows_runs_waiting_reason_wake_at_idx ON flows_runs (waiting_reason, waiting_wake_at_ms) WHERE waiting_reason IS NOT NULL`\n\n yield* sql`CREATE TABLE flows_attempts (\n run_id TEXT NOT NULL CHECK (length(run_id) > 0),\n step_key_digest TEXT NOT NULL CHECK (length(step_key_digest) > 0),\n attempt ${Dialect.integer(sql)} NOT NULL CHECK (${\n Dialect.isInteger(sql, sql`attempt`)\n } AND attempt >= 0 AND attempt <= 9007199254740991),\n state TEXT NOT NULL CHECK (length(state) > 0),\n started_at_ms ${Dialect.integer(sql)} NOT NULL CHECK (${\n Dialect.isInteger(sql, sql`started_at_ms`)\n } AND started_at_ms >= 0 AND started_at_ms <= 9007199254740991),\n finished_at_ms ${Dialect.integer(sql)} CHECK (finished_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`finished_at_ms`)\n } AND finished_at_ms >= 0 AND finished_at_ms <= 9007199254740991)),\n heartbeat_at_ms ${Dialect.integer(sql)} CHECK (heartbeat_at_ms IS NULL OR (${\n Dialect.isInteger(sql, sql`heartbeat_at_ms`)\n } AND heartbeat_at_ms >= 0 AND heartbeat_at_ms <= 9007199254740991)),\n checkpoint_json TEXT CHECK (checkpoint_json IS NULL OR ${Dialect.jsonValid(sql, sql`checkpoint_json`)}),\n error_json TEXT CHECK (error_json IS NULL OR ${Dialect.jsonValid(sql, sql`error_json`)}),\n outcome_json TEXT CHECK (outcome_json IS NULL OR ${Dialect.jsonValid(sql, sql`outcome_json`)}),\n meta_json TEXT NOT NULL CHECK (${Dialect.jsonValid(sql, sql`meta_json`)}),\n PRIMARY KEY (run_id, step_key_digest, attempt),\n FOREIGN KEY (run_id) REFERENCES flows_runs (run_id)\n )`\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,cAAyB;AACzB,aAAwB;AACxB,gBAA2B;AAQpB,MAAM,UAA6D,OAAO,IAAI,aAAY;AAC/F,QAAM,MAAM,OAAO,UAAU;AAE7B,SAAO;AAAA,MACH,QAAQ,MAAM,GAAG,CAAC;AAAA;AAAA;AAAA,oBAGJ,QAAQ,QAAQ,GAAG,CAAC,oBACpC,QAAQ,UAAU,KAAK,kBAAkB,CAC3C;AAAA,oBACkB,QAAQ,QAAQ,GAAG,CAAC,qCACpC,QAAQ,UAAU,KAAK,kBAAkB,CAC3C;AAAA,qBACmB,QAAQ,QAAQ,GAAG,CAAC,sCACrC,QAAQ,UAAU,KAAK,mBAAmB,CAC5C;AAAA;AAAA,gBAEc,QAAQ,QAAQ,GAAG,CAAC;AAAA;AAAA,sBAEd,QAAQ,QAAQ,GAAG,CAAC,uCACtC,QAAQ,UAAU,KAAK,oBAAoB,CAC7C;AAAA;AAAA,gBAEc,QAAQ,QAAQ,GAAG,CAAC;AAAA;AAAA,oBAEhB,QAAQ,QAAQ,GAAG,CAAC,qCACpC,QAAQ,UAAU,KAAK,kBAAkB,CAC3C;AAAA;AAAA,6BAE2B,QAAQ,QAAQ,GAAG,CAAC,8CAC7C,QAAQ,UAAU,KAAK,2BAA2B,CACpD;AAAA;AAAA,yBAEuB,QAAQ,QAAQ,GAAG,CAAC,0CACzC,QAAQ,UAAU,KAAK,uBAAuB,CAChD;AAAA;AAAA,sCAEoC,QAAQ,UAAU,KAAK,eAAe,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQnE,QAAQ,UAAU,KAAK,cAAc,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCAeb,QAAQ,UAAU,KAAK,cAAc,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUvE,SAAO;AACP,SAAO;AACP,SAAO;AAEP,SAAO;AAAA;AAAA;AAAA,cAGK,QAAQ,QAAQ,GAAG,CAAC,oBAC9B,QAAQ,UAAU,KAAK,YAAY,CACrC;AAAA;AAAA,oBAEkB,QAAQ,QAAQ,GAAG,CAAC,oBACpC,QAAQ,UAAU,KAAK,kBAAkB,CAC3C;AAAA,qBACmB,QAAQ,QAAQ,GAAG,CAAC,sCACrC,QAAQ,UAAU,KAAK,mBAAmB,CAC5C;AAAA,sBACoB,QAAQ,QAAQ,GAAG,CAAC,uCACtC,QAAQ,UAAU,KAAK,oBAAoB,CAC7C;AAAA,6DAC2D,QAAQ,UAAU,KAAK,oBAAoB,CAAC;AAAA,mDACtD,QAAQ,UAAU,KAAK,eAAe,CAAC;AAAA,uDACnC,QAAQ,UAAU,KAAK,iBAAiB,CAAC;AAAA,qCAC3D,QAAQ,UAAU,KAAK,cAAc,CAAC;AAAA;AAAA;AAAA;AAI3E,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|