@elaraai/e3-core 0.0.2-beta.4 → 0.0.2-beta.40
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
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { RepoNotFoundError, RepoAlreadyExistsError, RepoStatusConflictError, } from '../../errors.js';
|
|
8
|
+
import { decodeBeast2For } from '@elaraai/east';
|
|
9
|
+
import { WorkspaceStateType } from '@elaraai/e3-types';
|
|
10
|
+
const METADATA_FILENAME = '.e3-metadata.json';
|
|
11
|
+
/**
|
|
12
|
+
* Local filesystem implementation of RepoStore.
|
|
13
|
+
*
|
|
14
|
+
* Manages repository lifecycle for local e3 repositories stored
|
|
15
|
+
* as subdirectories within a parent directory.
|
|
16
|
+
*/
|
|
17
|
+
export class LocalRepoStore {
|
|
18
|
+
reposDir;
|
|
19
|
+
refs;
|
|
20
|
+
datasets;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new LocalRepoStore.
|
|
23
|
+
* @param reposDir - Parent directory containing repositories
|
|
24
|
+
* @param refs - RefStore for reading package/workspace/execution refs
|
|
25
|
+
* @param datasets - DatasetRefStore for reading per-dataset refs (for GC scanning)
|
|
26
|
+
*/
|
|
27
|
+
constructor(reposDir, refs, datasets) {
|
|
28
|
+
this.reposDir = reposDir;
|
|
29
|
+
this.refs = refs;
|
|
30
|
+
this.datasets = datasets;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the path to a repository directory.
|
|
34
|
+
*/
|
|
35
|
+
getRepoPath(repo) {
|
|
36
|
+
return path.join(this.reposDir, repo);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the path to a repository's metadata file.
|
|
40
|
+
*/
|
|
41
|
+
getMetadataPath(repo) {
|
|
42
|
+
return path.join(this.getRepoPath(repo), METADATA_FILENAME);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a directory is a valid e3 repository.
|
|
46
|
+
*/
|
|
47
|
+
async isValidRepository(repoPath) {
|
|
48
|
+
const requiredDirs = ['objects', 'packages', 'executions', 'workspaces'];
|
|
49
|
+
for (const dir of requiredDirs) {
|
|
50
|
+
try {
|
|
51
|
+
const stat = await fs.stat(path.join(repoPath, dir));
|
|
52
|
+
if (!stat.isDirectory()) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// ===========================================================================
|
|
63
|
+
// Queries
|
|
64
|
+
// ===========================================================================
|
|
65
|
+
async list() {
|
|
66
|
+
const repos = [];
|
|
67
|
+
try {
|
|
68
|
+
const entries = await fs.readdir(this.reposDir, { withFileTypes: true });
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
if (entry.isDirectory()) {
|
|
71
|
+
const repoPath = path.join(this.reposDir, entry.name);
|
|
72
|
+
if (await this.isValidRepository(repoPath)) {
|
|
73
|
+
repos.push(entry.name);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// reposDir doesn't exist or can't be read
|
|
80
|
+
}
|
|
81
|
+
return repos;
|
|
82
|
+
}
|
|
83
|
+
async exists(repo) {
|
|
84
|
+
const repoPath = this.getRepoPath(repo);
|
|
85
|
+
return this.isValidRepository(repoPath);
|
|
86
|
+
}
|
|
87
|
+
async getMetadata(repo) {
|
|
88
|
+
const repoPath = this.getRepoPath(repo);
|
|
89
|
+
// Check if repo exists
|
|
90
|
+
if (!(await this.isValidRepository(repoPath))) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const metadataPath = this.getMetadataPath(repo);
|
|
94
|
+
try {
|
|
95
|
+
const content = await fs.readFile(metadataPath, 'utf-8');
|
|
96
|
+
const metadata = JSON.parse(content);
|
|
97
|
+
return {
|
|
98
|
+
name: metadata.name,
|
|
99
|
+
status: metadata.status,
|
|
100
|
+
createdAt: metadata.createdAt,
|
|
101
|
+
statusChangedAt: metadata.statusChangedAt,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// No metadata file - synthesize for legacy repos
|
|
106
|
+
// Get mtime from repo directory for createdAt
|
|
107
|
+
try {
|
|
108
|
+
const stat = await fs.stat(repoPath);
|
|
109
|
+
const createdAt = stat.birthtime.toISOString();
|
|
110
|
+
return {
|
|
111
|
+
name: repo,
|
|
112
|
+
status: 'active',
|
|
113
|
+
createdAt,
|
|
114
|
+
statusChangedAt: createdAt,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ===========================================================================
|
|
123
|
+
// Lifecycle
|
|
124
|
+
// ===========================================================================
|
|
125
|
+
async create(repo) {
|
|
126
|
+
const repoPath = this.getRepoPath(repo);
|
|
127
|
+
// Check if already exists
|
|
128
|
+
if (await this.isValidRepository(repoPath)) {
|
|
129
|
+
throw new RepoAlreadyExistsError(repo);
|
|
130
|
+
}
|
|
131
|
+
// Create directory structure
|
|
132
|
+
await fs.mkdir(repoPath, { recursive: true });
|
|
133
|
+
await fs.mkdir(path.join(repoPath, 'objects'), { recursive: true });
|
|
134
|
+
await fs.mkdir(path.join(repoPath, 'packages'), { recursive: true });
|
|
135
|
+
await fs.mkdir(path.join(repoPath, 'executions'), { recursive: true });
|
|
136
|
+
await fs.mkdir(path.join(repoPath, 'workspaces'), { recursive: true });
|
|
137
|
+
// Write metadata file
|
|
138
|
+
const now = new Date().toISOString();
|
|
139
|
+
const metadata = {
|
|
140
|
+
name: repo,
|
|
141
|
+
status: 'active',
|
|
142
|
+
createdAt: now,
|
|
143
|
+
statusChangedAt: now,
|
|
144
|
+
};
|
|
145
|
+
await fs.writeFile(this.getMetadataPath(repo), JSON.stringify(metadata, null, 2));
|
|
146
|
+
}
|
|
147
|
+
async setStatus(repo, status, expected) {
|
|
148
|
+
const current = await this.getMetadata(repo);
|
|
149
|
+
if (!current) {
|
|
150
|
+
throw new RepoNotFoundError(repo);
|
|
151
|
+
}
|
|
152
|
+
// Check expected status (CAS)
|
|
153
|
+
if (expected !== undefined) {
|
|
154
|
+
const expectedArray = Array.isArray(expected) ? expected : [expected];
|
|
155
|
+
if (!expectedArray.includes(current.status)) {
|
|
156
|
+
throw new RepoStatusConflictError(repo, expected, current.status);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Update metadata
|
|
160
|
+
const now = new Date().toISOString();
|
|
161
|
+
const metadata = {
|
|
162
|
+
name: current.name,
|
|
163
|
+
status,
|
|
164
|
+
createdAt: current.createdAt,
|
|
165
|
+
statusChangedAt: now,
|
|
166
|
+
};
|
|
167
|
+
// Atomic write using rename
|
|
168
|
+
const metadataPath = this.getMetadataPath(repo);
|
|
169
|
+
const tempPath = `${metadataPath}.tmp`;
|
|
170
|
+
await fs.writeFile(tempPath, JSON.stringify(metadata, null, 2));
|
|
171
|
+
await fs.rename(tempPath, metadataPath);
|
|
172
|
+
}
|
|
173
|
+
async remove(repo) {
|
|
174
|
+
const repoPath = this.getRepoPath(repo);
|
|
175
|
+
try {
|
|
176
|
+
// Remove the entire repository directory
|
|
177
|
+
await fs.rm(repoPath, { recursive: true, force: true });
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
// Ignore errors if directory doesn't exist
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// ===========================================================================
|
|
184
|
+
// Batched Deletion
|
|
185
|
+
// ===========================================================================
|
|
186
|
+
async deleteRefsBatch(repo, _cursor) {
|
|
187
|
+
const repoPath = this.getRepoPath(repo);
|
|
188
|
+
let deleted = 0;
|
|
189
|
+
// For local storage, we delete all refs in one pass
|
|
190
|
+
// (packages/, workspaces/, executions/, locks/)
|
|
191
|
+
const refDirs = ['packages', 'workspaces', 'executions', 'locks'];
|
|
192
|
+
for (const dir of refDirs) {
|
|
193
|
+
const dirPath = path.join(repoPath, dir);
|
|
194
|
+
try {
|
|
195
|
+
deleted += await this.deleteDirectoryContents(dirPath);
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// Directory doesn't exist
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return { status: 'done', deleted };
|
|
202
|
+
}
|
|
203
|
+
async deleteObjectsBatch(repo, _cursor) {
|
|
204
|
+
const repoPath = this.getRepoPath(repo);
|
|
205
|
+
const objectsDir = path.join(repoPath, 'objects');
|
|
206
|
+
let deleted = 0;
|
|
207
|
+
try {
|
|
208
|
+
deleted = await this.deleteDirectoryContents(objectsDir);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// objects dir doesn't exist
|
|
212
|
+
}
|
|
213
|
+
return { status: 'done', deleted };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Recursively delete all contents of a directory.
|
|
217
|
+
* Returns count of files deleted.
|
|
218
|
+
*/
|
|
219
|
+
async deleteDirectoryContents(dir) {
|
|
220
|
+
let count = 0;
|
|
221
|
+
try {
|
|
222
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
223
|
+
for (const entry of entries) {
|
|
224
|
+
const entryPath = path.join(dir, entry.name);
|
|
225
|
+
if (entry.isDirectory()) {
|
|
226
|
+
count += await this.deleteDirectoryContents(entryPath);
|
|
227
|
+
await fs.rmdir(entryPath);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
await fs.unlink(entryPath);
|
|
231
|
+
count++;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Directory doesn't exist or can't be read
|
|
237
|
+
}
|
|
238
|
+
return count;
|
|
239
|
+
}
|
|
240
|
+
// ===========================================================================
|
|
241
|
+
// GC Primitives
|
|
242
|
+
// ===========================================================================
|
|
243
|
+
// Note: GC primitives receive `repo` as a full path (same as ObjectStore/RefStore),
|
|
244
|
+
// NOT as a repo name relative to reposDir. This is consistent with how all
|
|
245
|
+
// storage interfaces work in the local implementation.
|
|
246
|
+
async gcScanPackageRoots(repo, _cursor) {
|
|
247
|
+
const roots = [];
|
|
248
|
+
const packages = await this.refs.packageList(repo);
|
|
249
|
+
for (const { name, version } of packages) {
|
|
250
|
+
const hash = await this.refs.packageResolve(repo, name, version);
|
|
251
|
+
if (hash) {
|
|
252
|
+
roots.push(hash);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return { roots };
|
|
256
|
+
}
|
|
257
|
+
async gcScanWorkspaceRoots(repo, _cursor) {
|
|
258
|
+
const roots = [];
|
|
259
|
+
const decoder = decodeBeast2For(WorkspaceStateType);
|
|
260
|
+
const names = await this.refs.workspaceList(repo);
|
|
261
|
+
for (const name of names) {
|
|
262
|
+
const data = await this.refs.workspaceRead(repo, name);
|
|
263
|
+
if (!data || data.length === 0)
|
|
264
|
+
continue;
|
|
265
|
+
try {
|
|
266
|
+
const state = decoder(data);
|
|
267
|
+
roots.push(state.packageHash);
|
|
268
|
+
// Scan per-dataset ref files for value hashes
|
|
269
|
+
if (this.datasets) {
|
|
270
|
+
const refPaths = await this.datasets.list(repo, name);
|
|
271
|
+
for (const refPath of refPaths) {
|
|
272
|
+
const ref = await this.datasets.read(repo, name, refPath);
|
|
273
|
+
if (ref && ref.type === 'value') {
|
|
274
|
+
roots.push(ref.value.hash);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Corrupt workspace state - skip
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return { roots };
|
|
284
|
+
}
|
|
285
|
+
async gcScanExecutionRoots(repo, _cursor) {
|
|
286
|
+
const roots = [];
|
|
287
|
+
const entries = await this.refs.executionList(repo);
|
|
288
|
+
for (const { taskHash, inputsHash } of entries) {
|
|
289
|
+
const ids = await this.refs.executionListIds(repo, taskHash, inputsHash);
|
|
290
|
+
for (const executionId of ids) {
|
|
291
|
+
const status = await this.refs.executionGet(repo, taskHash, inputsHash, executionId);
|
|
292
|
+
if (!status)
|
|
293
|
+
continue;
|
|
294
|
+
// ExecutionStatus is a variant; extract outputHash from success
|
|
295
|
+
const raw = status;
|
|
296
|
+
if (raw.type === 'success' && raw.value.outputHash && /^[a-f0-9]{64}$/.test(raw.value.outputHash)) {
|
|
297
|
+
roots.push(raw.value.outputHash);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return { roots };
|
|
302
|
+
}
|
|
303
|
+
async gcScanObjects(repo, _cursor) {
|
|
304
|
+
const objectsDir = path.join(repo, 'objects');
|
|
305
|
+
const objects = [];
|
|
306
|
+
try {
|
|
307
|
+
const subdirs = await fs.readdir(objectsDir);
|
|
308
|
+
for (const subdir of subdirs) {
|
|
309
|
+
if (!/^[a-f0-9]{2}$/.test(subdir))
|
|
310
|
+
continue;
|
|
311
|
+
const subdirPath = path.join(objectsDir, subdir);
|
|
312
|
+
try {
|
|
313
|
+
const stat = await fs.stat(subdirPath);
|
|
314
|
+
if (!stat.isDirectory())
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const files = await fs.readdir(subdirPath);
|
|
321
|
+
for (const file of files) {
|
|
322
|
+
if (file.endsWith('.partial'))
|
|
323
|
+
continue;
|
|
324
|
+
if (!file.endsWith('.beast2'))
|
|
325
|
+
continue;
|
|
326
|
+
const hash = subdir + file.slice(0, -7); // remove .beast2
|
|
327
|
+
try {
|
|
328
|
+
const fileStat = await fs.stat(path.join(subdirPath, file));
|
|
329
|
+
objects.push({ hash, lastModified: fileStat.mtimeMs, size: fileStat.size });
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// Skip files we can't stat
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
// Objects directory doesn't exist
|
|
339
|
+
}
|
|
340
|
+
// Local returns all in one batch (no cursor)
|
|
341
|
+
return { objects };
|
|
342
|
+
}
|
|
343
|
+
async gcDeleteObjects(repo, hashes) {
|
|
344
|
+
const objectsDir = path.join(repo, 'objects');
|
|
345
|
+
for (const hash of hashes) {
|
|
346
|
+
const subdir = hash.slice(0, 2);
|
|
347
|
+
const rest = hash.slice(2);
|
|
348
|
+
const filePath = path.join(objectsDir, subdir, `${rest}.beast2`);
|
|
349
|
+
try {
|
|
350
|
+
await fs.unlink(filePath);
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
// File doesn't exist
|
|
354
|
+
}
|
|
355
|
+
// Try to remove empty subdirectory
|
|
356
|
+
try {
|
|
357
|
+
await fs.rmdir(path.join(objectsDir, subdir));
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
// Directory not empty or doesn't exist
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=LocalRepoStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalRepoStore.js","sourceRoot":"","sources":["../../../../src/storage/local/LocalRepoStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import type { RepoStore, GcObjectEntry, StorageBackend } from '../interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* Options for garbage collection
|
|
8
|
+
*/
|
|
9
|
+
export interface GcOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Minimum age in milliseconds for files to be considered for deletion.
|
|
12
|
+
* Files younger than this are skipped to avoid race conditions with concurrent writes.
|
|
13
|
+
* Default: 60000 (1 minute)
|
|
14
|
+
*/
|
|
15
|
+
minAge?: number;
|
|
16
|
+
/**
|
|
17
|
+
* If true, only report what would be deleted without actually deleting.
|
|
18
|
+
* Default: false
|
|
19
|
+
*/
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result of garbage collection
|
|
24
|
+
*/
|
|
25
|
+
export interface GcResult {
|
|
26
|
+
/** Number of objects deleted */
|
|
27
|
+
deletedObjects: number;
|
|
28
|
+
/** Number of orphaned staging files deleted */
|
|
29
|
+
deletedPartials: number;
|
|
30
|
+
/** Number of objects retained */
|
|
31
|
+
retainedObjects: number;
|
|
32
|
+
/** Number of files skipped due to being too young */
|
|
33
|
+
skippedYoung: number;
|
|
34
|
+
/** Total bytes freed */
|
|
35
|
+
bytesFreed: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result from sweepBatch — pure decision, no side effects.
|
|
39
|
+
*/
|
|
40
|
+
export interface SweepBatchResult {
|
|
41
|
+
/** Hashes of objects to delete */
|
|
42
|
+
toDelete: string[];
|
|
43
|
+
/** Number of objects retained (reachable) */
|
|
44
|
+
retained: number;
|
|
45
|
+
/** Number of objects skipped due to being too young */
|
|
46
|
+
skippedYoung: number;
|
|
47
|
+
/** Total bytes that would be freed */
|
|
48
|
+
bytesFreed: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Collect all root hashes from packages, workspaces, and executions.
|
|
52
|
+
*
|
|
53
|
+
* Calls each gcScan*Roots method with pagination support.
|
|
54
|
+
* Adding a new root scan method to RepoStore requires updating this function.
|
|
55
|
+
*/
|
|
56
|
+
export declare function collectAllRoots(store: RepoStore, repo: string): Promise<Set<string>>;
|
|
57
|
+
/**
|
|
58
|
+
* Trace the object graph from roots using iterative DFS with schema-aware traversal.
|
|
59
|
+
*
|
|
60
|
+
* Decodes each object using BEAST2 self-describing format and extracts child
|
|
61
|
+
* hashes based on the detected object type (Package, Task, or Tree). Objects
|
|
62
|
+
* known to be leaves (values, IR blobs) are marked reachable without reading.
|
|
63
|
+
*
|
|
64
|
+
* @param readObject - Function to read an object by hash (returns null if missing)
|
|
65
|
+
* @param roots - Set of root hashes to start from
|
|
66
|
+
* @returns Set of all reachable hashes
|
|
67
|
+
*/
|
|
68
|
+
export declare function markReachable(readObject: (hash: string) => Promise<Uint8Array | null>, roots: Set<string>): Promise<Set<string>>;
|
|
69
|
+
/**
|
|
70
|
+
* Pure decision function: determine which objects to delete.
|
|
71
|
+
*
|
|
72
|
+
* No side effects — trivially testable. Caller decides whether to
|
|
73
|
+
* actually delete (supports dry-run by skipping gcDeleteObjects).
|
|
74
|
+
*
|
|
75
|
+
* @param objects - Object entries from gcScanObjects
|
|
76
|
+
* @param reachable - Set of reachable hashes from markReachable
|
|
77
|
+
* @param minAge - Minimum age in ms; objects younger than this are skipped
|
|
78
|
+
* @returns Decision result with toDelete list and stats
|
|
79
|
+
*/
|
|
80
|
+
export declare function sweepBatch(objects: GcObjectEntry[], reachable: Set<string>, minAge: number): SweepBatchResult;
|
|
81
|
+
/**
|
|
82
|
+
* Run garbage collection on an e3 repository.
|
|
83
|
+
*
|
|
84
|
+
* Works with any StorageBackend — no instanceof checks.
|
|
85
|
+
*
|
|
86
|
+
* @param storage - Storage backend
|
|
87
|
+
* @param repo - Repository identifier
|
|
88
|
+
* @param options - GC options
|
|
89
|
+
* @returns GC result with statistics
|
|
90
|
+
*/
|
|
91
|
+
export declare function repoGc(storage: StorageBackend, repo: string, options?: GcOptions): Promise<GcResult>;
|
|
92
|
+
//# sourceMappingURL=gc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../../../src/storage/local/gc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAoB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEnG;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAmB1F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,EACxD,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GACjB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAgCtB;AAqGD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,aAAa,EAAE,EACxB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,MAAM,EAAE,MAAM,GACb,gBAAgB,CAsBlB;AAMD;;;;;;;;;GASG;AACH,wBAAsB,MAAM,CAC1B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,SAAc,GACtB,OAAO,CAAC,QAAQ,CAAC,CAmEnB"}
|