taskflow-core 0.2.0 → 0.2.1
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 +247 -862
- package/dist/agents.d.ts +12 -0
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +29 -1
- package/dist/agents.js.map +1 -1
- package/dist/cwd-bridge.d.ts +61 -0
- package/dist/cwd-bridge.d.ts.map +1 -0
- package/dist/cwd-bridge.js +136 -0
- package/dist/cwd-bridge.js.map +1 -0
- package/dist/detached-runner.js +31 -5
- package/dist/detached-runner.js.map +1 -1
- package/dist/exec/driver.d.ts +1 -0
- package/dist/exec/driver.d.ts.map +1 -1
- package/dist/exec/driver.js +15 -2
- package/dist/exec/driver.js.map +1 -1
- package/dist/exec/step-kinds.d.ts.map +1 -1
- package/dist/exec/step-kinds.js +28 -3
- package/dist/exec/step-kinds.js.map +1 -1
- package/dist/exec/step.d.ts +1 -0
- package/dist/exec/step.d.ts.map +1 -1
- package/dist/exec/step.js +18 -0
- package/dist/exec/step.js.map +1 -1
- package/dist/flowir/compile.d.ts.map +1 -1
- package/dist/flowir/compile.js +13 -0
- package/dist/flowir/compile.js.map +1 -1
- package/dist/host/runner-types.d.ts +16 -0
- package/dist/host/runner-types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/interpolate.d.ts +4 -0
- package/dist/interpolate.d.ts.map +1 -1
- package/dist/interpolate.js +14 -0
- package/dist/interpolate.js.map +1 -1
- package/dist/resources/authority.d.ts +35 -0
- package/dist/resources/authority.d.ts.map +1 -0
- package/dist/resources/authority.js +67 -0
- package/dist/resources/authority.js.map +1 -0
- package/dist/resources/backend.d.ts +302 -0
- package/dist/resources/backend.d.ts.map +1 -0
- package/dist/resources/backend.js +16 -0
- package/dist/resources/backend.js.map +1 -0
- package/dist/resources/baseline.d.ts +116 -0
- package/dist/resources/baseline.d.ts.map +1 -0
- package/dist/resources/baseline.js +447 -0
- package/dist/resources/baseline.js.map +1 -0
- package/dist/resources/canonical-json.d.ts +7 -0
- package/dist/resources/canonical-json.d.ts.map +1 -0
- package/dist/resources/canonical-json.js +75 -0
- package/dist/resources/canonical-json.js.map +1 -0
- package/dist/resources/errors.d.ts +23 -0
- package/dist/resources/errors.d.ts.map +1 -0
- package/dist/resources/errors.js +89 -0
- package/dist/resources/errors.js.map +1 -0
- package/dist/resources/execution.d.ts +90 -0
- package/dist/resources/execution.d.ts.map +1 -0
- package/dist/resources/execution.js +581 -0
- package/dist/resources/execution.js.map +1 -0
- package/dist/resources/index.d.ts +15 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +15 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/journal.d.ts +138 -0
- package/dist/resources/journal.d.ts.map +1 -0
- package/dist/resources/journal.js +438 -0
- package/dist/resources/journal.js.map +1 -0
- package/dist/resources/leases.d.ts +51 -0
- package/dist/resources/leases.d.ts.map +1 -0
- package/dist/resources/leases.js +354 -0
- package/dist/resources/leases.js.map +1 -0
- package/dist/resources/permits.d.ts +52 -0
- package/dist/resources/permits.d.ts.map +1 -0
- package/dist/resources/permits.js +240 -0
- package/dist/resources/permits.js.map +1 -0
- package/dist/resources/persistence.d.ts +63 -0
- package/dist/resources/persistence.d.ts.map +1 -0
- package/dist/resources/persistence.js +522 -0
- package/dist/resources/persistence.js.map +1 -0
- package/dist/resources/registry.d.ts +56 -0
- package/dist/resources/registry.d.ts.map +1 -0
- package/dist/resources/registry.js +139 -0
- package/dist/resources/registry.js.map +1 -0
- package/dist/resources/resolve.d.ts +49 -0
- package/dist/resources/resolve.d.ts.map +1 -0
- package/dist/resources/resolve.js +309 -0
- package/dist/resources/resolve.js.map +1 -0
- package/dist/resources/sandbox.d.ts +72 -0
- package/dist/resources/sandbox.d.ts.map +1 -0
- package/dist/resources/sandbox.js +952 -0
- package/dist/resources/sandbox.js.map +1 -0
- package/dist/resources/schema.d.ts +195 -0
- package/dist/resources/schema.d.ts.map +1 -0
- package/dist/resources/schema.js +231 -0
- package/dist/resources/schema.js.map +1 -0
- package/dist/resources/types.d.ts +36 -0
- package/dist/resources/types.d.ts.map +1 -0
- package/dist/resources/types.js +75 -0
- package/dist/resources/types.js.map +1 -0
- package/dist/runner-core.d.ts +29 -0
- package/dist/runner-core.d.ts.map +1 -1
- package/dist/runner-core.js +311 -36
- package/dist/runner-core.js.map +1 -1
- package/dist/runtime/phases/script.d.ts.map +1 -1
- package/dist/runtime/phases/script.js +47 -9
- package/dist/runtime/phases/script.js.map +1 -1
- package/dist/runtime.d.ts +39 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +542 -50
- package/dist/runtime.js.map +1 -1
- package/dist/schema.d.ts +68 -5
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +163 -22
- package/dist/schema.js.map +1 -1
- package/dist/store.d.ts +7 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js.map +1 -1
- package/dist/trace.d.ts +3 -0
- package/dist/trace.d.ts.map +1 -1
- package/dist/trace.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { type PersistentCoordinatorOptions } from "./persistence.ts";
|
|
2
|
+
import { MutationPermitRegistry, type MutationPermit } from "./permits.ts";
|
|
3
|
+
import { type ExecutionOwner, type ExternalMutationModel, type ScopedContentEvidence, type VersionCommitMode } from "./types.ts";
|
|
4
|
+
export type { ExternalMutationModel, ScopedContentEvidence, VersionCommitMode } from "./types.ts";
|
|
5
|
+
export type { MutationPermit } from "./permits.ts";
|
|
6
|
+
export type WriteIntentStatus = "pending" | "committed-content" | "committed-generation" | "dirty-unknown" | "reconciled";
|
|
7
|
+
export interface WriteIntentRecord {
|
|
8
|
+
journalVersion: 1;
|
|
9
|
+
intentId: string;
|
|
10
|
+
resourceDomainId: string;
|
|
11
|
+
providerInstanceId?: string;
|
|
12
|
+
scopes: ScopedContentEvidence[];
|
|
13
|
+
owner: ExecutionOwner;
|
|
14
|
+
beforeGeneration: number;
|
|
15
|
+
intentSequence: number;
|
|
16
|
+
commitGeneration?: number;
|
|
17
|
+
journalEpoch: number;
|
|
18
|
+
commitMode: VersionCommitMode;
|
|
19
|
+
externalMutation: ExternalMutationModel;
|
|
20
|
+
status: WriteIntentStatus;
|
|
21
|
+
restorableSnapshotArtifactIds?: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface RecoverPendingOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Return true only when the exact execution owner still holds a live
|
|
26
|
+
* mutation lease. The callback runs while the journal mutex is held so a
|
|
27
|
+
* writer cannot create a new intent between the liveness check and the WAL
|
|
28
|
+
* recovery append.
|
|
29
|
+
*/
|
|
30
|
+
isOwnerActive?: (owner: ExecutionOwner) => boolean | Promise<boolean>;
|
|
31
|
+
}
|
|
32
|
+
export interface PrepareWriteIntent {
|
|
33
|
+
resourceDomainId: string;
|
|
34
|
+
providerInstanceId?: string;
|
|
35
|
+
scopes: ScopedContentEvidence[];
|
|
36
|
+
owner: ExecutionOwner;
|
|
37
|
+
/** Optional external CAS assertion. Omit for ordinary writers so generation
|
|
38
|
+
* sampling and intent creation occur under one journal mutex. */
|
|
39
|
+
beforeGeneration?: number;
|
|
40
|
+
commitMode: VersionCommitMode;
|
|
41
|
+
externalMutation: ExternalMutationModel;
|
|
42
|
+
permitTtlMs?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface CommitWriteIntentOptions {
|
|
45
|
+
/** Last-moment synchronous validation after permit checks and before WAL. */
|
|
46
|
+
preCommitGuard?: () => void;
|
|
47
|
+
}
|
|
48
|
+
interface IntentWalRecord {
|
|
49
|
+
journalVersion: 1;
|
|
50
|
+
type: "write-intent";
|
|
51
|
+
ts: string;
|
|
52
|
+
intent: WriteIntentRecord;
|
|
53
|
+
}
|
|
54
|
+
interface CommitContentWalRecord {
|
|
55
|
+
journalVersion: 1;
|
|
56
|
+
type: "write-commit-content";
|
|
57
|
+
ts: string;
|
|
58
|
+
intentId: string;
|
|
59
|
+
resourceDomainId: string;
|
|
60
|
+
commitGeneration: number;
|
|
61
|
+
scopes: ScopedContentEvidence[];
|
|
62
|
+
restorableSnapshotArtifactIds?: string[];
|
|
63
|
+
}
|
|
64
|
+
interface CommitGenerationWalRecord {
|
|
65
|
+
journalVersion: 1;
|
|
66
|
+
type: "write-commit-generation";
|
|
67
|
+
ts: string;
|
|
68
|
+
intentId: string;
|
|
69
|
+
resourceDomainId: string;
|
|
70
|
+
commitGeneration: number;
|
|
71
|
+
}
|
|
72
|
+
interface UnknownWalRecord {
|
|
73
|
+
journalVersion: 1;
|
|
74
|
+
type: "write-unknown";
|
|
75
|
+
ts: string;
|
|
76
|
+
intentId: string;
|
|
77
|
+
resourceDomainId: string;
|
|
78
|
+
reason: string;
|
|
79
|
+
}
|
|
80
|
+
interface ReconcileWalRecord {
|
|
81
|
+
journalVersion: 1;
|
|
82
|
+
type: "write-reconcile";
|
|
83
|
+
ts: string;
|
|
84
|
+
resourceDomainId: string;
|
|
85
|
+
reconcileGeneration: number;
|
|
86
|
+
intentIds: string[];
|
|
87
|
+
reason: string;
|
|
88
|
+
}
|
|
89
|
+
export type JournalWalRecord = IntentWalRecord | CommitContentWalRecord | CommitGenerationWalRecord | UnknownWalRecord | ReconcileWalRecord;
|
|
90
|
+
export interface JournalManagerOptions extends PersistentCoordinatorOptions {
|
|
91
|
+
journalEpoch: number;
|
|
92
|
+
permitRegistry?: MutationPermitRegistry;
|
|
93
|
+
}
|
|
94
|
+
export interface PreparedMutation {
|
|
95
|
+
intent: WriteIntentRecord;
|
|
96
|
+
permit: MutationPermit;
|
|
97
|
+
}
|
|
98
|
+
export interface RecoveryResult {
|
|
99
|
+
recoveredIntentIds: string[];
|
|
100
|
+
dirtyDomains: string[];
|
|
101
|
+
}
|
|
102
|
+
export interface ReconciliationResult {
|
|
103
|
+
resourceDomainId: string;
|
|
104
|
+
previousGeneration: number;
|
|
105
|
+
generation: number;
|
|
106
|
+
reconciledIntentIds: string[];
|
|
107
|
+
}
|
|
108
|
+
export declare class JournalStateError extends Error {
|
|
109
|
+
readonly code = "TFWS_JOURNAL_STATE";
|
|
110
|
+
constructor(message: string);
|
|
111
|
+
}
|
|
112
|
+
export declare class WriteIntentJournal {
|
|
113
|
+
#private;
|
|
114
|
+
readonly walPath: string;
|
|
115
|
+
readonly journalEpoch: number;
|
|
116
|
+
readonly permits: MutationPermitRegistry;
|
|
117
|
+
readonly now: () => number;
|
|
118
|
+
constructor(options: JournalManagerOptions);
|
|
119
|
+
prepare(input: PrepareWriteIntent): Promise<PreparedMutation>;
|
|
120
|
+
/** Verify durable pending intents and atomically CAS all permits to active. */
|
|
121
|
+
activate(permits: readonly MutationPermit[], owner: ExecutionOwner): Promise<void>;
|
|
122
|
+
assertActive(permit: MutationPermit, owner: ExecutionOwner): Promise<void>;
|
|
123
|
+
commitGeneration(intentId: string, options?: CommitWriteIntentOptions): Promise<WriteIntentRecord>;
|
|
124
|
+
commitContent(intentId: string, scopes: readonly ScopedContentEvidence[], restorableSnapshotArtifactIds?: readonly string[], options?: CommitWriteIntentOptions): Promise<WriteIntentRecord>;
|
|
125
|
+
markUnknown(intentId: string, reason: string): Promise<WriteIntentRecord>;
|
|
126
|
+
/** Explicitly acknowledge the current external filesystem state for one
|
|
127
|
+
* resource domain. Callers must hold an exclusive whole-domain lease; this
|
|
128
|
+
* method serializes the durable decision and advances the generation so no
|
|
129
|
+
* earlier observation can be reused as the reconciled state. */
|
|
130
|
+
reconcileDomain(resourceDomainId: string, reason: string): Promise<ReconciliationResult>;
|
|
131
|
+
/** Startup recovery: any fsynced intent without a terminal WAL record and
|
|
132
|
+
* without a live mutation owner becomes dirty-unknown before reuse. */
|
|
133
|
+
recoverPending(reason?: string, options?: RecoverPendingOptions): Promise<RecoveryResult>;
|
|
134
|
+
getIntent(intentId: string): Promise<WriteIntentRecord | undefined>;
|
|
135
|
+
getDomainGeneration(resourceDomainId: string): Promise<number>;
|
|
136
|
+
listIntents(): Promise<WriteIntentRecord[]>;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.d.ts","sourceRoot":"","sources":["../../src/resources/journal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { PersistentFileMutex, appendJsonLinesDurable, readJsonLines, } from "./persistence.js";
|
|
4
|
+
import { MutationPermitRegistry, } from "./permits.js";
|
|
5
|
+
import { canonicalLeaseKeysOverlap, canonicalPrefixContains, cloneExecutionOwner, minimalCanonicalScopeCover, normalizeCanonicalPrefix, sameCanonicalScopes, sameExecutionOwner, } from "./types.js";
|
|
6
|
+
export class JournalStateError extends Error {
|
|
7
|
+
code = "TFWS_JOURNAL_STATE";
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "JournalStateError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function cloneEvidence(scope) {
|
|
14
|
+
if (typeof scope.scopeDigest !== "string" || scope.scopeDigest.length === 0)
|
|
15
|
+
throw new Error("scopeDigest must be non-empty");
|
|
16
|
+
return {
|
|
17
|
+
canonicalPrefix: normalizeCanonicalPrefix(scope.canonicalPrefix),
|
|
18
|
+
scopeDigest: scope.scopeDigest,
|
|
19
|
+
...(scope.beforeContentId === undefined ? {} : { beforeContentId: scope.beforeContentId }),
|
|
20
|
+
...(scope.afterContentId === undefined ? {} : { afterContentId: scope.afterContentId }),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function normalizeEvidence(scopes) {
|
|
24
|
+
if (scopes.length === 0)
|
|
25
|
+
throw new Error("A write intent requires at least one scope");
|
|
26
|
+
const byPrefix = new Map();
|
|
27
|
+
for (const scope of scopes.map(cloneEvidence)) {
|
|
28
|
+
if (byPrefix.has(scope.canonicalPrefix))
|
|
29
|
+
throw new Error(`Duplicate write scope ${scope.canonicalPrefix}`);
|
|
30
|
+
byPrefix.set(scope.canonicalPrefix, scope);
|
|
31
|
+
}
|
|
32
|
+
const sorted = [...byPrefix.values()].sort((a, b) => a.canonicalPrefix.localeCompare(b.canonicalPrefix));
|
|
33
|
+
return sorted.filter((scope, index) => !sorted.some((parent, parentIndex) => parentIndex !== index && canonicalPrefixContains(parent.canonicalPrefix, scope.canonicalPrefix)));
|
|
34
|
+
}
|
|
35
|
+
function intentScopeKeys(intent) {
|
|
36
|
+
return minimalCanonicalScopeCover(intent.scopes.map((scope) => ({
|
|
37
|
+
resourceDomainId: intent.resourceDomainId,
|
|
38
|
+
canonicalPrefix: scope.canonicalPrefix,
|
|
39
|
+
})));
|
|
40
|
+
}
|
|
41
|
+
function scopesOverlap(a, b) {
|
|
42
|
+
return intentScopeKeys(a).some((left) => intentScopeKeys(b).some((right) => canonicalLeaseKeysOverlap(left, right)));
|
|
43
|
+
}
|
|
44
|
+
function cloneIntent(intent) {
|
|
45
|
+
return structuredClone(intent);
|
|
46
|
+
}
|
|
47
|
+
function fold(records) {
|
|
48
|
+
const intents = new Map();
|
|
49
|
+
const domainGenerations = new Map();
|
|
50
|
+
let maxIntentSequence = 0;
|
|
51
|
+
for (const record of records) {
|
|
52
|
+
if (record.journalVersion !== 1)
|
|
53
|
+
throw new JournalStateError(`Unsupported journal record version: ${String(record.journalVersion)}`);
|
|
54
|
+
if (record.type === "write-intent") {
|
|
55
|
+
if (intents.has(record.intent.intentId))
|
|
56
|
+
throw new JournalStateError(`Duplicate intent ${record.intent.intentId}`);
|
|
57
|
+
intents.set(record.intent.intentId, cloneIntent(record.intent));
|
|
58
|
+
maxIntentSequence = Math.max(maxIntentSequence, record.intent.intentSequence);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (record.type === "write-reconcile") {
|
|
62
|
+
const intentIds = [...new Set(record.intentIds)];
|
|
63
|
+
if (intentIds.length === 0 || intentIds.length !== record.intentIds.length) {
|
|
64
|
+
throw new JournalStateError("Reconcile record must reference a non-empty unique intent set");
|
|
65
|
+
}
|
|
66
|
+
const previousGeneration = domainGenerations.get(record.resourceDomainId) ?? 0;
|
|
67
|
+
if (record.reconcileGeneration !== previousGeneration + 1) {
|
|
68
|
+
throw new JournalStateError(`Non-monotonic reconcile generation ${record.reconcileGeneration} for ${record.resourceDomainId}; expected ${previousGeneration + 1}`);
|
|
69
|
+
}
|
|
70
|
+
for (const intentId of intentIds) {
|
|
71
|
+
const intent = intents.get(intentId);
|
|
72
|
+
if (!intent)
|
|
73
|
+
throw new JournalStateError(`Reconcile record references unknown intent ${intentId}`);
|
|
74
|
+
if (intent.resourceDomainId !== record.resourceDomainId) {
|
|
75
|
+
throw new JournalStateError(`Reconcile intent ${intentId} domain mismatch`);
|
|
76
|
+
}
|
|
77
|
+
if (intent.status !== "dirty-unknown") {
|
|
78
|
+
throw new JournalStateError(`Reconcile intent ${intentId} is ${intent.status}, not dirty-unknown`);
|
|
79
|
+
}
|
|
80
|
+
intent.status = "reconciled";
|
|
81
|
+
intent.commitGeneration = record.reconcileGeneration;
|
|
82
|
+
}
|
|
83
|
+
domainGenerations.set(record.resourceDomainId, record.reconcileGeneration);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const intent = intents.get(record.intentId);
|
|
87
|
+
if (!intent)
|
|
88
|
+
throw new JournalStateError(`Terminal record references unknown intent ${record.intentId}`);
|
|
89
|
+
if (intent.status !== "pending")
|
|
90
|
+
throw new JournalStateError(`Intent ${record.intentId} has multiple terminal WAL records`);
|
|
91
|
+
if (record.resourceDomainId !== intent.resourceDomainId)
|
|
92
|
+
throw new JournalStateError(`Intent ${record.intentId} domain mismatch`);
|
|
93
|
+
if (record.type === "write-unknown") {
|
|
94
|
+
intent.status = "dirty-unknown";
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const previousGeneration = domainGenerations.get(record.resourceDomainId) ?? 0;
|
|
98
|
+
if (record.commitGeneration !== previousGeneration + 1) {
|
|
99
|
+
throw new JournalStateError(`Non-monotonic commit generation ${record.commitGeneration} for ${record.resourceDomainId}; expected ${previousGeneration + 1}`);
|
|
100
|
+
}
|
|
101
|
+
domainGenerations.set(record.resourceDomainId, record.commitGeneration);
|
|
102
|
+
intent.commitGeneration = record.commitGeneration;
|
|
103
|
+
if (record.type === "write-commit-content") {
|
|
104
|
+
intent.status = "committed-content";
|
|
105
|
+
intent.scopes = structuredClone(record.scopes);
|
|
106
|
+
intent.restorableSnapshotArtifactIds = record.restorableSnapshotArtifactIds ? [...record.restorableSnapshotArtifactIds] : undefined;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
intent.status = "committed-generation";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { intents, domainGenerations, maxIntentSequence };
|
|
113
|
+
}
|
|
114
|
+
function pendingDescriptor(intent) {
|
|
115
|
+
return {
|
|
116
|
+
intentId: intent.intentId,
|
|
117
|
+
intentSequence: intent.intentSequence,
|
|
118
|
+
journalEpoch: intent.journalEpoch,
|
|
119
|
+
owner: cloneExecutionOwner(intent.owner),
|
|
120
|
+
scopes: intentScopeKeys(intent),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export class WriteIntentJournal {
|
|
124
|
+
walPath;
|
|
125
|
+
journalEpoch;
|
|
126
|
+
permits;
|
|
127
|
+
now;
|
|
128
|
+
#mutex;
|
|
129
|
+
constructor(options) {
|
|
130
|
+
if (!Number.isSafeInteger(options.journalEpoch) || options.journalEpoch < 1)
|
|
131
|
+
throw new Error("journalEpoch must be a positive safe integer");
|
|
132
|
+
this.journalEpoch = options.journalEpoch;
|
|
133
|
+
this.walPath = path.join(options.directory, "resource-journal.wal.jsonl");
|
|
134
|
+
this.now = options.now ?? Date.now;
|
|
135
|
+
this.#mutex = new PersistentFileMutex(path.join(options.directory, "resource-journal.lock"), options);
|
|
136
|
+
this.permits = options.permitRegistry ?? new MutationPermitRegistry(options);
|
|
137
|
+
if (this.permits.journalEpoch !== this.journalEpoch)
|
|
138
|
+
throw new Error("Journal and permit registry epochs must match");
|
|
139
|
+
}
|
|
140
|
+
#records() {
|
|
141
|
+
return readJsonLines(this.walPath);
|
|
142
|
+
}
|
|
143
|
+
#projection() {
|
|
144
|
+
return fold(this.#records());
|
|
145
|
+
}
|
|
146
|
+
#append(records) {
|
|
147
|
+
appendJsonLinesDurable(this.walPath, records);
|
|
148
|
+
}
|
|
149
|
+
async prepare(input) {
|
|
150
|
+
if (input.beforeGeneration !== undefined && (!Number.isSafeInteger(input.beforeGeneration) || input.beforeGeneration < 0)) {
|
|
151
|
+
throw new Error("beforeGeneration must be a non-negative safe integer");
|
|
152
|
+
}
|
|
153
|
+
if (!input.resourceDomainId)
|
|
154
|
+
throw new Error("resourceDomainId must be non-empty");
|
|
155
|
+
if (!["content-snapshot", "generation-only", "unavailable"].includes(input.commitMode))
|
|
156
|
+
throw new Error(`Unsupported commitMode ${String(input.commitMode)}`);
|
|
157
|
+
if (!["taskflow-managed", "externally-mutable"].includes(input.externalMutation))
|
|
158
|
+
throw new Error(`Unsupported externalMutation ${String(input.externalMutation)}`);
|
|
159
|
+
const scopes = normalizeEvidence(input.scopes);
|
|
160
|
+
const ttlMs = input.permitTtlMs ?? 60_000;
|
|
161
|
+
return this.#mutex.runExclusive(async () => {
|
|
162
|
+
const projection = this.#projection();
|
|
163
|
+
const currentGeneration = projection.domainGenerations.get(input.resourceDomainId) ?? 0;
|
|
164
|
+
if (input.beforeGeneration !== undefined && input.beforeGeneration !== currentGeneration) {
|
|
165
|
+
throw new JournalStateError(`beforeGeneration ${input.beforeGeneration} does not match durable generation ${currentGeneration} for ${input.resourceDomainId}`);
|
|
166
|
+
}
|
|
167
|
+
const candidate = {
|
|
168
|
+
resourceDomainId: input.resourceDomainId,
|
|
169
|
+
scopes,
|
|
170
|
+
};
|
|
171
|
+
for (const existing of projection.intents.values()) {
|
|
172
|
+
if ((existing.status === "pending" || existing.status === "dirty-unknown") && scopesOverlap(existing, candidate)) {
|
|
173
|
+
throw new JournalStateError(`Scope overlaps ${existing.status} intent ${existing.intentId}; reconcile before writing`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const nowIso = new Date(this.now()).toISOString();
|
|
177
|
+
const intent = {
|
|
178
|
+
journalVersion: 1,
|
|
179
|
+
intentId: crypto.randomUUID(),
|
|
180
|
+
resourceDomainId: input.resourceDomainId,
|
|
181
|
+
...(input.providerInstanceId === undefined ? {} : { providerInstanceId: input.providerInstanceId }),
|
|
182
|
+
scopes,
|
|
183
|
+
owner: cloneExecutionOwner(input.owner),
|
|
184
|
+
beforeGeneration: currentGeneration,
|
|
185
|
+
intentSequence: projection.maxIntentSequence + 1,
|
|
186
|
+
journalEpoch: this.journalEpoch,
|
|
187
|
+
commitMode: input.commitMode,
|
|
188
|
+
externalMutation: input.externalMutation,
|
|
189
|
+
status: "pending",
|
|
190
|
+
};
|
|
191
|
+
this.#append([{ journalVersion: 1, type: "write-intent", ts: nowIso, intent }]);
|
|
192
|
+
try {
|
|
193
|
+
const permit = await this.permits.issueForDurableIntent(pendingDescriptor(intent), ttlMs);
|
|
194
|
+
return { intent: cloneIntent(intent), permit };
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
this.#append([{
|
|
198
|
+
journalVersion: 1,
|
|
199
|
+
type: "write-unknown",
|
|
200
|
+
ts: new Date(this.now()).toISOString(),
|
|
201
|
+
intentId: intent.intentId,
|
|
202
|
+
resourceDomainId: intent.resourceDomainId,
|
|
203
|
+
reason: `permit issuance failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
204
|
+
}]);
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/** Verify durable pending intents and atomically CAS all permits to active. */
|
|
210
|
+
async activate(permits, owner) {
|
|
211
|
+
await this.#mutex.runExclusive(async () => {
|
|
212
|
+
const projection = this.#projection();
|
|
213
|
+
const pending = [];
|
|
214
|
+
for (const permit of permits) {
|
|
215
|
+
const intent = projection.intents.get(permit.intentId);
|
|
216
|
+
if (!intent || intent.status !== "pending")
|
|
217
|
+
throw new JournalStateError(`Permit intent ${permit.intentId} is not pending`);
|
|
218
|
+
if (!sameExecutionOwner(intent.owner, owner))
|
|
219
|
+
throw new JournalStateError(`Intent ${intent.intentId} owner mismatch`);
|
|
220
|
+
pending.push(pendingDescriptor(intent));
|
|
221
|
+
}
|
|
222
|
+
await this.permits.activateMany(permits, { owner, pendingIntents: pending });
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
async assertActive(permit, owner) {
|
|
226
|
+
await this.#mutex.runExclusive(async () => {
|
|
227
|
+
const intent = this.#projection().intents.get(permit.intentId);
|
|
228
|
+
if (!intent || intent.status !== "pending")
|
|
229
|
+
throw new JournalStateError(`Permit intent ${permit.intentId} is not pending`);
|
|
230
|
+
await this.permits.assertActive(permit, owner);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
async commitGeneration(intentId, options = {}) {
|
|
234
|
+
return this.#commit(intentId, "generation-only", undefined, undefined, options);
|
|
235
|
+
}
|
|
236
|
+
async commitContent(intentId, scopes, restorableSnapshotArtifactIds, options = {}) {
|
|
237
|
+
const normalized = normalizeEvidence(scopes);
|
|
238
|
+
if (normalized.some((scope) => typeof scope.afterContentId !== "string" || scope.afterContentId.length === 0)) {
|
|
239
|
+
throw new JournalStateError("content-snapshot commit requires afterContentId for every scope");
|
|
240
|
+
}
|
|
241
|
+
return this.#commit(intentId, "content-snapshot", normalized, restorableSnapshotArtifactIds, options);
|
|
242
|
+
}
|
|
243
|
+
async #commit(intentId, mode, scopes, restorableSnapshotArtifactIds, options = {}) {
|
|
244
|
+
return this.#mutex.runExclusive(async () => {
|
|
245
|
+
const projection = this.#projection();
|
|
246
|
+
const intent = projection.intents.get(intentId);
|
|
247
|
+
if (!intent || intent.status !== "pending")
|
|
248
|
+
throw new JournalStateError(`Intent ${intentId} is not pending`);
|
|
249
|
+
if (intent.commitMode !== mode)
|
|
250
|
+
throw new JournalStateError(`Intent ${intentId} commit mode is ${intent.commitMode}, not ${mode}`);
|
|
251
|
+
await this.permits.assertIntentActive(intentId, intent.owner);
|
|
252
|
+
// Permit validation may wait on another cross-process mutex. Revalidate
|
|
253
|
+
// cancellation/path invariants after every awaited lock and immediately
|
|
254
|
+
// before the synchronous terminal WAL append.
|
|
255
|
+
options.preCommitGuard?.();
|
|
256
|
+
const generation = (projection.domainGenerations.get(intent.resourceDomainId) ?? 0) + 1;
|
|
257
|
+
const ts = new Date(this.now()).toISOString();
|
|
258
|
+
let record;
|
|
259
|
+
if (mode === "content-snapshot") {
|
|
260
|
+
if (!scopes || !sameCanonicalScopes(intentScopeKeys(intent), scopes.map((scope) => ({ resourceDomainId: intent.resourceDomainId, canonicalPrefix: scope.canonicalPrefix })))) {
|
|
261
|
+
throw new JournalStateError(`Committed content scopes do not match intent ${intentId}`);
|
|
262
|
+
}
|
|
263
|
+
record = {
|
|
264
|
+
journalVersion: 1,
|
|
265
|
+
type: "write-commit-content",
|
|
266
|
+
ts,
|
|
267
|
+
intentId,
|
|
268
|
+
resourceDomainId: intent.resourceDomainId,
|
|
269
|
+
commitGeneration: generation,
|
|
270
|
+
scopes,
|
|
271
|
+
...(restorableSnapshotArtifactIds === undefined ? {} : { restorableSnapshotArtifactIds: [...restorableSnapshotArtifactIds] }),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
record = {
|
|
276
|
+
journalVersion: 1,
|
|
277
|
+
type: "write-commit-generation",
|
|
278
|
+
ts,
|
|
279
|
+
intentId,
|
|
280
|
+
resourceDomainId: intent.resourceDomainId,
|
|
281
|
+
commitGeneration: generation,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
this.#append([record]);
|
|
285
|
+
await this.#settleTerminalPermit(intentId);
|
|
286
|
+
// The terminal WAL append is the durability point. Do not perform a new
|
|
287
|
+
// fallible WAL read after it or turn a committed mutation into a retryable
|
|
288
|
+
// caller failure.
|
|
289
|
+
const committed = cloneIntent(intent);
|
|
290
|
+
committed.commitGeneration = generation;
|
|
291
|
+
if (record.type === "write-commit-content") {
|
|
292
|
+
committed.status = "committed-content";
|
|
293
|
+
committed.scopes = structuredClone(record.scopes);
|
|
294
|
+
committed.restorableSnapshotArtifactIds = record.restorableSnapshotArtifactIds
|
|
295
|
+
? [...record.restorableSnapshotArtifactIds]
|
|
296
|
+
: undefined;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
committed.status = "committed-generation";
|
|
300
|
+
}
|
|
301
|
+
return cloneIntent(committed);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
async markUnknown(intentId, reason) {
|
|
305
|
+
return this.#mutex.runExclusive(async () => {
|
|
306
|
+
const projection = this.#projection();
|
|
307
|
+
const intent = projection.intents.get(intentId);
|
|
308
|
+
if (!intent || intent.status !== "pending")
|
|
309
|
+
throw new JournalStateError(`Intent ${intentId} is not pending`);
|
|
310
|
+
this.#append([{
|
|
311
|
+
journalVersion: 1,
|
|
312
|
+
type: "write-unknown",
|
|
313
|
+
ts: new Date(this.now()).toISOString(),
|
|
314
|
+
intentId,
|
|
315
|
+
resourceDomainId: intent.resourceDomainId,
|
|
316
|
+
reason: reason || "mutation outcome unknown",
|
|
317
|
+
}]);
|
|
318
|
+
await this.#settleTerminalPermit(intentId);
|
|
319
|
+
const dirty = cloneIntent(intent);
|
|
320
|
+
dirty.status = "dirty-unknown";
|
|
321
|
+
return cloneIntent(dirty);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/** Explicitly acknowledge the current external filesystem state for one
|
|
325
|
+
* resource domain. Callers must hold an exclusive whole-domain lease; this
|
|
326
|
+
* method serializes the durable decision and advances the generation so no
|
|
327
|
+
* earlier observation can be reused as the reconciled state. */
|
|
328
|
+
async reconcileDomain(resourceDomainId, reason) {
|
|
329
|
+
if (!resourceDomainId)
|
|
330
|
+
throw new Error("resourceDomainId must be non-empty");
|
|
331
|
+
const normalizedReason = reason.trim();
|
|
332
|
+
if (!normalizedReason || normalizedReason.length > 512) {
|
|
333
|
+
throw new Error("reconcile reason must contain 1-512 characters");
|
|
334
|
+
}
|
|
335
|
+
return this.#mutex.runExclusive(async () => {
|
|
336
|
+
const projection = this.#projection();
|
|
337
|
+
const inDomain = [...projection.intents.values()]
|
|
338
|
+
.filter((intent) => intent.resourceDomainId === resourceDomainId);
|
|
339
|
+
const pending = inDomain.filter((intent) => intent.status === "pending");
|
|
340
|
+
if (pending.length > 0) {
|
|
341
|
+
throw new JournalStateError("Cannot reconcile while a write intent is still pending");
|
|
342
|
+
}
|
|
343
|
+
const dirty = inDomain
|
|
344
|
+
.filter((intent) => intent.status === "dirty-unknown")
|
|
345
|
+
.sort((left, right) => left.intentSequence - right.intentSequence);
|
|
346
|
+
const previousGeneration = projection.domainGenerations.get(resourceDomainId) ?? 0;
|
|
347
|
+
if (dirty.length === 0) {
|
|
348
|
+
return {
|
|
349
|
+
resourceDomainId,
|
|
350
|
+
previousGeneration,
|
|
351
|
+
generation: previousGeneration,
|
|
352
|
+
reconciledIntentIds: [],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const generation = previousGeneration + 1;
|
|
356
|
+
this.#append([{
|
|
357
|
+
journalVersion: 1,
|
|
358
|
+
type: "write-reconcile",
|
|
359
|
+
ts: new Date(this.now()).toISOString(),
|
|
360
|
+
resourceDomainId,
|
|
361
|
+
reconcileGeneration: generation,
|
|
362
|
+
intentIds: dirty.map((intent) => intent.intentId),
|
|
363
|
+
reason: normalizedReason,
|
|
364
|
+
}]);
|
|
365
|
+
for (const intent of dirty)
|
|
366
|
+
await this.#settleTerminalPermit(intent.intentId);
|
|
367
|
+
return {
|
|
368
|
+
resourceDomainId,
|
|
369
|
+
previousGeneration,
|
|
370
|
+
generation,
|
|
371
|
+
reconciledIntentIds: dirty.map((intent) => intent.intentId),
|
|
372
|
+
};
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
async #settleTerminalPermit(intentId) {
|
|
376
|
+
try {
|
|
377
|
+
await this.permits.settleIntent(intentId);
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
// The WAL terminal record is the commit/dirty decision point. Permit
|
|
381
|
+
// cleanup may be retried during recovery, but must never turn an already
|
|
382
|
+
// committed filesystem mutation into a retryable execution failure.
|
|
383
|
+
console.warn(`[taskflow] workspace permit cleanup deferred for intent ${intentId}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/** Startup recovery: any fsynced intent without a terminal WAL record and
|
|
387
|
+
* without a live mutation owner becomes dirty-unknown before reuse. */
|
|
388
|
+
async recoverPending(reason = "startup recovery found an uncommitted write intent", options = {}) {
|
|
389
|
+
return this.#mutex.runExclusive(async () => {
|
|
390
|
+
const projection = this.#projection();
|
|
391
|
+
const pending = [];
|
|
392
|
+
for (const intent of projection.intents.values()) {
|
|
393
|
+
if (intent.status !== "pending")
|
|
394
|
+
continue;
|
|
395
|
+
if (options.isOwnerActive && await options.isOwnerActive(cloneExecutionOwner(intent.owner)))
|
|
396
|
+
continue;
|
|
397
|
+
pending.push(intent);
|
|
398
|
+
}
|
|
399
|
+
if (pending.length > 0) {
|
|
400
|
+
const ts = new Date(this.now()).toISOString();
|
|
401
|
+
this.#append(pending.map((intent) => ({
|
|
402
|
+
journalVersion: 1,
|
|
403
|
+
type: "write-unknown",
|
|
404
|
+
ts,
|
|
405
|
+
intentId: intent.intentId,
|
|
406
|
+
resourceDomainId: intent.resourceDomainId,
|
|
407
|
+
reason,
|
|
408
|
+
})));
|
|
409
|
+
}
|
|
410
|
+
// Also closes the crash window after a durable commit/unknown append but
|
|
411
|
+
// before the permit registry transition was persisted. Retained pending
|
|
412
|
+
// intents with a live owner are deliberately excluded.
|
|
413
|
+
const settle = [
|
|
414
|
+
...pending,
|
|
415
|
+
...[...projection.intents.values()].filter((intent) => intent.status !== "pending"),
|
|
416
|
+
];
|
|
417
|
+
for (const intent of settle)
|
|
418
|
+
await this.#settleTerminalPermit(intent.intentId);
|
|
419
|
+
return {
|
|
420
|
+
recoveredIntentIds: pending.map((intent) => intent.intentId),
|
|
421
|
+
dirtyDomains: [...new Set(pending.map((intent) => intent.resourceDomainId))].sort(),
|
|
422
|
+
};
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
async getIntent(intentId) {
|
|
426
|
+
return this.#mutex.runExclusive(() => {
|
|
427
|
+
const intent = this.#projection().intents.get(intentId);
|
|
428
|
+
return intent ? cloneIntent(intent) : undefined;
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
async getDomainGeneration(resourceDomainId) {
|
|
432
|
+
return this.#mutex.runExclusive(() => this.#projection().domainGenerations.get(resourceDomainId) ?? 0);
|
|
433
|
+
}
|
|
434
|
+
async listIntents() {
|
|
435
|
+
return this.#mutex.runExclusive(() => [...this.#projection().intents.values()].map(cloneIntent));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal.js","sourceRoot":"","sources":["../../src/resources/journal.ts"],"names":[],"mappings":"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"}
|