@elaraai/e3-core 0.0.1-beta.0 → 0.0.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -7
- package/dist/src/dataflow.d.ts +41 -1
- package/dist/src/dataflow.d.ts.map +1 -1
- package/dist/src/dataflow.js +165 -36
- package/dist/src/dataflow.js.map +1 -1
- package/dist/src/errors.d.ts +39 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +34 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/executions.d.ts +14 -1
- package/dist/src/executions.d.ts.map +1 -1
- package/dist/src/executions.js +60 -10
- package/dist/src/executions.js.map +1 -1
- package/dist/src/formats.d.ts +1 -1
- package/dist/src/formats.js +1 -1
- package/dist/src/gc.d.ts +1 -1
- package/dist/src/gc.js +3 -2
- package/dist/src/gc.js.map +1 -1
- package/dist/src/index.d.ts +9 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +10 -6
- package/dist/src/index.js.map +1 -1
- package/dist/src/objects.d.ts +1 -1
- package/dist/src/objects.js +1 -1
- package/dist/src/packages.d.ts +9 -1
- package/dist/src/packages.d.ts.map +1 -1
- package/dist/src/packages.js +16 -1
- package/dist/src/packages.js.map +1 -1
- package/dist/src/repository.d.ts +1 -1
- package/dist/src/repository.js +1 -1
- package/dist/src/tasks.d.ts +1 -1
- package/dist/src/tasks.js +1 -1
- package/dist/src/test-helpers.d.ts +1 -1
- package/dist/src/test-helpers.js +1 -1
- package/dist/src/trees.d.ts +24 -2
- package/dist/src/trees.d.ts.map +1 -1
- package/dist/src/trees.js +31 -2
- package/dist/src/trees.js.map +1 -1
- package/dist/src/workspaceLock.d.ts +67 -0
- package/dist/src/workspaceLock.d.ts.map +1 -0
- package/dist/src/workspaceLock.js +217 -0
- package/dist/src/workspaceLock.js.map +1 -0
- package/dist/src/workspaceStatus.d.ts +126 -0
- package/dist/src/workspaceStatus.d.ts.map +1 -0
- package/dist/src/workspaceStatus.js +352 -0
- package/dist/src/workspaceStatus.js.map +1 -0
- package/dist/src/workspaces.d.ts +37 -3
- package/dist/src/workspaces.d.ts.map +1 -1
- package/dist/src/workspaces.js +56 -22
- package/dist/src/workspaces.js.map +1 -1
- package/package.json +11 -2
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type LockHolder } from './errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Status of a dataset in the workspace.
|
|
8
|
+
*/
|
|
9
|
+
export type DatasetStatus = {
|
|
10
|
+
type: 'unset';
|
|
11
|
+
} | {
|
|
12
|
+
type: 'stale';
|
|
13
|
+
} | {
|
|
14
|
+
type: 'up-to-date';
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Status of a task in the workspace.
|
|
18
|
+
*/
|
|
19
|
+
export type TaskStatus = {
|
|
20
|
+
type: 'up-to-date';
|
|
21
|
+
cached: boolean;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'ready';
|
|
24
|
+
} | {
|
|
25
|
+
type: 'waiting';
|
|
26
|
+
reason: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'in-progress';
|
|
29
|
+
pid?: number;
|
|
30
|
+
startedAt?: string;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'failed';
|
|
33
|
+
exitCode: number;
|
|
34
|
+
completedAt?: string;
|
|
35
|
+
} | {
|
|
36
|
+
type: 'error';
|
|
37
|
+
message: string;
|
|
38
|
+
completedAt?: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: 'stale-running';
|
|
41
|
+
pid?: number;
|
|
42
|
+
startedAt?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Information about a dataset in the status report.
|
|
46
|
+
*/
|
|
47
|
+
export interface DatasetStatusInfo {
|
|
48
|
+
/** Dataset path (e.g., "inputs.sales_data") */
|
|
49
|
+
path: string;
|
|
50
|
+
/** Current status */
|
|
51
|
+
status: DatasetStatus;
|
|
52
|
+
/** Hash of current value (if set) */
|
|
53
|
+
hash: string | null;
|
|
54
|
+
/** True if this is a task output */
|
|
55
|
+
isTaskOutput: boolean;
|
|
56
|
+
/** Name of task that produces this (if any) */
|
|
57
|
+
producedBy: string | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Information about a task in the status report.
|
|
61
|
+
*/
|
|
62
|
+
export interface TaskStatusInfo {
|
|
63
|
+
/** Task name */
|
|
64
|
+
name: string;
|
|
65
|
+
/** Task hash */
|
|
66
|
+
hash: string;
|
|
67
|
+
/** Current status */
|
|
68
|
+
status: TaskStatus;
|
|
69
|
+
/** Input dataset paths */
|
|
70
|
+
inputs: string[];
|
|
71
|
+
/** Output dataset path */
|
|
72
|
+
output: string;
|
|
73
|
+
/** Tasks this one depends on */
|
|
74
|
+
dependsOn: string[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Complete workspace status report.
|
|
78
|
+
*/
|
|
79
|
+
export interface WorkspaceStatusResult {
|
|
80
|
+
/** Workspace name */
|
|
81
|
+
workspace: string;
|
|
82
|
+
/** Lock status - null if not locked */
|
|
83
|
+
lock: LockHolder | null;
|
|
84
|
+
/** Status of all datasets */
|
|
85
|
+
datasets: DatasetStatusInfo[];
|
|
86
|
+
/** Status of all tasks */
|
|
87
|
+
tasks: TaskStatusInfo[];
|
|
88
|
+
/** Summary counts */
|
|
89
|
+
summary: {
|
|
90
|
+
datasets: {
|
|
91
|
+
total: number;
|
|
92
|
+
unset: number;
|
|
93
|
+
stale: number;
|
|
94
|
+
upToDate: number;
|
|
95
|
+
};
|
|
96
|
+
tasks: {
|
|
97
|
+
total: number;
|
|
98
|
+
upToDate: number;
|
|
99
|
+
ready: number;
|
|
100
|
+
waiting: number;
|
|
101
|
+
inProgress: number;
|
|
102
|
+
failed: number;
|
|
103
|
+
error: number;
|
|
104
|
+
staleRunning: number;
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get comprehensive status of a workspace.
|
|
110
|
+
*
|
|
111
|
+
* Performs a dry-run analysis of the workspace to determine:
|
|
112
|
+
* - Whether the workspace is locked (and by whom)
|
|
113
|
+
* - Status of each dataset (unset, stale, up-to-date)
|
|
114
|
+
* - Status of each task (up-to-date, ready, waiting, in-progress)
|
|
115
|
+
*
|
|
116
|
+
* This is a read-only operation that does not modify workspace state
|
|
117
|
+
* and does not require acquiring a lock.
|
|
118
|
+
*
|
|
119
|
+
* @param repoPath - Path to .e3 repository
|
|
120
|
+
* @param ws - Workspace name
|
|
121
|
+
* @returns Complete status report
|
|
122
|
+
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
123
|
+
* @throws {WorkspaceNotDeployedError} If workspace has no package deployed
|
|
124
|
+
*/
|
|
125
|
+
export declare function workspaceStatus(repoPath: string, ws: string): Promise<WorkspaceStatusResult>;
|
|
126
|
+
//# sourceMappingURL=workspaceStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceStatus.d.ts","sourceRoot":"","sources":["../../src/workspaceStatus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Workspace status - dry-run analysis of dataflow execution state.
|
|
7
|
+
*
|
|
8
|
+
* Provides a complete view of workspace state including:
|
|
9
|
+
* - Lock status (who holds it, since when)
|
|
10
|
+
* - Dataset status (unset, stale, up-to-date)
|
|
11
|
+
* - Task status (up-to-date, ready, waiting, in-progress)
|
|
12
|
+
*
|
|
13
|
+
* This is read-only and does not require a lock.
|
|
14
|
+
*/
|
|
15
|
+
import { decodeBeast2For, variant } from '@elaraai/east';
|
|
16
|
+
import { PackageObjectType, TaskObjectType, WorkspaceStateType, pathToString, } from '@elaraai/e3-types';
|
|
17
|
+
import { objectRead } from './objects.js';
|
|
18
|
+
import { executionGet, inputsHash, } from './executions.js';
|
|
19
|
+
import { workspaceGetDatasetHash } from './trees.js';
|
|
20
|
+
import { WorkspaceNotFoundError, WorkspaceNotDeployedError, isNotFoundError, } from './errors.js';
|
|
21
|
+
import { getWorkspaceLockHolder } from './workspaceLock.js';
|
|
22
|
+
import * as fs from 'fs/promises';
|
|
23
|
+
import * as path from 'path';
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Workspace State Reader (duplicated to avoid circular deps)
|
|
26
|
+
// =============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Read workspace state from file.
|
|
29
|
+
*/
|
|
30
|
+
async function readWorkspaceState(repoPath, ws) {
|
|
31
|
+
const stateFile = path.join(repoPath, 'workspaces', `${ws}.beast2`);
|
|
32
|
+
let data;
|
|
33
|
+
try {
|
|
34
|
+
data = await fs.readFile(stateFile);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (isNotFoundError(err)) {
|
|
38
|
+
throw new WorkspaceNotFoundError(ws);
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
if (data.length === 0) {
|
|
43
|
+
throw new WorkspaceNotDeployedError(ws);
|
|
44
|
+
}
|
|
45
|
+
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
46
|
+
return decoder(data);
|
|
47
|
+
}
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// Main Function
|
|
50
|
+
// =============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* Get comprehensive status of a workspace.
|
|
53
|
+
*
|
|
54
|
+
* Performs a dry-run analysis of the workspace to determine:
|
|
55
|
+
* - Whether the workspace is locked (and by whom)
|
|
56
|
+
* - Status of each dataset (unset, stale, up-to-date)
|
|
57
|
+
* - Status of each task (up-to-date, ready, waiting, in-progress)
|
|
58
|
+
*
|
|
59
|
+
* This is a read-only operation that does not modify workspace state
|
|
60
|
+
* and does not require acquiring a lock.
|
|
61
|
+
*
|
|
62
|
+
* @param repoPath - Path to .e3 repository
|
|
63
|
+
* @param ws - Workspace name
|
|
64
|
+
* @returns Complete status report
|
|
65
|
+
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
66
|
+
* @throws {WorkspaceNotDeployedError} If workspace has no package deployed
|
|
67
|
+
*/
|
|
68
|
+
export async function workspaceStatus(repoPath, ws) {
|
|
69
|
+
// Check lock status first
|
|
70
|
+
const lock = await getWorkspaceLockHolder(repoPath, ws);
|
|
71
|
+
// Read workspace state
|
|
72
|
+
const state = await readWorkspaceState(repoPath, ws);
|
|
73
|
+
// Read package object to get tasks and structure
|
|
74
|
+
const pkgData = await objectRead(repoPath, state.packageHash);
|
|
75
|
+
const pkgDecoder = decodeBeast2For(PackageObjectType);
|
|
76
|
+
const pkgObject = pkgDecoder(Buffer.from(pkgData));
|
|
77
|
+
// Build task nodes
|
|
78
|
+
const taskNodes = new Map();
|
|
79
|
+
const outputToTask = new Map(); // output path -> task name
|
|
80
|
+
const taskDecoder = decodeBeast2For(TaskObjectType);
|
|
81
|
+
for (const [taskName, taskHash] of pkgObject.tasks) {
|
|
82
|
+
const taskData = await objectRead(repoPath, taskHash);
|
|
83
|
+
const task = taskDecoder(Buffer.from(taskData));
|
|
84
|
+
const outputPathStr = pathToString(task.output);
|
|
85
|
+
outputToTask.set(outputPathStr, taskName);
|
|
86
|
+
taskNodes.set(taskName, {
|
|
87
|
+
name: taskName,
|
|
88
|
+
hash: taskHash,
|
|
89
|
+
task,
|
|
90
|
+
inputPaths: task.inputs,
|
|
91
|
+
outputPath: task.output,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// Collect all dataset paths from structure
|
|
95
|
+
const datasetPaths = [];
|
|
96
|
+
collectDatasetPaths(pkgObject.data.structure, [], datasetPaths);
|
|
97
|
+
// Determine task dependencies
|
|
98
|
+
const taskDependsOn = new Map();
|
|
99
|
+
for (const [taskName, node] of taskNodes) {
|
|
100
|
+
const deps = [];
|
|
101
|
+
for (const inputPath of node.inputPaths) {
|
|
102
|
+
const inputPathStr = pathToString(inputPath);
|
|
103
|
+
const producerTask = outputToTask.get(inputPathStr);
|
|
104
|
+
if (producerTask) {
|
|
105
|
+
deps.push(producerTask);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
taskDependsOn.set(taskName, deps);
|
|
109
|
+
}
|
|
110
|
+
// Determine which tasks are stale (need to rerun)
|
|
111
|
+
// A task is stale if:
|
|
112
|
+
// 1. No cached execution for current inputs, OR
|
|
113
|
+
// 2. Cached output doesn't match current workspace output, OR
|
|
114
|
+
// 3. Any upstream task is stale
|
|
115
|
+
const taskIsStale = new Map();
|
|
116
|
+
const taskStatus = new Map();
|
|
117
|
+
// First pass: determine which tasks have valid cached executions
|
|
118
|
+
for (const [taskName, node] of taskNodes) {
|
|
119
|
+
const status = await computeTaskStatus(repoPath, ws, node, outputToTask, taskNodes, taskIsStale);
|
|
120
|
+
taskStatus.set(taskName, status);
|
|
121
|
+
taskIsStale.set(taskName, status.type !== 'up-to-date');
|
|
122
|
+
}
|
|
123
|
+
// Second pass: mark tasks as waiting if their upstream is stale
|
|
124
|
+
for (const [taskName] of taskNodes) {
|
|
125
|
+
const currentStatus = taskStatus.get(taskName);
|
|
126
|
+
if (currentStatus.type === 'ready') {
|
|
127
|
+
// Check if any upstream task is stale
|
|
128
|
+
const deps = taskDependsOn.get(taskName) ?? [];
|
|
129
|
+
for (const depName of deps) {
|
|
130
|
+
if (taskIsStale.get(depName)) {
|
|
131
|
+
taskStatus.set(taskName, {
|
|
132
|
+
type: 'waiting',
|
|
133
|
+
reason: `Waiting for task '${depName}'`,
|
|
134
|
+
});
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Build dataset status
|
|
141
|
+
const datasetStatusInfos = [];
|
|
142
|
+
for (const datasetPath of datasetPaths) {
|
|
143
|
+
const pathStr = pathToString(datasetPath);
|
|
144
|
+
const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, datasetPath);
|
|
145
|
+
const producerTask = outputToTask.get(pathStr) ?? null;
|
|
146
|
+
const isTaskOutput = producerTask !== null;
|
|
147
|
+
let status;
|
|
148
|
+
if (refType === 'unassigned') {
|
|
149
|
+
status = { type: 'unset' };
|
|
150
|
+
}
|
|
151
|
+
else if (isTaskOutput && producerTask && taskIsStale.get(producerTask)) {
|
|
152
|
+
status = { type: 'stale' };
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
status = { type: 'up-to-date' };
|
|
156
|
+
}
|
|
157
|
+
datasetStatusInfos.push({
|
|
158
|
+
path: pathStr,
|
|
159
|
+
status,
|
|
160
|
+
hash,
|
|
161
|
+
isTaskOutput,
|
|
162
|
+
producedBy: producerTask,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Build task status info
|
|
166
|
+
const taskStatusInfos = [];
|
|
167
|
+
for (const [taskName, node] of taskNodes) {
|
|
168
|
+
taskStatusInfos.push({
|
|
169
|
+
name: taskName,
|
|
170
|
+
hash: node.hash,
|
|
171
|
+
status: taskStatus.get(taskName),
|
|
172
|
+
inputs: node.inputPaths.map(pathToString),
|
|
173
|
+
output: pathToString(node.outputPath),
|
|
174
|
+
dependsOn: taskDependsOn.get(taskName) ?? [],
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// Compute summary
|
|
178
|
+
const summary = {
|
|
179
|
+
datasets: {
|
|
180
|
+
total: datasetStatusInfos.length,
|
|
181
|
+
unset: datasetStatusInfos.filter((d) => d.status.type === 'unset').length,
|
|
182
|
+
stale: datasetStatusInfos.filter((d) => d.status.type === 'stale').length,
|
|
183
|
+
upToDate: datasetStatusInfos.filter((d) => d.status.type === 'up-to-date').length,
|
|
184
|
+
},
|
|
185
|
+
tasks: {
|
|
186
|
+
total: taskStatusInfos.length,
|
|
187
|
+
upToDate: taskStatusInfos.filter((t) => t.status.type === 'up-to-date').length,
|
|
188
|
+
ready: taskStatusInfos.filter((t) => t.status.type === 'ready').length,
|
|
189
|
+
waiting: taskStatusInfos.filter((t) => t.status.type === 'waiting').length,
|
|
190
|
+
inProgress: taskStatusInfos.filter((t) => t.status.type === 'in-progress').length,
|
|
191
|
+
failed: taskStatusInfos.filter((t) => t.status.type === 'failed').length,
|
|
192
|
+
error: taskStatusInfos.filter((t) => t.status.type === 'error').length,
|
|
193
|
+
staleRunning: taskStatusInfos.filter((t) => t.status.type === 'stale-running').length,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
workspace: ws,
|
|
198
|
+
lock,
|
|
199
|
+
datasets: datasetStatusInfos,
|
|
200
|
+
tasks: taskStatusInfos,
|
|
201
|
+
summary,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
// =============================================================================
|
|
205
|
+
// Helper Functions
|
|
206
|
+
// =============================================================================
|
|
207
|
+
/**
|
|
208
|
+
* Recursively collect all dataset paths from a structure.
|
|
209
|
+
*/
|
|
210
|
+
function collectDatasetPaths(structure, currentPath, result) {
|
|
211
|
+
if (structure.type === 'value') {
|
|
212
|
+
result.push(currentPath);
|
|
213
|
+
}
|
|
214
|
+
else if (structure.type === 'struct') {
|
|
215
|
+
for (const [fieldName, childStructure] of structure.value) {
|
|
216
|
+
const childPath = [...currentPath, variant('field', fieldName)];
|
|
217
|
+
collectDatasetPaths(childStructure, childPath, result);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Compute the status of a task.
|
|
223
|
+
*/
|
|
224
|
+
async function computeTaskStatus(repoPath, ws, node, outputToTask, _taskNodes, _taskIsStale) {
|
|
225
|
+
// First, check if execution is in progress
|
|
226
|
+
const inProgressStatus = await checkInProgress(repoPath, node.hash);
|
|
227
|
+
if (inProgressStatus) {
|
|
228
|
+
return inProgressStatus;
|
|
229
|
+
}
|
|
230
|
+
// Gather current input hashes
|
|
231
|
+
const currentInputHashes = [];
|
|
232
|
+
let hasUnsetInputs = false;
|
|
233
|
+
let waitingOnTasks = [];
|
|
234
|
+
for (const inputPath of node.inputPaths) {
|
|
235
|
+
const inputPathStr = pathToString(inputPath);
|
|
236
|
+
const { refType, hash } = await workspaceGetDatasetHash(repoPath, ws, inputPath);
|
|
237
|
+
if (refType === 'unassigned' || hash === null) {
|
|
238
|
+
hasUnsetInputs = true;
|
|
239
|
+
// Check if this is produced by another task
|
|
240
|
+
const producerTask = outputToTask.get(inputPathStr);
|
|
241
|
+
if (producerTask) {
|
|
242
|
+
waitingOnTasks.push(producerTask);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// External input that is unset
|
|
246
|
+
return {
|
|
247
|
+
type: 'waiting',
|
|
248
|
+
reason: `Input '${inputPathStr}' is not set`,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
currentInputHashes.push(hash);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// If any inputs are unset and produced by tasks, we're waiting
|
|
257
|
+
if (hasUnsetInputs && waitingOnTasks.length > 0) {
|
|
258
|
+
return {
|
|
259
|
+
type: 'waiting',
|
|
260
|
+
reason: `Waiting for task(s): ${waitingOnTasks.join(', ')}`,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
// If any inputs are unset (external), we're waiting
|
|
264
|
+
if (hasUnsetInputs) {
|
|
265
|
+
return {
|
|
266
|
+
type: 'waiting',
|
|
267
|
+
reason: 'Some inputs are not set',
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// Check the execution status for these inputs
|
|
271
|
+
const inHash = inputsHash(currentInputHashes);
|
|
272
|
+
const execStatus = await executionGet(repoPath, node.hash, inHash);
|
|
273
|
+
if (execStatus === null) {
|
|
274
|
+
// No execution attempted - task is ready to run
|
|
275
|
+
return { type: 'ready' };
|
|
276
|
+
}
|
|
277
|
+
// Check the execution status type
|
|
278
|
+
switch (execStatus.type) {
|
|
279
|
+
case 'running': {
|
|
280
|
+
// Execution was marked as running - check if process is still alive
|
|
281
|
+
// For now, just report it (process liveness check is done in checkInProgress)
|
|
282
|
+
// If we reach here, checkInProgress didn't find it, so it might be stale
|
|
283
|
+
return {
|
|
284
|
+
type: 'stale-running',
|
|
285
|
+
pid: Number(execStatus.value.pid),
|
|
286
|
+
startedAt: execStatus.value.startedAt.toISOString(),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
case 'failed': {
|
|
290
|
+
// Task ran but returned non-zero exit code
|
|
291
|
+
return {
|
|
292
|
+
type: 'failed',
|
|
293
|
+
exitCode: Number(execStatus.value.exitCode),
|
|
294
|
+
completedAt: execStatus.value.completedAt.toISOString(),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
case 'error': {
|
|
298
|
+
// Internal error during execution
|
|
299
|
+
return {
|
|
300
|
+
type: 'error',
|
|
301
|
+
message: execStatus.value.message,
|
|
302
|
+
completedAt: execStatus.value.completedAt.toISOString(),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
case 'success': {
|
|
306
|
+
// Execution succeeded - check if workspace output matches
|
|
307
|
+
const cachedOutputHash = execStatus.value.outputHash;
|
|
308
|
+
const { refType, hash: wsOutputHash } = await workspaceGetDatasetHash(repoPath, ws, node.outputPath);
|
|
309
|
+
if (refType !== 'value' || wsOutputHash !== cachedOutputHash) {
|
|
310
|
+
// Workspace output doesn't match - task needs to run
|
|
311
|
+
// (This might happen if workspace was modified externally)
|
|
312
|
+
return { type: 'ready' };
|
|
313
|
+
}
|
|
314
|
+
// Everything matches - task is up-to-date
|
|
315
|
+
return { type: 'up-to-date', cached: true };
|
|
316
|
+
}
|
|
317
|
+
default:
|
|
318
|
+
// Unknown status type - treat as ready
|
|
319
|
+
return { type: 'ready' };
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Check if an execution is currently in progress for a task.
|
|
324
|
+
*
|
|
325
|
+
* Looks for a 'running' execution status that is still alive.
|
|
326
|
+
*/
|
|
327
|
+
async function checkInProgress(repoPath, taskHash) {
|
|
328
|
+
// List all executions for this task
|
|
329
|
+
const execDir = path.join(repoPath, 'executions', taskHash);
|
|
330
|
+
try {
|
|
331
|
+
const entries = await fs.readdir(execDir);
|
|
332
|
+
for (const inHash of entries) {
|
|
333
|
+
if (!/^[a-f0-9]{64}$/.test(inHash))
|
|
334
|
+
continue;
|
|
335
|
+
const status = await executionGet(repoPath, taskHash, inHash);
|
|
336
|
+
if (status?.type === 'running') {
|
|
337
|
+
// Found a running execution
|
|
338
|
+
// We could also verify the process is still alive here
|
|
339
|
+
return {
|
|
340
|
+
type: 'in-progress',
|
|
341
|
+
pid: Number(status.value.pid),
|
|
342
|
+
startedAt: status.value.startedAt.toISOString(),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
// No executions directory
|
|
349
|
+
}
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=workspaceStatus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceStatus.js","sourceRoot":"","sources":["../../src/workspaceStatus.ts"],"names":[],"mappings":"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"}
|
package/dist/src/workspaces.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
-
*
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import type { WorkspaceState } from '@elaraai/e3-types';
|
|
6
|
+
import { type WorkspaceLockHandle } from './workspaceLock.js';
|
|
6
7
|
/**
|
|
7
8
|
* Create an empty workspace.
|
|
8
9
|
*
|
|
@@ -14,16 +15,32 @@ import type { WorkspaceState } from '@elaraai/e3-types';
|
|
|
14
15
|
* @throws {WorkspaceExistsError} If workspace already exists
|
|
15
16
|
*/
|
|
16
17
|
export declare function workspaceCreate(repoPath: string, name: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Options for workspace removal.
|
|
20
|
+
*/
|
|
21
|
+
export interface WorkspaceRemoveOptions {
|
|
22
|
+
/**
|
|
23
|
+
* External workspace lock to use. If provided, the caller is responsible
|
|
24
|
+
* for releasing the lock after the operation. If not provided, workspaceRemove
|
|
25
|
+
* will acquire and release a lock internally.
|
|
26
|
+
*/
|
|
27
|
+
lock?: WorkspaceLockHandle;
|
|
28
|
+
}
|
|
17
29
|
/**
|
|
18
30
|
* Remove a workspace.
|
|
19
31
|
*
|
|
20
32
|
* Objects remain until repoGc is run.
|
|
21
33
|
*
|
|
34
|
+
* Acquires a workspace lock to prevent removing a workspace while a dataflow
|
|
35
|
+
* is running. Throws WorkspaceLockError if the workspace is currently locked.
|
|
36
|
+
*
|
|
22
37
|
* @param repoPath - Path to .e3 repository
|
|
23
38
|
* @param name - Workspace name
|
|
39
|
+
* @param options - Optional settings including external lock
|
|
24
40
|
* @throws {WorkspaceNotFoundError} If workspace doesn't exist
|
|
41
|
+
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
25
42
|
*/
|
|
26
|
-
export declare function workspaceRemove(repoPath: string, name: string): Promise<void>;
|
|
43
|
+
export declare function workspaceRemove(repoPath: string, name: string, options?: WorkspaceRemoveOptions): Promise<void>;
|
|
27
44
|
/**
|
|
28
45
|
* List workspace names.
|
|
29
46
|
*
|
|
@@ -73,18 +90,35 @@ export declare function workspaceGetRoot(repoPath: string, name: string): Promis
|
|
|
73
90
|
* @throws {WorkspaceNotDeployedError} If workspace exists but has no package deployed
|
|
74
91
|
*/
|
|
75
92
|
export declare function workspaceSetRoot(repoPath: string, name: string, hash: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Options for workspace deployment.
|
|
95
|
+
*/
|
|
96
|
+
export interface WorkspaceDeployOptions {
|
|
97
|
+
/**
|
|
98
|
+
* External workspace lock to use. If provided, the caller is responsible
|
|
99
|
+
* for releasing the lock after the operation. If not provided, workspaceDeploy
|
|
100
|
+
* will acquire and release a lock internally.
|
|
101
|
+
*/
|
|
102
|
+
lock?: WorkspaceLockHandle;
|
|
103
|
+
}
|
|
76
104
|
/**
|
|
77
105
|
* Deploy a package to a workspace.
|
|
78
106
|
*
|
|
79
107
|
* Creates the workspace if it doesn't exist. Writes state file atomically
|
|
80
108
|
* containing deployment info and root hash.
|
|
81
109
|
*
|
|
110
|
+
* Acquires a workspace lock to prevent conflicts with running dataflows
|
|
111
|
+
* or concurrent deploys. Throws WorkspaceLockError if the workspace is
|
|
112
|
+
* currently locked by another process.
|
|
113
|
+
*
|
|
82
114
|
* @param repoPath - Path to .e3 repository
|
|
83
115
|
* @param name - Workspace name
|
|
84
116
|
* @param pkgName - Package name
|
|
85
117
|
* @param pkgVersion - Package version
|
|
118
|
+
* @param options - Optional settings including external lock
|
|
119
|
+
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
86
120
|
*/
|
|
87
|
-
export declare function workspaceDeploy(repoPath: string, name: string, pkgName: string, pkgVersion: string): Promise<void>;
|
|
121
|
+
export declare function workspaceDeploy(repoPath: string, name: string, pkgName: string, pkgVersion: string, options?: WorkspaceDeployOptions): Promise<void>;
|
|
88
122
|
/**
|
|
89
123
|
* Result of exporting a workspace
|
|
90
124
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../../src/workspaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,OAAO,KAAK,EAAiB,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASvE,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AA6EpF;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAMhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAO1D;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CA0Bf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,CAAC,CAqGhC"}
|