@elaraai/e3-api-server 1.0.76 → 1.0.77
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 +21 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +13 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/handlers/datasets.d.ts.map +1 -1
- package/dist/src/handlers/datasets.js +3 -1
- package/dist/src/handlers/datasets.js.map +1 -1
- package/dist/src/handlers/datasets.spec.js +1 -1
- package/dist/src/handlers/datasets.spec.js.map +1 -1
- package/dist/src/handlers/functions.spec.js +1 -0
- package/dist/src/handlers/functions.spec.js.map +1 -1
- package/dist/src/handlers/records.spec.js +1 -0
- package/dist/src/handlers/records.spec.js.map +1 -1
- package/dist/src/handlers/workspaces.d.ts.map +1 -1
- package/dist/src/handlers/workspaces.js +11 -1
- package/dist/src/handlers/workspaces.js.map +1 -1
- package/dist/src/routes/data.d.ts +2 -1
- package/dist/src/routes/data.d.ts.map +1 -1
- package/dist/src/routes/data.js +86 -7
- package/dist/src/routes/data.js.map +1 -1
- package/dist/src/routes/index.d.ts +1 -1
- package/dist/src/routes/index.d.ts.map +1 -1
- package/dist/src/routes/index.js.map +1 -1
- package/dist/src/routes/transfer.d.ts +20 -3
- package/dist/src/routes/transfer.d.ts.map +1 -1
- package/dist/src/routes/transfer.js +191 -54
- package/dist/src/routes/transfer.js.map +1 -1
- package/dist/src/server.d.ts +9 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +5 -2
- package/dist/src/server.js.map +1 -1
- package/dist/src/types.d.ts +23 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +3 -2
- package/dist/src/types.js.map +1 -1
- package/package.json +4 -4
|
@@ -194,7 +194,17 @@ export async function deployWorkspace(storage, repoPath, workspace, packageRef)
|
|
|
194
194
|
if (!pkgVersion) {
|
|
195
195
|
return sendError(NullType, errorToVariant(new Error(`Package not found: ${pkgName}`)));
|
|
196
196
|
}
|
|
197
|
-
|
|
197
|
+
// A path-initialised input names a path on the machine that EXPORTED the
|
|
198
|
+
// package, never this server's. The server must not open it — even a path
|
|
199
|
+
// it can read — or a package could adopt any server-readable file of the
|
|
200
|
+
// declared type into the caller's repository. Every `file` source is left
|
|
201
|
+
// unassigned with a warning: `e3 workspace deploy <url> --from-source`
|
|
202
|
+
// completes those inputs over the dataset transfer protocol immediately
|
|
203
|
+
// afterwards, and the server's commit runs the same validation.
|
|
204
|
+
await workspaceDeploy(storage, repoPath, workspace, pkgName, pkgVersion, {
|
|
205
|
+
resolveFileSources: false,
|
|
206
|
+
sourceWarning: (message) => console.warn(`[deploy ${workspace}] ${message}`),
|
|
207
|
+
});
|
|
198
208
|
return sendSuccess(NullType, null);
|
|
199
209
|
}
|
|
200
210
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../src/handlers/workspaces.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../../../src/handlers/workspaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,8 @@ import { type StorageBackend, type TransferBackend } from '@elaraai/e3-core';
|
|
|
8
8
|
* Create generic upload/download data endpoints.
|
|
9
9
|
*
|
|
10
10
|
* Returns two Hono apps:
|
|
11
|
-
* - `uploads`: PUT /:id — upload data (dataset BEAST2 or package zip)
|
|
11
|
+
* - `uploads`: PUT /:id — upload data (dataset BEAST2 or package zip);
|
|
12
|
+
* PUT /:id/parts/:part — one part of a dataset upload planned as parts
|
|
12
13
|
* - `downloads`: GET /:id — download data (dataset BEAST2 or package zip)
|
|
13
14
|
*
|
|
14
15
|
* These are unauthenticated — the UUID in the URL is the sole capability.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../src/routes/data.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../src/routes/data.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAmB1B;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;;;EAoLtC"}
|
package/dist/src/routes/data.js
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
|
-
import { mkdir, writeFile, readFile, unlink } from 'node:fs/promises';
|
|
6
|
+
import { mkdir, open, writeFile, readFile, unlink } from 'node:fs/promises';
|
|
7
|
+
import { createWriteStream } from 'node:fs';
|
|
8
|
+
import { Readable, Transform } from 'node:stream';
|
|
9
|
+
import { pipeline } from 'node:stream/promises';
|
|
7
10
|
import { join } from 'node:path';
|
|
8
11
|
import { tmpdir } from 'node:os';
|
|
9
12
|
import { variant } from '@elaraai/east';
|
|
10
|
-
import {
|
|
13
|
+
import { transferPartCount, transferPartRange } from '@elaraai/e3-types';
|
|
14
|
+
import { BEAST2_CONTENT_TYPE, ObjectNotFoundError, transferStagingDir, transferStagingPath, } from '@elaraai/e3-core';
|
|
11
15
|
const STAGING_DIR = join(tmpdir(), 'e3-transfers');
|
|
12
16
|
/**
|
|
13
17
|
* Reject requests that carry an Authorization header.
|
|
@@ -27,7 +31,8 @@ function rejectAuthHeader(c) {
|
|
|
27
31
|
* Create generic upload/download data endpoints.
|
|
28
32
|
*
|
|
29
33
|
* Returns two Hono apps:
|
|
30
|
-
* - `uploads`: PUT /:id — upload data (dataset BEAST2 or package zip)
|
|
34
|
+
* - `uploads`: PUT /:id — upload data (dataset BEAST2 or package zip);
|
|
35
|
+
* PUT /:id/parts/:part — one part of a dataset upload planned as parts
|
|
31
36
|
* - `downloads`: GET /:id — download data (dataset BEAST2 or package zip)
|
|
32
37
|
*
|
|
33
38
|
* These are unauthenticated — the UUID in the URL is the sole capability.
|
|
@@ -45,10 +50,28 @@ export function createDataEndpoints(transferBackend, storage, getRepoPath) {
|
|
|
45
50
|
// Try dataset upload first
|
|
46
51
|
const dsRecord = await transferBackend.datasetUpload.get(id);
|
|
47
52
|
if (dsRecord) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
// Streamed to the repo's own staging area: a delivery can be far larger
|
|
54
|
+
// than this process's heap, and the commit turns the staged file into an
|
|
55
|
+
// object by link or rename — which only works on the repo's device.
|
|
56
|
+
const repoPath = getRepoPath(dsRecord.repo);
|
|
57
|
+
const stagingPath = transferStagingPath(repoPath, id);
|
|
58
|
+
await mkdir(transferStagingDir(repoPath), { recursive: true });
|
|
59
|
+
const stream = c.req.raw.body;
|
|
60
|
+
try {
|
|
61
|
+
if (stream) {
|
|
62
|
+
await pipeline(Readable.fromWeb(stream), createWriteStream(stagingPath));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
await writeFile(stagingPath, new Uint8Array(await c.req.arrayBuffer()));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
// A broken upload leaves no partial file behind; gc sweeps the staging
|
|
70
|
+
// directory only as the backstop for a server that crashed mid-upload.
|
|
71
|
+
// The transfer record stays, so the client may retry the PUT.
|
|
72
|
+
await unlink(stagingPath).catch(() => { });
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
52
75
|
return new Response(null, { status: 200 });
|
|
53
76
|
}
|
|
54
77
|
// Try package import — stage file for later processing by trigger endpoint
|
|
@@ -67,6 +90,62 @@ export function createDataEndpoints(transferBackend, storage, getRepoPath) {
|
|
|
67
90
|
}
|
|
68
91
|
return new Response('Not found', { status: 404 });
|
|
69
92
|
});
|
|
93
|
+
// PUT /api/uploads/:id/parts/:part — One part of a dataset upload planned as
|
|
94
|
+
// parts (protocol 2)
|
|
95
|
+
uploads.put('/:id/parts/:part', async (c) => {
|
|
96
|
+
const rejected = rejectAuthHeader(c);
|
|
97
|
+
if (rejected)
|
|
98
|
+
return rejected;
|
|
99
|
+
const id = c.req.param('id');
|
|
100
|
+
const record = await transferBackend.datasetUpload.get(id);
|
|
101
|
+
const partBytes = record ? await transferBackend.datasetUpload.getPartBytes(id) : null;
|
|
102
|
+
if (!record || partBytes === null) {
|
|
103
|
+
return new Response('Not found', { status: 404 });
|
|
104
|
+
}
|
|
105
|
+
const part = Number(c.req.param('part'));
|
|
106
|
+
const range = transferPartRange(record.size, partBytes, part);
|
|
107
|
+
if (!range) {
|
|
108
|
+
return new Response(`No part ${c.req.param('part')}: the upload has ${transferPartCount(record.size, partBytes)} parts`, { status: 404 });
|
|
109
|
+
}
|
|
110
|
+
// Every part streams to its own offset in the one staged file — in any
|
|
111
|
+
// order, concurrently, and a re-sent part over the old one — so the commit
|
|
112
|
+
// adopts the file exactly as it does a single PUT's, with nothing to
|
|
113
|
+
// assemble. Opening with 'a' creates the file without truncating the parts
|
|
114
|
+
// already there; the write itself needs a positioned handle.
|
|
115
|
+
const repoPath = getRepoPath(record.repo);
|
|
116
|
+
const stagingPath = transferStagingPath(repoPath, id);
|
|
117
|
+
await mkdir(transferStagingDir(repoPath), { recursive: true });
|
|
118
|
+
await (await open(stagingPath, 'a')).close();
|
|
119
|
+
// A part longer than its range would overwrite the next part, so the
|
|
120
|
+
// stream stops at the range's end instead of trusting Content-Length.
|
|
121
|
+
const expected = range.end - range.start;
|
|
122
|
+
let received = 0;
|
|
123
|
+
const bounded = new Transform({
|
|
124
|
+
transform(chunk, _encoding, callback) {
|
|
125
|
+
received += chunk.length;
|
|
126
|
+
if (received > expected) {
|
|
127
|
+
callback(new Error(`part ${part} is ${expected} bytes, and more were sent`));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
callback(null, chunk);
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const body = c.req.raw.body;
|
|
135
|
+
try {
|
|
136
|
+
await pipeline(body ? Readable.fromWeb(body) : Readable.from([]), bounded, createWriteStream(stagingPath, { flags: 'r+', start: range.start }));
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
if (received > expected) {
|
|
140
|
+
return new Response(`part ${part} is ${expected} bytes, and more were sent`, { status: 400 });
|
|
141
|
+
}
|
|
142
|
+
throw err;
|
|
143
|
+
}
|
|
144
|
+
if (received !== expected) {
|
|
145
|
+
return new Response(`part ${part} is ${expected} bytes, got ${received}`, { status: 400 });
|
|
146
|
+
}
|
|
147
|
+
return new Response(null, { status: 200 });
|
|
148
|
+
});
|
|
70
149
|
// GET /api/downloads/:id — Download data (dataset BEAST2 or package zip)
|
|
71
150
|
downloads.get('/:id', async (c) => {
|
|
72
151
|
const rejected = rejectAuthHeader(c);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../src/routes/data.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../src/routes/data.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ export { createDatasetRoutes } from './datasets.js';
|
|
|
9
9
|
export { createTaskRoutes } from './tasks.js';
|
|
10
10
|
export { createExecutionRoutes } from './executions.js';
|
|
11
11
|
export { createObjectRoutes } from './objects.js';
|
|
12
|
-
export { createTransferRoutes } from './transfer.js';
|
|
12
|
+
export { createTransferRoutes, type TransferRouteOptions } from './transfer.js';
|
|
13
13
|
export { createPackageTransferRoutes } from './package-transfer.js';
|
|
14
14
|
export { createDataEndpoints } from './data.js';
|
|
15
15
|
export { createPackageFunctionRoutes, createWorkspaceFunctionRoutes, createOneShotRoutes, type GetRunner } from './functions.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACjI,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/routes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAA6B,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,mBAAmB,EAAkB,MAAM,gBAAgB,CAAC;AACjI,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -4,16 +4,33 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
6
|
import { type StorageBackend, type TransferBackend } from '@elaraai/e3-core';
|
|
7
|
+
/** Options for {@link createTransferRoutes}. */
|
|
8
|
+
export interface TransferRouteOptions {
|
|
9
|
+
/**
|
|
10
|
+
* How long a protocol-2 commit waits for the staged bytes to be verified
|
|
11
|
+
* before it answers `processing` for the client to poll (default 5000 ms; 0
|
|
12
|
+
* answers `processing` at once). A protocol-1 commit always waits.
|
|
13
|
+
*/
|
|
14
|
+
commitWaitMs?: number;
|
|
15
|
+
}
|
|
7
16
|
/**
|
|
8
17
|
* Create dataset transfer routes.
|
|
9
18
|
*
|
|
10
|
-
* Returns an `api` Hono app with authenticated routes (init upload,
|
|
11
|
-
* mounted at /api/repos/:repo/workspaces/:ws/datasets.
|
|
19
|
+
* Returns an `api` Hono app with authenticated routes (init upload, part
|
|
20
|
+
* targets, commit, commit poll) mounted at /api/repos/:repo/workspaces/:ws/datasets.
|
|
12
21
|
*
|
|
13
22
|
* Unauthenticated data routes (upload/download bytes) are handled by the
|
|
14
23
|
* generic data endpoints in `data.ts`.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* A protocol-2 client (`?protocol=2` on the init and the commit) is sent its
|
|
27
|
+
* bytes' plan as parts, and its commit runs in the background: the request
|
|
28
|
+
* waits up to `commitWaitMs` for it and otherwise answers `processing`, which
|
|
29
|
+
* the client polls — so verifying a delivery of many gigabytes never holds one
|
|
30
|
+
* request open for as long as its SHA-256 takes. A protocol-1 client gets the
|
|
31
|
+
* single upload URL and a commit that answers only when it is done.
|
|
15
32
|
*/
|
|
16
|
-
export declare function createTransferRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, transferBackend: TransferBackend): {
|
|
33
|
+
export declare function createTransferRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, transferBackend: TransferBackend, options?: TransferRouteOptions): {
|
|
17
34
|
api: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
18
35
|
};
|
|
19
36
|
//# sourceMappingURL=transfer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../../src/routes/transfer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../../src/routes/transfer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAW1B,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqDD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACrC,eAAe,EAAE,eAAe,EAChC,OAAO,GAAE,oBAAyB;;EA0OnC"}
|
|
@@ -3,27 +3,66 @@
|
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
|
-
import { mkdir,
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
import { tmpdir } from 'node:os';
|
|
6
|
+
import { mkdir, stat, unlink } from 'node:fs/promises';
|
|
9
7
|
import { randomUUID } from 'node:crypto';
|
|
10
|
-
import { variant
|
|
11
|
-
import { urlPathToTreePath } from '@elaraai/e3-types';
|
|
12
|
-
import {
|
|
8
|
+
import { variant } from '@elaraai/east';
|
|
9
|
+
import { transferPartCount, urlPathToTreePath } from '@elaraai/e3-types';
|
|
10
|
+
import { DatasetTypeMismatchError, datasetAdoptFile, datasetAdoptObject, transferStagingDir, transferStagingPath, } from '@elaraai/e3-core';
|
|
13
11
|
import { decodeBody, sendSuccess, sendError } from '../beast2.js';
|
|
14
|
-
import { TransferUploadRequestType, TransferUploadResponseType, TransferDoneResponseType } from '../types.js';
|
|
15
|
-
const
|
|
12
|
+
import { TransferUploadRequestType, TransferUploadResponseType, TransferPartResponseType, TransferDoneResponseType, } from '../types.js';
|
|
13
|
+
const DEFAULT_COMMIT_WAIT_MS = 5_000;
|
|
14
|
+
/** How long a finished commit's answer stays pollable. */
|
|
15
|
+
const COMMIT_RESULT_TTL_MS = 10 * 60 * 1000;
|
|
16
|
+
/** The transfer protocol version a request speaks: `?protocol=N`, else 1. */
|
|
17
|
+
function requestProtocol(c) {
|
|
18
|
+
const version = Number(c.req.query('protocol'));
|
|
19
|
+
return Number.isInteger(version) && version >= 1 ? version : 1;
|
|
20
|
+
}
|
|
21
|
+
/** A backend's URL as the client can use it: a relative one resolves against the request's origin. */
|
|
22
|
+
function resolveUrl(c, url) {
|
|
23
|
+
return url.startsWith('/') ? `${new URL(c.req.url).origin}${url}` : url;
|
|
24
|
+
}
|
|
25
|
+
/** The promise's value if it settles within `ms`, else `null` — at once when `ms` is 0. */
|
|
26
|
+
async function within(promise, ms) {
|
|
27
|
+
if (ms <= 0)
|
|
28
|
+
return null;
|
|
29
|
+
let timer;
|
|
30
|
+
const timeout = new Promise((resolve) => {
|
|
31
|
+
timer = setTimeout(() => resolve(null), ms);
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
return await Promise.race([promise, timeout]);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function sendOutcome(outcome) {
|
|
41
|
+
return outcome.type === 'answer'
|
|
42
|
+
? sendSuccess(TransferDoneResponseType, outcome.value)
|
|
43
|
+
: sendError(TransferDoneResponseType, outcome.error);
|
|
44
|
+
}
|
|
16
45
|
/**
|
|
17
46
|
* Create dataset transfer routes.
|
|
18
47
|
*
|
|
19
|
-
* Returns an `api` Hono app with authenticated routes (init upload,
|
|
20
|
-
* mounted at /api/repos/:repo/workspaces/:ws/datasets.
|
|
48
|
+
* Returns an `api` Hono app with authenticated routes (init upload, part
|
|
49
|
+
* targets, commit, commit poll) mounted at /api/repos/:repo/workspaces/:ws/datasets.
|
|
21
50
|
*
|
|
22
51
|
* Unauthenticated data routes (upload/download bytes) are handled by the
|
|
23
52
|
* generic data endpoints in `data.ts`.
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* A protocol-2 client (`?protocol=2` on the init and the commit) is sent its
|
|
56
|
+
* bytes' plan as parts, and its commit runs in the background: the request
|
|
57
|
+
* waits up to `commitWaitMs` for it and otherwise answers `processing`, which
|
|
58
|
+
* the client polls — so verifying a delivery of many gigabytes never holds one
|
|
59
|
+
* request open for as long as its SHA-256 takes. A protocol-1 client gets the
|
|
60
|
+
* single upload URL and a commit that answers only when it is done.
|
|
24
61
|
*/
|
|
25
|
-
export function createTransferRoutes(storage, getRepoPath, transferBackend) {
|
|
62
|
+
export function createTransferRoutes(storage, getRepoPath, transferBackend, options = {}) {
|
|
26
63
|
const api = new Hono();
|
|
64
|
+
const commitWaitMs = options.commitWaitMs ?? DEFAULT_COMMIT_WAIT_MS;
|
|
65
|
+
const commits = new Map();
|
|
27
66
|
/**
|
|
28
67
|
* Extract dataset path from the request URL wildcard.
|
|
29
68
|
* The route is mounted at /api/repos/:repo/workspaces/:ws/datasets
|
|
@@ -45,6 +84,17 @@ export function createTransferRoutes(storage, getRepoPath, transferBackend) {
|
|
|
45
84
|
}
|
|
46
85
|
return pathStr;
|
|
47
86
|
}
|
|
87
|
+
/** Whether an upload was created for the repository, workspace and dataset this request addresses. */
|
|
88
|
+
function addresses(c, transfer, suffix) {
|
|
89
|
+
return transfer.repo === c.req.param('repo')
|
|
90
|
+
&& transfer.workspace === c.req.param('ws')
|
|
91
|
+
&& transfer.path === extractDatasetPath(c, suffix);
|
|
92
|
+
}
|
|
93
|
+
/** The upload `id`, if this request addresses it. */
|
|
94
|
+
async function uploadAt(c, id, suffix) {
|
|
95
|
+
const transfer = await transferBackend.datasetUpload.get(id);
|
|
96
|
+
return transfer && addresses(c, transfer, suffix) ? transfer : null;
|
|
97
|
+
}
|
|
48
98
|
// =========================================================================
|
|
49
99
|
// Authenticated API routes (mounted at /api/repos/:repo/workspaces/:ws/datasets)
|
|
50
100
|
// =========================================================================
|
|
@@ -56,7 +106,7 @@ export function createTransferRoutes(storage, getRepoPath, transferBackend) {
|
|
|
56
106
|
// Check for commit: .../upload/<uuid>
|
|
57
107
|
const commitMatch = fullPath.match(/\/upload\/([0-9a-f-]{36})$/);
|
|
58
108
|
if (commitMatch) {
|
|
59
|
-
return handleCommit(c, commitMatch[1]);
|
|
109
|
+
return handleCommit(c, commitMatch[1], commitMatch[0]);
|
|
60
110
|
}
|
|
61
111
|
// Check for init: .../upload
|
|
62
112
|
if (fullPath.endsWith('/upload')) {
|
|
@@ -65,70 +115,157 @@ export function createTransferRoutes(storage, getRepoPath, transferBackend) {
|
|
|
65
115
|
// Not a transfer route — return 404
|
|
66
116
|
return new Response('Not found', { status: 404 });
|
|
67
117
|
});
|
|
118
|
+
// GET routes dispatch the same way, and leave every other read to the
|
|
119
|
+
// dataset routes mounted after these:
|
|
120
|
+
// - .../datasets/<path>/upload/<id>/parts/<n> → where to send part n
|
|
121
|
+
// - .../datasets/<path>/upload/<id> → poll a commit
|
|
122
|
+
api.get('/*', async (c, next) => {
|
|
123
|
+
const fullPath = c.req.path;
|
|
124
|
+
const partMatch = fullPath.match(/\/upload\/([0-9a-f-]{36})\/parts\/([0-9]+)$/);
|
|
125
|
+
if (partMatch) {
|
|
126
|
+
return handlePart(c, partMatch[1], Number(partMatch[2]), partMatch[0]);
|
|
127
|
+
}
|
|
128
|
+
const pollMatch = fullPath.match(/\/upload\/([0-9a-f-]{36})$/);
|
|
129
|
+
if (pollMatch) {
|
|
130
|
+
return handlePoll(c, pollMatch[1], pollMatch[0]);
|
|
131
|
+
}
|
|
132
|
+
await next();
|
|
133
|
+
});
|
|
68
134
|
async function handleInit(c) {
|
|
69
135
|
const repo = c.req.param('repo');
|
|
70
136
|
const ws = c.req.param('ws');
|
|
71
137
|
const repoPath = getRepoPath(repo);
|
|
72
138
|
const pathStr = extractDatasetPath(c, '/upload');
|
|
73
139
|
const { hash, size } = await decodeBody(c, TransferUploadRequestType);
|
|
74
|
-
// Dedup
|
|
140
|
+
// Dedup — the bytes are already an object, so no upload is needed. The
|
|
141
|
+
// object is not necessarily THIS dataset's type though (it may have been
|
|
142
|
+
// stored for another one), so the pairing is checked here: it is the only
|
|
143
|
+
// door that skips the commit.
|
|
75
144
|
if (await storage.objects.exists(repoPath, hash)) {
|
|
76
145
|
const treePath = urlPathToTreePath(pathStr);
|
|
77
|
-
await
|
|
146
|
+
await datasetAdoptObject(storage, repoPath, ws, treePath, hash);
|
|
78
147
|
return sendSuccess(TransferUploadResponseType, variant('completed', null));
|
|
79
148
|
}
|
|
80
149
|
// Create transfer record in backend
|
|
81
150
|
const transferId = randomUUID();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
151
|
+
const transfer = { repo, workspace: ws, path: pathStr, hash, size };
|
|
152
|
+
await transferBackend.datasetUpload.create(transferId, transfer);
|
|
153
|
+
// Create the staging slot under the repo, so the commit's adopt is a
|
|
154
|
+
// same-device link or rename rather than a whole-file copy.
|
|
155
|
+
await mkdir(transferStagingDir(repoPath), { recursive: true });
|
|
156
|
+
if (requestProtocol(c) >= 2) {
|
|
157
|
+
const partBytes = await transferBackend.datasetUpload.createParts(transferId, transfer);
|
|
158
|
+
return sendSuccess(TransferUploadResponseType, variant('upload_parts', { id: transferId, partBytes }));
|
|
159
|
+
}
|
|
85
160
|
const uploadUrl = await transferBackend.datasetUpload.getUploadUrl(transferId, repo, hash);
|
|
86
|
-
|
|
87
|
-
const origin = new URL(c.req.url).origin;
|
|
88
|
-
const resolvedUrl = uploadUrl.startsWith('/') ? `${origin}${uploadUrl}` : uploadUrl;
|
|
89
|
-
return sendSuccess(TransferUploadResponseType, variant('upload', { id: transferId, uploadUrl: resolvedUrl }));
|
|
161
|
+
return sendSuccess(TransferUploadResponseType, variant('upload', { id: transferId, uploadUrl: resolveUrl(c, uploadUrl) }));
|
|
90
162
|
}
|
|
91
|
-
async function
|
|
92
|
-
const transfer = await
|
|
163
|
+
async function handlePart(c, id, part, suffix) {
|
|
164
|
+
const transfer = await uploadAt(c, id, suffix);
|
|
93
165
|
if (!transfer) {
|
|
94
|
-
return sendError(
|
|
166
|
+
return sendError(TransferPartResponseType, variant('internal', { message: 'transfer not found' }));
|
|
95
167
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
168
|
+
const partBytes = await transferBackend.datasetUpload.getPartBytes(id);
|
|
169
|
+
if (partBytes === null) {
|
|
170
|
+
return sendError(TransferPartResponseType, variant('internal', { message: 'transfer was not planned as parts' }));
|
|
171
|
+
}
|
|
172
|
+
const count = transferPartCount(transfer.size, partBytes);
|
|
173
|
+
if (part < 1 || part > count) {
|
|
174
|
+
return sendError(TransferPartResponseType, variant('internal', {
|
|
175
|
+
message: `no part ${part}: the upload has ${count} part${count === 1 ? '' : 's'}`,
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
const target = await transferBackend.datasetUpload.getPartUpload(id, transfer, part);
|
|
179
|
+
return sendSuccess(TransferPartResponseType, {
|
|
180
|
+
url: resolveUrl(c, target.url),
|
|
181
|
+
headers: new Map(Object.entries(target.headers)),
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
async function handleCommit(c, id, suffix) {
|
|
185
|
+
let commit = commits.get(id);
|
|
186
|
+
if (!commit) {
|
|
187
|
+
const transfer = await uploadAt(c, id, suffix);
|
|
188
|
+
if (!transfer) {
|
|
189
|
+
return sendError(TransferDoneResponseType, variant('internal', { message: 'transfer not found' }));
|
|
104
190
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
191
|
+
// A retried commit may have started it while this one looked it up.
|
|
192
|
+
commit = commits.get(id) ?? startCommit(id, transfer);
|
|
193
|
+
}
|
|
194
|
+
if (!addresses(c, commit.transfer, suffix)) {
|
|
195
|
+
return sendError(TransferDoneResponseType, variant('internal', { message: 'transfer not found' }));
|
|
196
|
+
}
|
|
197
|
+
const outcome = requestProtocol(c) >= 2
|
|
198
|
+
? commit.outcome ?? await within(commit.settled, commitWaitMs)
|
|
199
|
+
: await commit.settled;
|
|
200
|
+
return outcome ? sendOutcome(outcome) : sendSuccess(TransferDoneResponseType, variant('processing', null));
|
|
201
|
+
}
|
|
202
|
+
async function handlePoll(c, id, suffix) {
|
|
203
|
+
const commit = commits.get(id);
|
|
204
|
+
if (commit && addresses(c, commit.transfer, suffix)) {
|
|
205
|
+
return commit.outcome
|
|
206
|
+
? sendOutcome(commit.outcome)
|
|
207
|
+
: sendSuccess(TransferDoneResponseType, variant('processing', null));
|
|
208
|
+
}
|
|
209
|
+
const transfer = await uploadAt(c, id, suffix);
|
|
210
|
+
return sendError(TransferDoneResponseType, variant('internal', {
|
|
211
|
+
message: transfer ? 'transfer not committed' : 'transfer not found',
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
function startCommit(id, transfer) {
|
|
215
|
+
const settled = verifyAndAdopt(id, transfer).then((outcome) => {
|
|
216
|
+
commit.outcome = outcome;
|
|
217
|
+
// The answer stays pollable for a while — a client whose response was
|
|
218
|
+
// lost asks again — and then goes, as the upload record already has.
|
|
219
|
+
setTimeout(() => commits.delete(id), COMMIT_RESULT_TTL_MS).unref();
|
|
220
|
+
return outcome;
|
|
221
|
+
});
|
|
222
|
+
const commit = { transfer, outcome: null, settled };
|
|
223
|
+
commits.set(id, commit);
|
|
224
|
+
return commit;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Verify a staged upload and point its dataset at it; never rejects.
|
|
228
|
+
*/
|
|
229
|
+
async function verifyAndAdopt(id, transfer) {
|
|
230
|
+
// Nothing may escape: a commit answering `processing` is awaited by no one.
|
|
231
|
+
let stagingPath = null;
|
|
232
|
+
try {
|
|
233
|
+
const repoPath = getRepoPath(transfer.repo);
|
|
234
|
+
stagingPath = transferStagingPath(repoPath, id);
|
|
235
|
+
// The staged file is never read whole: its size comes from `stat`, its
|
|
236
|
+
// digest from a streamed hash, its declared type and paging index from
|
|
237
|
+
// two ranged reads, and it becomes an object by link or rename. A
|
|
238
|
+
// multi-gigabyte delivery therefore commits for the cost of its SHA-256.
|
|
239
|
+
const stats = await stat(stagingPath);
|
|
240
|
+
if (BigInt(stats.size) !== transfer.size) {
|
|
241
|
+
return {
|
|
242
|
+
type: 'answer',
|
|
243
|
+
value: variant('error', { message: `size mismatch: expected ${transfer.size}, got ${stats.size}` }),
|
|
244
|
+
};
|
|
109
245
|
}
|
|
110
|
-
// The transfer path stores the client's bytes verbatim — the one place
|
|
111
|
-
// un-indexed bytes could enter at rest. Collection datasets must be
|
|
112
|
-
// segmented + indexed (the uniform at-rest contract), so validate here.
|
|
113
246
|
const treePath = urlPathToTreePath(transfer.path);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return
|
|
247
|
+
await datasetAdoptFile(storage, repoPath, transfer.workspace, treePath, stagingPath, {
|
|
248
|
+
expectHash: transfer.hash,
|
|
249
|
+
});
|
|
250
|
+
return { type: 'answer', value: variant('completed', null) };
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
if (err instanceof DatasetTypeMismatchError) {
|
|
254
|
+
return {
|
|
255
|
+
type: 'refused',
|
|
256
|
+
error: variant('dataset_type_mismatch', {
|
|
257
|
+
workspace: transfer.workspace,
|
|
258
|
+
path: err.path,
|
|
259
|
+
message: err.message,
|
|
260
|
+
}),
|
|
261
|
+
};
|
|
122
262
|
}
|
|
123
|
-
|
|
124
|
-
await storage.objects.write(repoPath, data);
|
|
125
|
-
await unlink(stagingPath).catch(() => { });
|
|
126
|
-
// Update dataset ref
|
|
127
|
-
await workspaceSetDatasetByHash(storage, repoPath, transfer.workspace, treePath, actualHash, new Map());
|
|
128
|
-
return sendSuccess(TransferDoneResponseType, variant('completed', null));
|
|
263
|
+
return { type: 'answer', value: variant('error', { message: err instanceof Error ? err.message : String(err) }) };
|
|
129
264
|
}
|
|
130
265
|
finally {
|
|
131
|
-
|
|
266
|
+
if (stagingPath !== null)
|
|
267
|
+
await unlink(stagingPath).catch(() => { });
|
|
268
|
+
await transferBackend.datasetUpload.delete(id).catch(() => { });
|
|
132
269
|
}
|
|
133
270
|
}
|
|
134
271
|
return { api };
|