@elaraai/e3-core 0.0.2-beta.3 → 0.0.2-beta.31
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 +25 -22
- package/dist/src/dataflow/api-compat.d.ts +90 -0
- package/dist/src/dataflow/api-compat.d.ts.map +1 -0
- package/dist/src/dataflow/api-compat.js +134 -0
- package/dist/src/dataflow/api-compat.js.map +1 -0
- package/dist/src/dataflow/index.d.ts +18 -0
- package/dist/src/dataflow/index.d.ts.map +1 -0
- package/dist/src/dataflow/index.js +23 -0
- package/dist/src/dataflow/index.js.map +1 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts +53 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.js +416 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.js.map +1 -0
- package/dist/src/dataflow/orchestrator/index.d.ts +12 -0
- package/dist/src/dataflow/orchestrator/index.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/index.js +12 -0
- package/dist/src/dataflow/orchestrator/index.js.map +1 -0
- package/dist/src/dataflow/orchestrator/interfaces.d.ts +157 -0
- package/dist/src/dataflow/orchestrator/interfaces.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/interfaces.js +51 -0
- package/dist/src/dataflow/orchestrator/interfaces.js.map +1 -0
- package/dist/src/dataflow/state-store/FileStateStore.d.ts +67 -0
- package/dist/src/dataflow/state-store/FileStateStore.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/FileStateStore.js +286 -0
- package/dist/src/dataflow/state-store/FileStateStore.js.map +1 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts +42 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.js +214 -0
- package/dist/src/dataflow/state-store/InMemoryStateStore.js.map +1 -0
- package/dist/src/dataflow/state-store/index.d.ts +13 -0
- package/dist/src/dataflow/state-store/index.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/index.js +13 -0
- package/dist/src/dataflow/state-store/index.js.map +1 -0
- package/dist/src/dataflow/state-store/interfaces.d.ts +159 -0
- package/dist/src/dataflow/state-store/interfaces.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/interfaces.js +6 -0
- package/dist/src/dataflow/state-store/interfaces.js.map +1 -0
- package/dist/src/dataflow/steps.d.ts +176 -0
- package/dist/src/dataflow/steps.d.ts.map +1 -0
- package/dist/src/dataflow/steps.js +528 -0
- package/dist/src/dataflow/steps.js.map +1 -0
- package/dist/src/dataflow/types.d.ts +116 -0
- package/dist/src/dataflow/types.d.ts.map +1 -0
- package/dist/src/dataflow/types.js +7 -0
- package/dist/src/dataflow/types.js.map +1 -0
- package/dist/src/dataflow.d.ts +142 -9
- package/dist/src/dataflow.d.ts.map +1 -1
- package/dist/src/dataflow.js +427 -64
- package/dist/src/dataflow.js.map +1 -1
- package/dist/src/errors.d.ts +39 -9
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +51 -8
- package/dist/src/errors.js.map +1 -1
- package/dist/src/execution/LocalTaskRunner.d.ts +73 -0
- package/dist/src/execution/LocalTaskRunner.d.ts.map +1 -0
- package/dist/src/execution/LocalTaskRunner.js +399 -0
- package/dist/src/execution/LocalTaskRunner.js.map +1 -0
- package/dist/src/execution/MockTaskRunner.d.ts +49 -0
- package/dist/src/execution/MockTaskRunner.d.ts.map +1 -0
- package/dist/src/execution/MockTaskRunner.js +55 -0
- package/dist/src/execution/MockTaskRunner.js.map +1 -0
- package/dist/src/execution/index.d.ts +16 -0
- package/dist/src/execution/index.d.ts.map +1 -0
- package/dist/src/execution/index.js +8 -0
- package/dist/src/execution/index.js.map +1 -0
- package/dist/src/execution/interfaces.d.ts +246 -0
- package/dist/src/execution/interfaces.d.ts.map +1 -0
- package/dist/src/execution/interfaces.js +6 -0
- package/dist/src/execution/interfaces.js.map +1 -0
- package/dist/src/execution/processHelpers.d.ts +20 -0
- package/dist/src/execution/processHelpers.d.ts.map +1 -0
- package/dist/src/execution/processHelpers.js +62 -0
- package/dist/src/execution/processHelpers.js.map +1 -0
- package/dist/src/executions.d.ts +71 -104
- package/dist/src/executions.d.ts.map +1 -1
- package/dist/src/executions.js +110 -476
- package/dist/src/executions.js.map +1 -1
- package/dist/src/index.d.ts +17 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +44 -18
- package/dist/src/index.js.map +1 -1
- package/dist/src/objects.d.ts +6 -53
- package/dist/src/objects.d.ts.map +1 -1
- package/dist/src/objects.js +11 -232
- package/dist/src/objects.js.map +1 -1
- package/dist/src/packages.d.ts +22 -14
- package/dist/src/packages.d.ts.map +1 -1
- package/dist/src/packages.js +116 -83
- package/dist/src/packages.js.map +1 -1
- package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts +35 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.d.ts.map +1 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.js +107 -0
- package/dist/src/storage/in-memory/InMemoryRepoStore.js.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts +114 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.js +349 -0
- package/dist/src/storage/in-memory/InMemoryStorage.js.map +1 -0
- package/dist/src/storage/in-memory/index.d.ts +12 -0
- package/dist/src/storage/in-memory/index.d.ts.map +1 -0
- package/dist/src/storage/in-memory/index.js +12 -0
- package/dist/src/storage/in-memory/index.js.map +1 -0
- package/dist/src/storage/index.d.ts +18 -0
- package/dist/src/storage/index.d.ts.map +1 -0
- package/dist/src/storage/index.js +10 -0
- package/dist/src/storage/index.js.map +1 -0
- package/dist/src/storage/interfaces.d.ts +520 -0
- package/dist/src/storage/interfaces.d.ts.map +1 -0
- package/dist/src/storage/interfaces.js +6 -0
- package/dist/src/storage/interfaces.js.map +1 -0
- package/dist/src/storage/local/LocalBackend.d.ts +54 -0
- package/dist/src/storage/local/LocalBackend.d.ts.map +1 -0
- package/dist/src/storage/local/LocalBackend.js +141 -0
- package/dist/src/storage/local/LocalBackend.js.map +1 -0
- package/dist/src/storage/local/LocalLockService.d.ts +105 -0
- package/dist/src/storage/local/LocalLockService.d.ts.map +1 -0
- package/dist/src/storage/local/LocalLockService.js +342 -0
- package/dist/src/storage/local/LocalLockService.js.map +1 -0
- package/dist/src/storage/local/LocalLogStore.d.ts +23 -0
- package/dist/src/storage/local/LocalLogStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalLogStore.js +66 -0
- package/dist/src/storage/local/LocalLogStore.js.map +1 -0
- package/dist/src/storage/local/LocalObjectStore.d.ts +52 -0
- package/dist/src/storage/local/LocalObjectStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalObjectStore.js +287 -0
- package/dist/src/storage/local/LocalObjectStore.js.map +1 -0
- package/dist/src/storage/local/LocalRefStore.d.ts +50 -0
- package/dist/src/storage/local/LocalRefStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalRefStore.js +337 -0
- package/dist/src/storage/local/LocalRefStore.js.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts +53 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.js +353 -0
- package/dist/src/storage/local/LocalRepoStore.js.map +1 -0
- package/dist/src/storage/local/gc.d.ts +92 -0
- package/dist/src/storage/local/gc.d.ts.map +1 -0
- package/dist/src/storage/local/gc.js +322 -0
- package/dist/src/storage/local/gc.js.map +1 -0
- package/dist/src/storage/local/index.d.ts +17 -0
- package/dist/src/storage/local/index.d.ts.map +1 -0
- package/dist/src/storage/local/index.js +17 -0
- package/dist/src/storage/local/index.js.map +1 -0
- package/dist/src/storage/local/localHelpers.d.ts +25 -0
- package/dist/src/storage/local/localHelpers.d.ts.map +1 -0
- package/dist/src/storage/local/localHelpers.js +69 -0
- package/dist/src/storage/local/localHelpers.js.map +1 -0
- package/dist/src/{repository.d.ts → storage/local/repository.d.ts} +8 -4
- package/dist/src/storage/local/repository.d.ts.map +1 -0
- package/dist/src/{repository.js → storage/local/repository.js} +31 -29
- package/dist/src/storage/local/repository.js.map +1 -0
- package/dist/src/tasks.d.ts +16 -10
- package/dist/src/tasks.d.ts.map +1 -1
- package/dist/src/tasks.js +35 -41
- package/dist/src/tasks.js.map +1 -1
- package/dist/src/test-helpers.d.ts +4 -4
- package/dist/src/test-helpers.d.ts.map +1 -1
- package/dist/src/test-helpers.js +7 -21
- package/dist/src/test-helpers.js.map +1 -1
- package/dist/src/trees.d.ts +89 -27
- package/dist/src/trees.d.ts.map +1 -1
- package/dist/src/trees.js +218 -100
- package/dist/src/trees.js.map +1 -1
- package/dist/src/uuid.d.ts +26 -0
- package/dist/src/uuid.d.ts.map +1 -0
- package/dist/src/uuid.js +80 -0
- package/dist/src/uuid.js.map +1 -0
- package/dist/src/workspaceStatus.d.ts +6 -4
- package/dist/src/workspaceStatus.d.ts.map +1 -1
- package/dist/src/workspaceStatus.js +43 -49
- package/dist/src/workspaceStatus.js.map +1 -1
- package/dist/src/workspaces.d.ts +35 -26
- package/dist/src/workspaces.d.ts.map +1 -1
- package/dist/src/workspaces.js +169 -118
- package/dist/src/workspaces.js.map +1 -1
- package/package.json +4 -4
- package/dist/src/gc.d.ts +0 -54
- package/dist/src/gc.d.ts.map +0 -1
- package/dist/src/gc.js +0 -233
- package/dist/src/gc.js.map +0 -1
- package/dist/src/repository.d.ts.map +0 -1
- package/dist/src/repository.js.map +0 -1
- package/dist/src/workspaceLock.d.ts +0 -67
- package/dist/src/workspaceLock.d.ts.map +0 -1
- package/dist/src/workspaceLock.js +0 -217
- package/dist/src/workspaceLock.js.map +0 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert execution state to status summary.
|
|
7
|
+
*/
|
|
8
|
+
export function stateToStatus(state) {
|
|
9
|
+
const completed = [];
|
|
10
|
+
const running = [];
|
|
11
|
+
const pending = [];
|
|
12
|
+
const failed = [];
|
|
13
|
+
const skipped = [];
|
|
14
|
+
for (const [name, taskState] of state.tasks) {
|
|
15
|
+
switch (taskState.status) {
|
|
16
|
+
case 'completed':
|
|
17
|
+
completed.push(name);
|
|
18
|
+
break;
|
|
19
|
+
case 'in_progress':
|
|
20
|
+
running.push(name);
|
|
21
|
+
break;
|
|
22
|
+
case 'pending':
|
|
23
|
+
case 'ready':
|
|
24
|
+
pending.push(name);
|
|
25
|
+
break;
|
|
26
|
+
case 'failed':
|
|
27
|
+
failed.push(name);
|
|
28
|
+
break;
|
|
29
|
+
case 'skipped':
|
|
30
|
+
skipped.push(name);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Get error value (handle Option type)
|
|
35
|
+
const errorValue = state.error.type === 'some' ? state.error.value : undefined;
|
|
36
|
+
// Get completedAt value (handle Option type)
|
|
37
|
+
const completedAtValue = state.completedAt.type === 'some' ? state.completedAt.value : undefined;
|
|
38
|
+
return {
|
|
39
|
+
id: state.id,
|
|
40
|
+
state: state.status,
|
|
41
|
+
completed,
|
|
42
|
+
running,
|
|
43
|
+
pending,
|
|
44
|
+
failed,
|
|
45
|
+
skipped,
|
|
46
|
+
error: errorValue,
|
|
47
|
+
startedAt: state.startedAt,
|
|
48
|
+
completedAt: completedAtValue,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=interfaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../../src/dataflow/orchestrator/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsKH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAA6B;IACzD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC5C,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC;YACzB,KAAK,WAAW;gBACd,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,MAAM;YACR,KAAK,aAAa;gBAChB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,MAAM;YACR,KAAK,SAAS,CAAC;YACf,KAAK,OAAO;gBACV,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,MAAM;YACR,KAAK,SAAS;gBACZ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,MAAM;QACV,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAE/E,6CAA6C;IAC7C,MAAM,gBAAgB,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjG,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,MAA0D;QACvE,SAAS;QACT,OAAO;QACP,OAAO;QACP,MAAM;QACN,OAAO;QACP,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,gBAAgB;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { ExecutionStateStore, TaskStatusDetails, ExecutionStatusDetails } from './interfaces.js';
|
|
6
|
+
import { type DataflowExecutionState, type ExecutionEvent, type TaskStatus } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* File-based state store for local filesystem persistence.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* - Uses atomic writes (write to temp, then rename) for durability
|
|
12
|
+
* - State is stored in beast2 binary format for type safety
|
|
13
|
+
* - Events are stored inline in the execution state
|
|
14
|
+
* - Thread-safe for concurrent access within a single process (via file locking)
|
|
15
|
+
* - Suitable for local CLI and API server usage
|
|
16
|
+
*/
|
|
17
|
+
export declare class FileStateStore implements ExecutionStateStore {
|
|
18
|
+
private readonly workspacesDir;
|
|
19
|
+
/**
|
|
20
|
+
* Create a new FileStateStore.
|
|
21
|
+
*
|
|
22
|
+
* @param workspacesDir - Path to the workspaces directory (e.g., repo/workspaces)
|
|
23
|
+
*/
|
|
24
|
+
constructor(workspacesDir: string);
|
|
25
|
+
/**
|
|
26
|
+
* Get the path to a workspace's directory.
|
|
27
|
+
*/
|
|
28
|
+
private workspacePath;
|
|
29
|
+
/**
|
|
30
|
+
* Get the path to a workspace's execution state file.
|
|
31
|
+
*/
|
|
32
|
+
private statePath;
|
|
33
|
+
/**
|
|
34
|
+
* Get the path to a workspace's execution counter file.
|
|
35
|
+
*/
|
|
36
|
+
private counterPath;
|
|
37
|
+
create(state: DataflowExecutionState): Promise<void>;
|
|
38
|
+
read(repo: string, workspace: string, id: string): Promise<DataflowExecutionState | null>;
|
|
39
|
+
readLatest(_repo: string, workspace: string): Promise<DataflowExecutionState | null>;
|
|
40
|
+
update(state: DataflowExecutionState): Promise<void>;
|
|
41
|
+
updateTaskStatus(repo: string, workspace: string, executionId: string, task: string, status: TaskStatus, details?: TaskStatusDetails): Promise<void>;
|
|
42
|
+
updateStatus(repo: string, workspace: string, executionId: string, status: 'running' | 'completed' | 'failed' | 'cancelled', details?: ExecutionStatusDetails): Promise<void>;
|
|
43
|
+
recordEvent(repo: string, workspace: string, executionId: string, event: ExecutionEvent): Promise<void>;
|
|
44
|
+
getEventsSince(repo: string, workspace: string, executionId: string, sinceSeq: number): Promise<ExecutionEvent[]>;
|
|
45
|
+
nextExecutionId(_repo: string, workspace: string): Promise<string>;
|
|
46
|
+
delete(_repo: string, workspace: string, executionId: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Check if an incomplete execution exists for a workspace.
|
|
49
|
+
*
|
|
50
|
+
* An execution is incomplete if its status is 'running'.
|
|
51
|
+
* This is used to detect crash recovery scenarios.
|
|
52
|
+
*
|
|
53
|
+
* @param repo - Repository identifier
|
|
54
|
+
* @param workspace - Workspace name
|
|
55
|
+
* @returns The incomplete execution if one exists, null otherwise
|
|
56
|
+
*/
|
|
57
|
+
getIncompleteExecution(repo: string, workspace: string): Promise<DataflowExecutionState | null>;
|
|
58
|
+
/**
|
|
59
|
+
* Write a binary file atomically using temp file + rename.
|
|
60
|
+
*/
|
|
61
|
+
private atomicWrite;
|
|
62
|
+
/**
|
|
63
|
+
* Write a text file atomically using temp file + rename.
|
|
64
|
+
*/
|
|
65
|
+
private atomicWriteText;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=FileStateStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileStateStore.d.ts","sourceRoot":"","sources":["../../../../src/dataflow/state-store/FileStateStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EAEnB,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AASrB;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,mBAAmB;IAM5C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAL1C;;;;OAIG;gBAC0B,aAAa,EAAE,MAAM;IAElD;;OAEG;IACH,OAAO,CAAC,aAAa;IAIrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,WAAW;IAIb,MAAM,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAcpD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IA0BzF,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAcpF,MAAM,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD,gBAAgB,CACpB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAqCV,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,EACxD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAyBV,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC;IAYV,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,EAAE,CAAC;IAetB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBlE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBlF;;;;;;;;;OASG;IACG,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAQrG;;OAEG;YACW,WAAW;IAmBzB;;OAEG;YACW,eAAe;CAkB9B"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* File-based implementation of ExecutionStateStore.
|
|
7
|
+
*
|
|
8
|
+
* Persists execution state to the workspace directory structure:
|
|
9
|
+
* - workspaces/{ws}/execution.beast2 - Current/last execution state (binary format)
|
|
10
|
+
* - workspaces/{ws}/execution-counter - Auto-increment counter
|
|
11
|
+
*
|
|
12
|
+
* Events are stored inline in the execution state (not as a separate file).
|
|
13
|
+
* This enables crash recovery and external monitoring of execution progress.
|
|
14
|
+
*/
|
|
15
|
+
import { promises as fs } from 'node:fs';
|
|
16
|
+
import { join, dirname } from 'node:path';
|
|
17
|
+
import { encodeBeast2For, decodeBeast2For, some } from '@elaraai/east';
|
|
18
|
+
import { DataflowExecutionStateType, } from '../types.js';
|
|
19
|
+
// Create encoder/decoder for beast2 serialization
|
|
20
|
+
const encode = encodeBeast2For(DataflowExecutionStateType);
|
|
21
|
+
const decode = decodeBeast2For(DataflowExecutionStateType);
|
|
22
|
+
/**
|
|
23
|
+
* File-based state store for local filesystem persistence.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* - Uses atomic writes (write to temp, then rename) for durability
|
|
27
|
+
* - State is stored in beast2 binary format for type safety
|
|
28
|
+
* - Events are stored inline in the execution state
|
|
29
|
+
* - Thread-safe for concurrent access within a single process (via file locking)
|
|
30
|
+
* - Suitable for local CLI and API server usage
|
|
31
|
+
*/
|
|
32
|
+
export class FileStateStore {
|
|
33
|
+
workspacesDir;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new FileStateStore.
|
|
36
|
+
*
|
|
37
|
+
* @param workspacesDir - Path to the workspaces directory (e.g., repo/workspaces)
|
|
38
|
+
*/
|
|
39
|
+
constructor(workspacesDir) {
|
|
40
|
+
this.workspacesDir = workspacesDir;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get the path to a workspace's directory.
|
|
44
|
+
*/
|
|
45
|
+
workspacePath(workspace) {
|
|
46
|
+
return join(this.workspacesDir, workspace);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the path to a workspace's execution state file.
|
|
50
|
+
*/
|
|
51
|
+
statePath(workspace) {
|
|
52
|
+
return join(this.workspacePath(workspace), 'execution.beast2');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the path to a workspace's execution counter file.
|
|
56
|
+
*/
|
|
57
|
+
counterPath(workspace) {
|
|
58
|
+
return join(this.workspacePath(workspace), 'execution-counter');
|
|
59
|
+
}
|
|
60
|
+
async create(state) {
|
|
61
|
+
const path = this.statePath(state.workspace);
|
|
62
|
+
// Check if execution already exists
|
|
63
|
+
const existing = await this.read(state.repo, state.workspace, state.id);
|
|
64
|
+
if (existing) {
|
|
65
|
+
throw new Error(`Execution ${state.id} already exists in workspace '${state.workspace}'`);
|
|
66
|
+
}
|
|
67
|
+
// Write state atomically using beast2 encoding
|
|
68
|
+
const data = encode(state);
|
|
69
|
+
await this.atomicWrite(path, data);
|
|
70
|
+
}
|
|
71
|
+
async read(repo, workspace, id) {
|
|
72
|
+
const path = this.statePath(workspace);
|
|
73
|
+
try {
|
|
74
|
+
const data = await fs.readFile(path);
|
|
75
|
+
const state = decode(data);
|
|
76
|
+
// Check if this is the requested execution
|
|
77
|
+
if (state.id !== id) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
// Verify repo matches (if stored)
|
|
81
|
+
if (state.repo && state.repo !== repo) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return state;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
if (err.code === 'ENOENT') {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async readLatest(_repo, workspace) {
|
|
94
|
+
const path = this.statePath(workspace);
|
|
95
|
+
try {
|
|
96
|
+
const data = await fs.readFile(path);
|
|
97
|
+
return decode(data);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
if (err.code === 'ENOENT') {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async update(state) {
|
|
107
|
+
const path = this.statePath(state.workspace);
|
|
108
|
+
const data = encode(state);
|
|
109
|
+
await this.atomicWrite(path, data);
|
|
110
|
+
}
|
|
111
|
+
async updateTaskStatus(repo, workspace, executionId, task, status, details) {
|
|
112
|
+
const state = await this.read(repo, workspace, executionId);
|
|
113
|
+
if (!state) {
|
|
114
|
+
throw new Error(`Execution ${executionId} not found in workspace '${workspace}'`);
|
|
115
|
+
}
|
|
116
|
+
const taskState = state.tasks.get(task);
|
|
117
|
+
if (!taskState) {
|
|
118
|
+
throw new Error(`Task '${task}' not found in execution ${executionId}`);
|
|
119
|
+
}
|
|
120
|
+
const mutableState = state;
|
|
121
|
+
taskState.status = status;
|
|
122
|
+
if (details) {
|
|
123
|
+
if (details.cached !== undefined)
|
|
124
|
+
taskState.cached = some(details.cached);
|
|
125
|
+
if (details.outputHash !== undefined)
|
|
126
|
+
taskState.outputHash = some(details.outputHash);
|
|
127
|
+
if (details.error !== undefined)
|
|
128
|
+
taskState.error = some(details.error);
|
|
129
|
+
if (details.exitCode !== undefined)
|
|
130
|
+
taskState.exitCode = some(BigInt(details.exitCode));
|
|
131
|
+
if (details.duration !== undefined)
|
|
132
|
+
taskState.duration = some(BigInt(details.duration));
|
|
133
|
+
}
|
|
134
|
+
taskState.completedAt = some(new Date());
|
|
135
|
+
// Update counters based on status
|
|
136
|
+
if (status === 'completed' && details?.cached) {
|
|
137
|
+
mutableState.cached = state.cached + 1n;
|
|
138
|
+
}
|
|
139
|
+
else if (status === 'completed') {
|
|
140
|
+
mutableState.executed = state.executed + 1n;
|
|
141
|
+
}
|
|
142
|
+
else if (status === 'failed') {
|
|
143
|
+
mutableState.failed = state.failed + 1n;
|
|
144
|
+
}
|
|
145
|
+
else if (status === 'skipped') {
|
|
146
|
+
mutableState.skipped = state.skipped + 1n;
|
|
147
|
+
}
|
|
148
|
+
await this.update(state);
|
|
149
|
+
}
|
|
150
|
+
async updateStatus(repo, workspace, executionId, status, details) {
|
|
151
|
+
const state = await this.read(repo, workspace, executionId);
|
|
152
|
+
if (!state) {
|
|
153
|
+
throw new Error(`Execution ${executionId} not found in workspace '${workspace}'`);
|
|
154
|
+
}
|
|
155
|
+
const mutableState = state;
|
|
156
|
+
mutableState.status = status;
|
|
157
|
+
if (status !== 'running') {
|
|
158
|
+
mutableState.completedAt = some(new Date());
|
|
159
|
+
}
|
|
160
|
+
if (details?.error) {
|
|
161
|
+
mutableState.error = some(details.error);
|
|
162
|
+
}
|
|
163
|
+
if (details?.summary) {
|
|
164
|
+
mutableState.executed = BigInt(details.summary.executed);
|
|
165
|
+
mutableState.cached = BigInt(details.summary.cached);
|
|
166
|
+
mutableState.failed = BigInt(details.summary.failed);
|
|
167
|
+
mutableState.skipped = BigInt(details.summary.skipped);
|
|
168
|
+
}
|
|
169
|
+
await this.update(state);
|
|
170
|
+
}
|
|
171
|
+
async recordEvent(repo, workspace, executionId, event) {
|
|
172
|
+
const state = await this.read(repo, workspace, executionId);
|
|
173
|
+
if (!state) {
|
|
174
|
+
throw new Error(`Execution ${executionId} not found in workspace '${workspace}'`);
|
|
175
|
+
}
|
|
176
|
+
// Append event to inline events array (cast to mutable array)
|
|
177
|
+
state.events.push(event);
|
|
178
|
+
await this.update(state);
|
|
179
|
+
}
|
|
180
|
+
async getEventsSince(repo, workspace, executionId, sinceSeq) {
|
|
181
|
+
const state = await this.read(repo, workspace, executionId);
|
|
182
|
+
if (!state) {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
// Filter events from inline array
|
|
186
|
+
const sinceSeqBigInt = BigInt(sinceSeq);
|
|
187
|
+
return state.events.filter(e => {
|
|
188
|
+
// Events are variants, so we access seq via e.value.seq
|
|
189
|
+
const seq = e.value.seq;
|
|
190
|
+
return seq > sinceSeqBigInt;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
async nextExecutionId(_repo, workspace) {
|
|
194
|
+
const path = this.counterPath(workspace);
|
|
195
|
+
let current = 0;
|
|
196
|
+
try {
|
|
197
|
+
const data = await fs.readFile(path, 'utf-8');
|
|
198
|
+
current = parseInt(data.trim(), 10) || 0;
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
if (err.code !== 'ENOENT') {
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const next = current + 1;
|
|
206
|
+
await this.atomicWriteText(path, String(next));
|
|
207
|
+
return String(next);
|
|
208
|
+
}
|
|
209
|
+
async delete(_repo, workspace, executionId) {
|
|
210
|
+
// Only delete if the stored execution matches the requested ID
|
|
211
|
+
const state = await this.readLatest(_repo, workspace);
|
|
212
|
+
if (state && state.id === executionId) {
|
|
213
|
+
const statePath = this.statePath(workspace);
|
|
214
|
+
try {
|
|
215
|
+
await fs.unlink(statePath);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
if (err.code !== 'ENOENT') {
|
|
219
|
+
throw err;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check if an incomplete execution exists for a workspace.
|
|
226
|
+
*
|
|
227
|
+
* An execution is incomplete if its status is 'running'.
|
|
228
|
+
* This is used to detect crash recovery scenarios.
|
|
229
|
+
*
|
|
230
|
+
* @param repo - Repository identifier
|
|
231
|
+
* @param workspace - Workspace name
|
|
232
|
+
* @returns The incomplete execution if one exists, null otherwise
|
|
233
|
+
*/
|
|
234
|
+
async getIncompleteExecution(repo, workspace) {
|
|
235
|
+
const state = await this.readLatest(repo, workspace);
|
|
236
|
+
if (state && state.status === 'running') {
|
|
237
|
+
return state;
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Write a binary file atomically using temp file + rename.
|
|
243
|
+
*/
|
|
244
|
+
async atomicWrite(path, content) {
|
|
245
|
+
const dir = dirname(path);
|
|
246
|
+
const tmpPath = join(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
247
|
+
try {
|
|
248
|
+
await fs.mkdir(dir, { recursive: true });
|
|
249
|
+
await fs.writeFile(tmpPath, content);
|
|
250
|
+
await fs.rename(tmpPath, path);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
// Clean up temp file on failure
|
|
254
|
+
try {
|
|
255
|
+
await fs.unlink(tmpPath);
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// Ignore cleanup errors
|
|
259
|
+
}
|
|
260
|
+
throw err;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Write a text file atomically using temp file + rename.
|
|
265
|
+
*/
|
|
266
|
+
async atomicWriteText(path, content) {
|
|
267
|
+
const dir = dirname(path);
|
|
268
|
+
const tmpPath = join(dir, `.tmp-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
269
|
+
try {
|
|
270
|
+
await fs.mkdir(dir, { recursive: true });
|
|
271
|
+
await fs.writeFile(tmpPath, content, 'utf-8');
|
|
272
|
+
await fs.rename(tmpPath, path);
|
|
273
|
+
}
|
|
274
|
+
catch (err) {
|
|
275
|
+
// Clean up temp file on failure
|
|
276
|
+
try {
|
|
277
|
+
await fs.unlink(tmpPath);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Ignore cleanup errors
|
|
281
|
+
}
|
|
282
|
+
throw err;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=FileStateStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileStateStore.js","sourceRoot":"","sources":["../../../../src/dataflow/state-store/FileStateStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { ExecutionStateStore, TaskStatusDetails, ExecutionStatusDetails } from './interfaces.js';
|
|
6
|
+
import type { DataflowExecutionState, ExecutionEvent, TaskStatus } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* In-memory state store for testing and simple use cases.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* - Thread-safe for concurrent access within a single process
|
|
12
|
+
* - State is lost on process exit
|
|
13
|
+
* - No durability guarantees
|
|
14
|
+
*/
|
|
15
|
+
export declare class InMemoryStateStore implements ExecutionStateStore {
|
|
16
|
+
/** Map of "repo::workspace" -> execution ID -> state */
|
|
17
|
+
private states;
|
|
18
|
+
/** Map of "repo::workspace" -> next execution ID counter */
|
|
19
|
+
private counters;
|
|
20
|
+
private makeKey;
|
|
21
|
+
create(state: DataflowExecutionState): Promise<void>;
|
|
22
|
+
read(repo: string, workspace: string, id: string): Promise<DataflowExecutionState | null>;
|
|
23
|
+
readLatest(repo: string, workspace: string): Promise<DataflowExecutionState | null>;
|
|
24
|
+
update(state: DataflowExecutionState): Promise<void>;
|
|
25
|
+
updateTaskStatus(repo: string, workspace: string, executionId: string, task: string, status: TaskStatus, details?: TaskStatusDetails): Promise<void>;
|
|
26
|
+
updateStatus(repo: string, workspace: string, executionId: string, status: 'running' | 'completed' | 'failed' | 'cancelled', details?: ExecutionStatusDetails): Promise<void>;
|
|
27
|
+
recordEvent(repo: string, workspace: string, executionId: string, event: ExecutionEvent): Promise<void>;
|
|
28
|
+
getEventsSince(repo: string, workspace: string, executionId: string, sinceSeq: number): Promise<ExecutionEvent[]>;
|
|
29
|
+
nextExecutionId(repo: string, workspace: string): Promise<string>;
|
|
30
|
+
delete(repo: string, workspace: string, executionId: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all state (for testing).
|
|
33
|
+
*/
|
|
34
|
+
clear(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Deep clone execution state to prevent external mutation.
|
|
37
|
+
*
|
|
38
|
+
* Note: We use spread and some() to properly clone the branded option types.
|
|
39
|
+
*/
|
|
40
|
+
private cloneState;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=InMemoryStateStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InMemoryStateStore.d.ts","sourceRoot":"","sources":["../../../../src/dataflow/state-store/InMemoryStateStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EACV,sBAAsB,EAEtB,cAAc,EACd,UAAU,EAEX,MAAM,aAAa,CAAC;AAKrB;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,wDAAwD;IACxD,OAAO,CAAC,MAAM,CAA0D;IAExE,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAA6B;IAE7C,OAAO,CAAC,OAAO;IAKT,MAAM,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAYzF,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAwBnF,MAAM,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUpD,gBAAgB,CACpB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAwBV,YAAY,CAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,EACxD,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAyBV,WAAW,CACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC;IAaV,cAAc,CAClB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,EAAE,CAAC;IActB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASjE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjF;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAmCnB"}
|