@elaraai/e3-core 0.0.2-beta.4 → 0.0.2-beta.41
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 +139 -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 +76 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/LocalOrchestrator.js +695 -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 +163 -0
- package/dist/src/dataflow/orchestrator/interfaces.d.ts.map +1 -0
- package/dist/src/dataflow/orchestrator/interfaces.js +52 -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 +300 -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 +229 -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 +222 -0
- package/dist/src/dataflow/steps.d.ts.map +1 -0
- package/dist/src/dataflow/steps.js +707 -0
- package/dist/src/dataflow/steps.js.map +1 -0
- package/dist/src/dataflow/types.d.ts +127 -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 +113 -38
- package/dist/src/dataflow.d.ts.map +1 -1
- package/dist/src/dataflow.js +269 -416
- package/dist/src/dataflow.js.map +1 -1
- package/dist/src/dataset-refs.d.ts +124 -0
- package/dist/src/dataset-refs.d.ts.map +1 -0
- package/dist/src/dataset-refs.js +319 -0
- package/dist/src/dataset-refs.js.map +1 -0
- 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 +54 -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 +19 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +48 -18
- package/dist/src/index.js.map +1 -1
- package/dist/src/objects.d.ts +8 -51
- package/dist/src/objects.d.ts.map +1 -1
- package/dist/src/objects.js +13 -230
- 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 +134 -88
- 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 +139 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.js +439 -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 +581 -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 +56 -0
- package/dist/src/storage/local/LocalBackend.d.ts.map +1 -0
- package/dist/src/storage/local/LocalBackend.js +145 -0
- package/dist/src/storage/local/LocalBackend.js.map +1 -0
- package/dist/src/storage/local/LocalDatasetRefStore.d.ts +22 -0
- package/dist/src/storage/local/LocalDatasetRefStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalDatasetRefStore.js +118 -0
- package/dist/src/storage/local/LocalDatasetRefStore.js.map +1 -0
- package/dist/src/storage/local/LocalLockService.d.ts +111 -0
- package/dist/src/storage/local/LocalLockService.d.ts.map +1 -0
- package/dist/src/storage/local/LocalLockService.js +355 -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 +55 -0
- package/dist/src/storage/local/LocalObjectStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalObjectStore.js +300 -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 +55 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.js +365 -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 +377 -0
- package/dist/src/storage/local/gc.js.map +1 -0
- package/dist/src/storage/local/index.d.ts +18 -0
- package/dist/src/storage/local/index.d.ts.map +1 -0
- package/dist/src/storage/local/index.js +18 -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 +5 -4
- package/dist/src/test-helpers.d.ts.map +1 -1
- package/dist/src/test-helpers.js +9 -21
- package/dist/src/test-helpers.js.map +1 -1
- package/dist/src/transfer/InMemoryTransferBackend.d.ts +66 -0
- package/dist/src/transfer/InMemoryTransferBackend.d.ts.map +1 -0
- package/dist/src/transfer/InMemoryTransferBackend.js +166 -0
- package/dist/src/transfer/InMemoryTransferBackend.js.map +1 -0
- package/dist/src/transfer/index.d.ts +8 -0
- package/dist/src/transfer/index.d.ts.map +1 -0
- package/dist/src/transfer/index.js +9 -0
- package/dist/src/transfer/index.js.map +1 -0
- package/dist/src/transfer/interfaces.d.ts +103 -0
- package/dist/src/transfer/interfaces.d.ts.map +1 -0
- package/dist/src/transfer/interfaces.js +6 -0
- package/dist/src/transfer/interfaces.js.map +1 -0
- package/dist/src/transfer/types.d.ts +79 -0
- package/dist/src/transfer/types.d.ts.map +1 -0
- package/dist/src/transfer/types.js +58 -0
- package/dist/src/transfer/types.js.map +1 -0
- package/dist/src/trees.d.ts +147 -59
- package/dist/src/trees.d.ts.map +1 -1
- package/dist/src/trees.js +372 -419
- 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 -47
- package/dist/src/workspaces.d.ts.map +1 -1
- package/dist/src/workspaces.js +194 -156
- 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
package/dist/src/gc.js
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
-
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Garbage collection for e3 repositories.
|
|
7
|
-
*
|
|
8
|
-
* Uses mark-and-sweep algorithm:
|
|
9
|
-
* 1. Mark: Find all root refs (packages, executions, workspaces) and trace reachable objects
|
|
10
|
-
* 2. Sweep: Delete unreachable objects and orphaned staging files
|
|
11
|
-
*/
|
|
12
|
-
import * as fs from 'fs/promises';
|
|
13
|
-
import * as path from 'path';
|
|
14
|
-
import { decodeBeast2For } from '@elaraai/east';
|
|
15
|
-
import { WorkspaceStateType } from '@elaraai/e3-types';
|
|
16
|
-
import { objectRead } from './objects.js';
|
|
17
|
-
/**
|
|
18
|
-
* Run garbage collection on an e3 repository.
|
|
19
|
-
*
|
|
20
|
-
* @param repoPath - Path to .e3 repository
|
|
21
|
-
* @param options - GC options
|
|
22
|
-
* @returns GC result with statistics
|
|
23
|
-
*/
|
|
24
|
-
export async function repoGc(repoPath, options = {}) {
|
|
25
|
-
const minAge = options.minAge ?? 60000; // Default 1 minute
|
|
26
|
-
const dryRun = options.dryRun ?? false;
|
|
27
|
-
const now = Date.now();
|
|
28
|
-
// Step 1: Collect all root hashes
|
|
29
|
-
const roots = await collectRoots(repoPath);
|
|
30
|
-
// Step 2: Mark all reachable objects starting from roots
|
|
31
|
-
const reachable = new Set();
|
|
32
|
-
for (const root of roots) {
|
|
33
|
-
await markReachable(repoPath, root, reachable);
|
|
34
|
-
}
|
|
35
|
-
// Step 3: Sweep - enumerate all objects and delete unreachable ones
|
|
36
|
-
const result = await sweep(repoPath, reachable, minAge, now, dryRun);
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Collect all root hashes from refs in packages, executions, and workspaces.
|
|
41
|
-
*/
|
|
42
|
-
async function collectRoots(repoPath) {
|
|
43
|
-
const roots = new Set();
|
|
44
|
-
// Collect from packages/<name>/<version> files
|
|
45
|
-
const packagesDir = path.join(repoPath, 'packages');
|
|
46
|
-
await collectRefsFromDir(packagesDir, roots, 2); // depth 2: packages/<name>/<version>
|
|
47
|
-
// Collect from executions/<taskHash>/<inputsHash>/output files
|
|
48
|
-
const executionsDir = path.join(repoPath, 'executions');
|
|
49
|
-
await collectRefsFromDir(executionsDir, roots, 3); // depth 3: executions/<taskHash>/<inputsHash>/output
|
|
50
|
-
// Collect from workspaces/<name>/state.beast2 files
|
|
51
|
-
const workspacesDir = path.join(repoPath, 'workspaces');
|
|
52
|
-
await collectWorkspaceRoots(workspacesDir, roots);
|
|
53
|
-
return roots;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Collect root hashes from workspace state files.
|
|
57
|
-
*/
|
|
58
|
-
async function collectWorkspaceRoots(workspacesDir, roots) {
|
|
59
|
-
try {
|
|
60
|
-
const entries = await fs.readdir(workspacesDir);
|
|
61
|
-
for (const entry of entries) {
|
|
62
|
-
if (!entry.endsWith('.beast2'))
|
|
63
|
-
continue;
|
|
64
|
-
const stateFile = path.join(workspacesDir, entry);
|
|
65
|
-
try {
|
|
66
|
-
const data = await fs.readFile(stateFile);
|
|
67
|
-
// Skip empty files (undeployed workspaces)
|
|
68
|
-
if (data.length === 0)
|
|
69
|
-
continue;
|
|
70
|
-
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
71
|
-
const state = decoder(data);
|
|
72
|
-
// Add both the package hash and root hash as roots
|
|
73
|
-
roots.add(state.packageHash);
|
|
74
|
-
roots.add(state.rootHash);
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
// State file can't be parsed - skip
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
// Workspaces directory doesn't exist
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Recursively collect hashes from ref files in a directory.
|
|
87
|
-
*
|
|
88
|
-
* @param dir - Directory to scan
|
|
89
|
-
* @param roots - Set to add found hashes to
|
|
90
|
-
* @param maxDepth - Maximum depth to traverse
|
|
91
|
-
*/
|
|
92
|
-
async function collectRefsFromDir(dir, roots, maxDepth, currentDepth = 0) {
|
|
93
|
-
try {
|
|
94
|
-
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
95
|
-
for (const entry of entries) {
|
|
96
|
-
const entryPath = path.join(dir, entry.name);
|
|
97
|
-
if (entry.isDirectory() && currentDepth < maxDepth) {
|
|
98
|
-
await collectRefsFromDir(entryPath, roots, maxDepth, currentDepth + 1);
|
|
99
|
-
}
|
|
100
|
-
else if (entry.isFile()) {
|
|
101
|
-
// Read the ref file - it contains a hash
|
|
102
|
-
try {
|
|
103
|
-
const content = await fs.readFile(entryPath, 'utf-8');
|
|
104
|
-
const hash = content.trim();
|
|
105
|
-
// Validate it looks like a SHA256 hash
|
|
106
|
-
if (/^[a-f0-9]{64}$/.test(hash)) {
|
|
107
|
-
roots.add(hash);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
// Skip files we can't read
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
// Directory doesn't exist or can't be read - that's fine
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Mark all objects reachable from a root hash.
|
|
122
|
-
*
|
|
123
|
-
* Traverses the object graph by scanning for hash patterns in the data.
|
|
124
|
-
*/
|
|
125
|
-
async function markReachable(repoPath, hash, reachable) {
|
|
126
|
-
// Already visited?
|
|
127
|
-
if (reachable.has(hash)) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
// Try to load the object
|
|
131
|
-
try {
|
|
132
|
-
const data = await objectRead(repoPath, hash);
|
|
133
|
-
reachable.add(hash);
|
|
134
|
-
// Scan for hash patterns in the data
|
|
135
|
-
const dataStr = Buffer.from(data).toString('latin1');
|
|
136
|
-
const hashPattern = /[a-f0-9]{64}/g;
|
|
137
|
-
const matches = dataStr.matchAll(hashPattern);
|
|
138
|
-
for (const match of matches) {
|
|
139
|
-
const potentialHash = match[0];
|
|
140
|
-
if (!reachable.has(potentialHash)) {
|
|
141
|
-
// Recursively mark if it exists
|
|
142
|
-
await markReachable(repoPath, potentialHash, reachable);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
// Object doesn't exist - not an error, just means this hash
|
|
148
|
-
// wasn't actually a reference to an object
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Sweep unreachable objects and orphaned staging files.
|
|
153
|
-
*/
|
|
154
|
-
async function sweep(repoPath, reachable, minAge, now, dryRun) {
|
|
155
|
-
const objectsDir = path.join(repoPath, 'objects');
|
|
156
|
-
const result = {
|
|
157
|
-
deletedObjects: 0,
|
|
158
|
-
deletedPartials: 0,
|
|
159
|
-
retainedObjects: 0,
|
|
160
|
-
skippedYoung: 0,
|
|
161
|
-
bytesFreed: 0,
|
|
162
|
-
};
|
|
163
|
-
try {
|
|
164
|
-
// Iterate through objects/xx/ directories
|
|
165
|
-
const subdirs = await fs.readdir(objectsDir);
|
|
166
|
-
for (const subdir of subdirs) {
|
|
167
|
-
// Skip if not a 2-char hex directory
|
|
168
|
-
if (!/^[a-f0-9]{2}$/.test(subdir)) {
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
const subdirPath = path.join(objectsDir, subdir);
|
|
172
|
-
const stat = await fs.stat(subdirPath);
|
|
173
|
-
if (!stat.isDirectory()) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
const files = await fs.readdir(subdirPath);
|
|
177
|
-
for (const file of files) {
|
|
178
|
-
const filePath = path.join(subdirPath, file);
|
|
179
|
-
try {
|
|
180
|
-
const fileStat = await fs.stat(filePath);
|
|
181
|
-
// Check age - skip young files to avoid race with concurrent writes
|
|
182
|
-
// Note: age can be negative if file was written after 'now' was captured
|
|
183
|
-
const age = now - fileStat.mtimeMs;
|
|
184
|
-
if (minAge > 0 && age < minAge) {
|
|
185
|
-
result.skippedYoung++;
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
// Handle .partial staging files
|
|
189
|
-
if (file.endsWith('.partial')) {
|
|
190
|
-
if (!dryRun) {
|
|
191
|
-
await fs.unlink(filePath);
|
|
192
|
-
}
|
|
193
|
-
result.deletedPartials++;
|
|
194
|
-
result.bytesFreed += fileStat.size;
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
// Handle .beast2 object files
|
|
198
|
-
if (file.endsWith('.beast2')) {
|
|
199
|
-
// Reconstruct the hash: subdir (2 chars) + filename without extension
|
|
200
|
-
const hash = subdir + file.slice(0, -7); // -7 removes '.beast2'
|
|
201
|
-
if (reachable.has(hash)) {
|
|
202
|
-
result.retainedObjects++;
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
if (!dryRun) {
|
|
206
|
-
await fs.unlink(filePath);
|
|
207
|
-
}
|
|
208
|
-
result.deletedObjects++;
|
|
209
|
-
result.bytesFreed += fileStat.size;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
// Skip files we can't stat or delete
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// Try to remove empty subdirectory
|
|
218
|
-
if (!dryRun) {
|
|
219
|
-
try {
|
|
220
|
-
await fs.rmdir(subdirPath);
|
|
221
|
-
}
|
|
222
|
-
catch {
|
|
223
|
-
// Directory not empty, that's fine
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
// Objects directory doesn't exist or can't be read
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=gc.js.map
|
package/dist/src/gc.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gc.js","sourceRoot":"","sources":["../../src/gc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAyC/D;AAYD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0B1D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAQjD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,67 +0,0 @@
|
|
|
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
|
-
* Handle to a held workspace lock.
|
|
8
|
-
* Call release() when done to free the lock.
|
|
9
|
-
*/
|
|
10
|
-
export interface WorkspaceLockHandle {
|
|
11
|
-
/** The workspace name this lock is for */
|
|
12
|
-
readonly workspace: string;
|
|
13
|
-
/** Path to the lock file */
|
|
14
|
-
readonly lockPath: string;
|
|
15
|
-
/** Release the lock. Safe to call multiple times. */
|
|
16
|
-
release(): Promise<void>;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Options for acquiring a workspace lock.
|
|
20
|
-
*/
|
|
21
|
-
export interface AcquireLockOptions {
|
|
22
|
-
/**
|
|
23
|
-
* If true, wait for the lock to become available instead of failing immediately.
|
|
24
|
-
* Default: false (fail fast if locked)
|
|
25
|
-
*/
|
|
26
|
-
wait?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Timeout in milliseconds when wait=true. Default: 30000 (30 seconds)
|
|
29
|
-
*/
|
|
30
|
-
timeout?: number;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get the lock file path for a workspace.
|
|
34
|
-
*/
|
|
35
|
-
export declare function workspaceLockPath(repoPath: string, workspace: string): string;
|
|
36
|
-
/**
|
|
37
|
-
* Acquire an exclusive lock on a workspace.
|
|
38
|
-
*
|
|
39
|
-
* Uses Linux flock() for kernel-managed locking. The lock is automatically
|
|
40
|
-
* released when the process exits (even on crash/kill).
|
|
41
|
-
*
|
|
42
|
-
* @param repoPath - Path to .e3 repository
|
|
43
|
-
* @param workspace - Workspace name to lock
|
|
44
|
-
* @param options - Lock acquisition options
|
|
45
|
-
* @returns Lock handle - call release() when done
|
|
46
|
-
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```typescript
|
|
50
|
-
* const lock = await acquireWorkspaceLock(repoPath, 'production');
|
|
51
|
-
* try {
|
|
52
|
-
* await dataflowExecute(repoPath, 'production', { lock });
|
|
53
|
-
* } finally {
|
|
54
|
-
* await lock.release();
|
|
55
|
-
* }
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export declare function acquireWorkspaceLock(repoPath: string, workspace: string, options?: AcquireLockOptions): Promise<WorkspaceLockHandle>;
|
|
59
|
-
/**
|
|
60
|
-
* Check if a workspace is currently locked.
|
|
61
|
-
*
|
|
62
|
-
* @param repoPath - Path to .e3 repository
|
|
63
|
-
* @param workspace - Workspace name to check
|
|
64
|
-
* @returns Lock holder info if locked, null if not locked
|
|
65
|
-
*/
|
|
66
|
-
export declare function getWorkspaceLockHolder(repoPath: string, workspace: string): Promise<LockHolder | null>;
|
|
67
|
-
//# sourceMappingURL=workspaceLock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceLock.d.ts","sourceRoot":"","sources":["../../src/workspaceLock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAOlE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAcD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7E;AAgCD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,mBAAmB,CAAC,CAiD9B;AAsFD;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAoB5B"}
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
-
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Workspace locking for safe concurrent access.
|
|
7
|
-
*
|
|
8
|
-
* Provides exclusive locks on workspaces to prevent concurrent dataflow
|
|
9
|
-
* executions or writes that could corrupt workspace state. Uses Linux
|
|
10
|
-
* flock() for automatic lock release on process death.
|
|
11
|
-
*
|
|
12
|
-
* Lock mechanism:
|
|
13
|
-
* - Uses flock(LOCK_EX | LOCK_NB) via the `flock` command for kernel-managed locking
|
|
14
|
-
* - Lock is automatically released when the process dies (kernel handles this)
|
|
15
|
-
* - Metadata (PID, bootId, startTime) written to lock file for diagnostics
|
|
16
|
-
* - Stale lock detection via bootId comparison (handles system restarts)
|
|
17
|
-
*/
|
|
18
|
-
import * as fs from 'fs/promises';
|
|
19
|
-
import * as path from 'path';
|
|
20
|
-
import { spawn } from 'child_process';
|
|
21
|
-
import { WorkspaceLockError } from './errors.js';
|
|
22
|
-
import { getBootId, getPidStartTime, isProcessAlive } from './executions.js';
|
|
23
|
-
/**
|
|
24
|
-
* Get the lock file path for a workspace.
|
|
25
|
-
*/
|
|
26
|
-
export function workspaceLockPath(repoPath, workspace) {
|
|
27
|
-
return path.join(repoPath, 'workspaces', `${workspace}.lock`);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Read lock metadata from a lock file.
|
|
31
|
-
* Returns null if file doesn't exist or is invalid.
|
|
32
|
-
*/
|
|
33
|
-
async function readLockMetadata(lockPath) {
|
|
34
|
-
try {
|
|
35
|
-
const data = await fs.readFile(lockPath, 'utf-8');
|
|
36
|
-
return JSON.parse(data);
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Convert internal metadata to public LockHolder interface.
|
|
44
|
-
*/
|
|
45
|
-
function metadataToHolder(metadata) {
|
|
46
|
-
return {
|
|
47
|
-
pid: metadata.pid,
|
|
48
|
-
acquiredAt: metadata.acquiredAt,
|
|
49
|
-
bootId: metadata.bootId,
|
|
50
|
-
startTime: metadata.startTime,
|
|
51
|
-
command: metadata.command,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
// =============================================================================
|
|
55
|
-
// Lock Acquisition
|
|
56
|
-
// =============================================================================
|
|
57
|
-
/**
|
|
58
|
-
* Acquire an exclusive lock on a workspace.
|
|
59
|
-
*
|
|
60
|
-
* Uses Linux flock() for kernel-managed locking. The lock is automatically
|
|
61
|
-
* released when the process exits (even on crash/kill).
|
|
62
|
-
*
|
|
63
|
-
* @param repoPath - Path to .e3 repository
|
|
64
|
-
* @param workspace - Workspace name to lock
|
|
65
|
-
* @param options - Lock acquisition options
|
|
66
|
-
* @returns Lock handle - call release() when done
|
|
67
|
-
* @throws {WorkspaceLockError} If workspace is locked by another process
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* const lock = await acquireWorkspaceLock(repoPath, 'production');
|
|
72
|
-
* try {
|
|
73
|
-
* await dataflowExecute(repoPath, 'production', { lock });
|
|
74
|
-
* } finally {
|
|
75
|
-
* await lock.release();
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export async function acquireWorkspaceLock(repoPath, workspace, options = {}) {
|
|
80
|
-
const lockPath = workspaceLockPath(repoPath, workspace);
|
|
81
|
-
// Ensure workspaces directory exists
|
|
82
|
-
await fs.mkdir(path.dirname(lockPath), { recursive: true });
|
|
83
|
-
// Gather our process identification
|
|
84
|
-
const pid = process.pid;
|
|
85
|
-
const bootId = await getBootId();
|
|
86
|
-
const startTime = await getPidStartTime(pid);
|
|
87
|
-
const command = process.argv.join(' ');
|
|
88
|
-
const acquiredAt = new Date().toISOString();
|
|
89
|
-
const metadata = { pid, bootId, startTime, acquiredAt, command };
|
|
90
|
-
// Try to acquire flock via subprocess
|
|
91
|
-
// The subprocess holds the lock and we communicate with it via stdin/signals
|
|
92
|
-
const flockProcess = await tryAcquireFlock(lockPath, metadata, options);
|
|
93
|
-
if (!flockProcess) {
|
|
94
|
-
// Failed to acquire - read metadata to report who has it
|
|
95
|
-
const existingMetadata = await readLockMetadata(lockPath);
|
|
96
|
-
const holder = existingMetadata ? metadataToHolder(existingMetadata) : undefined;
|
|
97
|
-
throw new WorkspaceLockError(workspace, holder);
|
|
98
|
-
}
|
|
99
|
-
// Lock acquired! Create handle
|
|
100
|
-
let released = false;
|
|
101
|
-
const handle = {
|
|
102
|
-
workspace,
|
|
103
|
-
lockPath,
|
|
104
|
-
async release() {
|
|
105
|
-
if (released)
|
|
106
|
-
return;
|
|
107
|
-
released = true;
|
|
108
|
-
// Kill the flock subprocess to release the lock
|
|
109
|
-
flockProcess.kill('SIGTERM');
|
|
110
|
-
// Clean up lock file (best effort)
|
|
111
|
-
try {
|
|
112
|
-
await fs.unlink(lockPath);
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
// Ignore - file might already be gone
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
return handle;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Try to acquire flock using a subprocess.
|
|
123
|
-
*
|
|
124
|
-
* We spawn `flock --nonblock <lockfile> cat` which:
|
|
125
|
-
* 1. Tries to acquire exclusive lock (non-blocking)
|
|
126
|
-
* 2. If successful, runs `cat` which blocks reading stdin forever
|
|
127
|
-
* 3. We keep the subprocess alive to hold the lock
|
|
128
|
-
* 4. When we kill the subprocess, the lock is released
|
|
129
|
-
*
|
|
130
|
-
* Returns the subprocess if lock acquired, null if lock is held by another.
|
|
131
|
-
*/
|
|
132
|
-
async function tryAcquireFlock(lockPath, metadata, options) {
|
|
133
|
-
// First, check if there's a stale lock we can clean up
|
|
134
|
-
await checkAndCleanStaleLock(lockPath);
|
|
135
|
-
const args = options.wait
|
|
136
|
-
? ['--timeout', String((options.timeout ?? 30000) / 1000), lockPath, 'cat']
|
|
137
|
-
: ['--nonblock', lockPath, 'cat'];
|
|
138
|
-
const child = spawn('flock', args, {
|
|
139
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
140
|
-
detached: false,
|
|
141
|
-
});
|
|
142
|
-
return new Promise((resolve) => {
|
|
143
|
-
let resolved = false;
|
|
144
|
-
// If flock fails to acquire, it exits with code 1
|
|
145
|
-
child.on('error', () => {
|
|
146
|
-
if (!resolved) {
|
|
147
|
-
resolved = true;
|
|
148
|
-
resolve(null);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
child.on('exit', () => {
|
|
152
|
-
if (!resolved) {
|
|
153
|
-
resolved = true;
|
|
154
|
-
// Exit code 1 means lock is held by another
|
|
155
|
-
resolve(null);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
// Give flock a moment to either acquire or fail
|
|
159
|
-
// If it's still running after 100ms, we have the lock
|
|
160
|
-
setTimeout(() => {
|
|
161
|
-
if (!resolved && !child.killed && child.exitCode === null) {
|
|
162
|
-
resolved = true;
|
|
163
|
-
// Write metadata to lock file now that we have the lock
|
|
164
|
-
// Use void to explicitly ignore the promise (metadata is informational only)
|
|
165
|
-
void fs.writeFile(lockPath, JSON.stringify(metadata, null, 2)).catch(() => { });
|
|
166
|
-
resolve(child);
|
|
167
|
-
}
|
|
168
|
-
}, 100);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Check if a lock file exists with stale metadata and clean it up.
|
|
173
|
-
* A lock is stale if the holder process no longer exists.
|
|
174
|
-
*/
|
|
175
|
-
async function checkAndCleanStaleLock(lockPath) {
|
|
176
|
-
const metadata = await readLockMetadata(lockPath);
|
|
177
|
-
if (!metadata)
|
|
178
|
-
return;
|
|
179
|
-
// Check if the process that created this lock is still alive
|
|
180
|
-
const alive = await isProcessAlive(metadata.pid, metadata.startTime, metadata.bootId);
|
|
181
|
-
if (!alive) {
|
|
182
|
-
// Stale lock - try to remove it
|
|
183
|
-
try {
|
|
184
|
-
await fs.unlink(lockPath);
|
|
185
|
-
}
|
|
186
|
-
catch {
|
|
187
|
-
// Ignore - another process might have cleaned it up
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Check if a workspace is currently locked.
|
|
193
|
-
*
|
|
194
|
-
* @param repoPath - Path to .e3 repository
|
|
195
|
-
* @param workspace - Workspace name to check
|
|
196
|
-
* @returns Lock holder info if locked, null if not locked
|
|
197
|
-
*/
|
|
198
|
-
export async function getWorkspaceLockHolder(repoPath, workspace) {
|
|
199
|
-
const lockPath = workspaceLockPath(repoPath, workspace);
|
|
200
|
-
const metadata = await readLockMetadata(lockPath);
|
|
201
|
-
if (!metadata)
|
|
202
|
-
return null;
|
|
203
|
-
// Check if the holder is still alive
|
|
204
|
-
const alive = await isProcessAlive(metadata.pid, metadata.startTime, metadata.bootId);
|
|
205
|
-
if (!alive) {
|
|
206
|
-
// Stale lock - clean it up and report as not locked
|
|
207
|
-
try {
|
|
208
|
-
await fs.unlink(lockPath);
|
|
209
|
-
}
|
|
210
|
-
catch {
|
|
211
|
-
// Ignore
|
|
212
|
-
}
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
return metadataToHolder(metadata);
|
|
216
|
-
}
|
|
217
|
-
//# sourceMappingURL=workspaceLock.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceLock.js","sourceRoot":"","sources":["../../src/workspaceLock.ts"],"names":[],"mappings":"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"}
|