@elaraai/e3-api-server 1.0.82 → 1.0.84
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 +75 -8
- package/dist/src/auth/keys.d.ts +3 -0
- package/dist/src/auth/keys.d.ts.map +1 -1
- package/dist/src/auth/keys.js.map +1 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +6 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/handlers/dataflow.d.ts +6 -3
- package/dist/src/handlers/dataflow.d.ts.map +1 -1
- package/dist/src/handlers/dataflow.js +8 -8
- package/dist/src/handlers/dataflow.js.map +1 -1
- package/dist/src/handlers/dataflow.spec.js +30 -0
- package/dist/src/handlers/dataflow.spec.js.map +1 -1
- package/dist/src/handlers/datasets.spec.js +2 -2
- package/dist/src/handlers/datasets.spec.js.map +1 -1
- package/dist/src/handlers/functions.d.ts +88 -8
- package/dist/src/handlers/functions.d.ts.map +1 -1
- package/dist/src/handlers/functions.js +204 -145
- package/dist/src/handlers/functions.js.map +1 -1
- package/dist/src/handlers/functions.spec.js +156 -32
- package/dist/src/handlers/functions.spec.js.map +1 -1
- package/dist/src/handlers/index.d.ts +1 -1
- package/dist/src/handlers/index.d.ts.map +1 -1
- package/dist/src/handlers/index.js +1 -1
- package/dist/src/handlers/index.js.map +1 -1
- package/dist/src/handlers/records.spec.js +1 -1
- package/dist/src/handlers/records.spec.js.map +1 -1
- package/dist/src/handlers/workspaces.spec.js +1 -1
- package/dist/src/handlers/workspaces.spec.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/middleware/repository.d.ts +40 -1
- package/dist/src/middleware/repository.d.ts.map +1 -1
- package/dist/src/middleware/repository.js +42 -4
- package/dist/src/middleware/repository.js.map +1 -1
- package/dist/src/middleware/repository.spec.d.ts +6 -0
- package/dist/src/middleware/repository.spec.d.ts.map +1 -0
- package/dist/src/middleware/repository.spec.js +118 -0
- package/dist/src/middleware/repository.spec.js.map +1 -0
- package/dist/src/routes/functions.d.ts +94 -13
- package/dist/src/routes/functions.d.ts.map +1 -1
- package/dist/src/routes/functions.js +116 -30
- package/dist/src/routes/functions.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 +1 -1
- package/dist/src/routes/index.js.map +1 -1
- package/dist/src/routes/package-transfer.d.ts +5 -0
- package/dist/src/routes/package-transfer.d.ts.map +1 -1
- package/dist/src/routes/package-transfer.js +19 -6
- package/dist/src/routes/package-transfer.js.map +1 -1
- package/dist/src/routes/transfer.d.ts +9 -6
- package/dist/src/routes/transfer.d.ts.map +1 -1
- package/dist/src/routes/transfer.js +23 -14
- package/dist/src/routes/transfer.js.map +1 -1
- package/dist/src/routes/transfer.spec.d.ts +6 -0
- package/dist/src/routes/transfer.spec.d.ts.map +1 -0
- package/dist/src/routes/transfer.spec.js +91 -0
- package/dist/src/routes/transfer.spec.js.map +1 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +13 -6
- package/dist/src/server.js.map +1 -1
- package/dist/src/types.d.ts +204 -2
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +10 -2
- package/dist/src/types.js.map +1 -1
- package/package.json +7 -4
|
@@ -2,12 +2,24 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import { repositoryOpen } from '@elaraai/e3-core';
|
|
5
|
+
import { RepositoryUpgradePendingError, repositoryOpen } from '@elaraai/e3-core';
|
|
6
6
|
import { sendJsonError } from '../errors.js';
|
|
7
|
+
/** How long, in seconds, a client is told to wait before it asks again of a
|
|
8
|
+
* repository an upgrade waits on. */
|
|
9
|
+
const UPGRADE_RETRY_AFTER_S = 5;
|
|
7
10
|
/** Whether a request creates or removes a repository. */
|
|
8
11
|
function createsOrRemoves(c) {
|
|
9
12
|
return (c.req.method === 'PUT' || c.req.method === 'DELETE') && /\/repos\/[^/]+$/.test(c.req.path);
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Whether a request stops or polls a workspace's dataflow: what a repository
|
|
16
|
+
* an upgrade waits on still answers, since the run is what the upgrade waits
|
|
17
|
+
* for, and both reach only the run's state and its orchestrator.
|
|
18
|
+
*/
|
|
19
|
+
function stopsOrPollsDataflow(c) {
|
|
20
|
+
const run = /\/repos\/[^/]+\/workspaces\/[^/]+\/dataflow\/(cancel|execution)$/.exec(c.req.path);
|
|
21
|
+
return run !== null && (run[1] === 'cancel' ? c.req.method === 'POST' : c.req.method === 'GET');
|
|
22
|
+
}
|
|
11
23
|
/**
|
|
12
24
|
* The gate of a host's repositories: the repository exists, is not being
|
|
13
25
|
* removed, and is opened as every way into a repository opens it — upgraded in
|
|
@@ -16,12 +28,24 @@ function createsOrRemoves(c) {
|
|
|
16
28
|
* is not opened. It goes through the storage backend's `RepoStore`, so a host
|
|
17
29
|
* mounts it over its own.
|
|
18
30
|
*
|
|
31
|
+
* No request waits on an upgrade. The open refuses at once when the repository
|
|
32
|
+
* owes one and work running in it holds it, and the gate answers 503
|
|
33
|
+
* `repository_upgrade_pending`, naming the steps and the work, with a
|
|
34
|
+
* `Retry-After`; the steps apply at the first request that finds the
|
|
35
|
+
* repository still, or, with `options.applyUpgrades: false`, in the host's
|
|
36
|
+
* job, and the gate answers so until they have. A running dataflow's cancel
|
|
37
|
+
* and poll pass the gate all the same, so the run an upgrade waits for can
|
|
38
|
+
* always be stopped.
|
|
39
|
+
*
|
|
19
40
|
* @param storage - Storage backend, whose `RepoStore` keeps the repositories
|
|
20
41
|
* @param getRepoPath - A repository's identifier from its name, as the stores
|
|
21
42
|
* other than the `RepoStore` take it
|
|
43
|
+
* @param options - Whether a request applies the upgrades a repository owes,
|
|
44
|
+
* and what starts the host's job when not
|
|
22
45
|
* @returns The middleware
|
|
23
46
|
*/
|
|
24
|
-
export function createRepositoryGate(storage, getRepoPath) {
|
|
47
|
+
export function createRepositoryGate(storage, getRepoPath, options = {}) {
|
|
48
|
+
const apply = options.applyUpgrades ?? true;
|
|
25
49
|
return async (c, next) => {
|
|
26
50
|
if (createsOrRemoves(c)) {
|
|
27
51
|
await next();
|
|
@@ -47,10 +71,24 @@ export function createRepositoryGate(storage, getRepoPath) {
|
|
|
47
71
|
}
|
|
48
72
|
else {
|
|
49
73
|
try {
|
|
50
|
-
await repositoryOpen(storage, getRepoPath(repo));
|
|
74
|
+
await repositoryOpen(storage, getRepoPath(repo), { apply, waitMs: 0 });
|
|
51
75
|
}
|
|
52
76
|
catch (err) {
|
|
53
|
-
|
|
77
|
+
if (!(err instanceof RepositoryUpgradePendingError))
|
|
78
|
+
return sendJsonError(err);
|
|
79
|
+
if (err.job && options.onUpgradePending !== undefined) {
|
|
80
|
+
try {
|
|
81
|
+
await options.onUpgradePending(repo, err.upgrades);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// The host's to report; the next request calls it again.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!stopsOrPollsDataflow(c)) {
|
|
88
|
+
const refused = sendJsonError(err);
|
|
89
|
+
refused.headers.set('Retry-After', String(UPGRADE_RETRY_AFTER_S));
|
|
90
|
+
return refused;
|
|
91
|
+
}
|
|
54
92
|
}
|
|
55
93
|
}
|
|
56
94
|
await next();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/middleware/repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,OAAO,EAAE,cAAc,EAAuB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/middleware/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.spec.d.ts","sourceRoot":"","sources":["../../../src/middleware/repository.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The repository gate: an upgrade a repository owes never makes the work it
|
|
7
|
+
* waits for impossible to stop, no request is held for the wait, and a host
|
|
8
|
+
* may leave the upgrade to a job of its own.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it } from 'node:test';
|
|
11
|
+
import assert from 'node:assert/strict';
|
|
12
|
+
import { Hono } from 'hono';
|
|
13
|
+
import { encodeBeast2For, none, variant } from '@elaraai/east';
|
|
14
|
+
import { repositoryOpen } from '@elaraai/e3-core';
|
|
15
|
+
import { InMemoryStorage } from '@elaraai/e3-core/test';
|
|
16
|
+
import { WorkspaceRecordType } from '@elaraai/e3-types';
|
|
17
|
+
import { createRepositoryGate } from './repository.js';
|
|
18
|
+
describe('the repository gate', () => {
|
|
19
|
+
it('lets a running dataflow\'s cancel and poll through while an upgrade waits on the run, and holds no request for it', async () => {
|
|
20
|
+
const storage = new InMemoryStorage();
|
|
21
|
+
const repo = 'gated';
|
|
22
|
+
await storage.repos.create(repo);
|
|
23
|
+
await storage.refs.workspaceWrite(repo, 'main', encodeBeast2For(WorkspaceRecordType)(none));
|
|
24
|
+
// A dataflow runs in `main`, holding its workspace's dataflow lock, as the
|
|
25
|
+
// orchestrator does for the whole run.
|
|
26
|
+
const run = await storage.locks.acquire(repo, 'main#dataflow', variant('dataflow', null));
|
|
27
|
+
assert.ok(run, 'the run holds its workspace');
|
|
28
|
+
// The host is upgraded to a release whose backend ships a layout step,
|
|
29
|
+
// which the repository, created before it, owes.
|
|
30
|
+
const applied = [];
|
|
31
|
+
storage.upgrades.push({ name: 'host-layout-2', apply: async () => { applied.push('host-layout-2'); } });
|
|
32
|
+
const app = new Hono();
|
|
33
|
+
app.use('/api/repos/:repo/*', createRepositoryGate(storage, (r) => r));
|
|
34
|
+
app.post('/api/repos/:repo/workspaces/:ws/dataflow/cancel', (c) => c.text('the cancel route ran'));
|
|
35
|
+
app.get('/api/repos/:repo/workspaces/:ws/dataflow/execution', (c) => c.text('the poll route ran'));
|
|
36
|
+
app.get('/api/repos/:repo/workspaces/:ws/status', (c) => c.text('the status route ran'));
|
|
37
|
+
try {
|
|
38
|
+
for (const [method, path, answer] of [
|
|
39
|
+
['POST', 'dataflow/cancel', 'the cancel route ran'],
|
|
40
|
+
['GET', 'dataflow/execution', 'the poll route ran'],
|
|
41
|
+
]) {
|
|
42
|
+
const started = Date.now();
|
|
43
|
+
const response = await app.request(`/api/repos/${repo}/workspaces/main/${path}`, { method });
|
|
44
|
+
assert.equal(response.status, 200, `${method} ${path}`);
|
|
45
|
+
assert.equal(await response.text(), answer);
|
|
46
|
+
assert.ok(Date.now() - started < 5_000, `${method} ${path} waited on the upgrade`);
|
|
47
|
+
}
|
|
48
|
+
// Every other request is refused at once, naming the step and the run,
|
|
49
|
+
// with when to ask again.
|
|
50
|
+
const started = Date.now();
|
|
51
|
+
const refused = await app.request(`/api/repos/${repo}/workspaces/main/status`);
|
|
52
|
+
assert.ok(Date.now() - started < 5_000, 'the refusal waited on the upgrade');
|
|
53
|
+
assert.equal(refused.status, 503);
|
|
54
|
+
assert.equal(refused.headers.get('Retry-After'), '5');
|
|
55
|
+
assert.deepEqual(await refused.json(), {
|
|
56
|
+
error: {
|
|
57
|
+
type: 'repository_upgrade_pending',
|
|
58
|
+
message: 'the repository gated owes the upgrade "host-layout-2", which applies once nothing runs in it, '
|
|
59
|
+
+ 'and a dataflow is running in workspace \'main\' — retry when it finishes, or cancel it',
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
assert.deepEqual(applied, []);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await run.release();
|
|
66
|
+
}
|
|
67
|
+
// Once the run has let its workspace go, the next request applies the step.
|
|
68
|
+
const status = await app.request(`/api/repos/${repo}/workspaces/main/status`);
|
|
69
|
+
assert.equal(await status.text(), 'the status route ran');
|
|
70
|
+
assert.deepEqual(applied, ['host-layout-2']);
|
|
71
|
+
assert.deepEqual((await storage.refs.repositoryRead(repo))?.upgrades.map(({ name }) => name), ['host-layout-2']);
|
|
72
|
+
});
|
|
73
|
+
it('leaves the upgrade to the host\'s job when told to: no request applies it, each one tells the host, and all pass once the job has', async () => {
|
|
74
|
+
const storage = new InMemoryStorage();
|
|
75
|
+
const repo = 'gated';
|
|
76
|
+
await storage.repos.create(repo);
|
|
77
|
+
await storage.refs.workspaceWrite(repo, 'main', encodeBeast2For(WorkspaceRecordType)(none));
|
|
78
|
+
const applied = [];
|
|
79
|
+
storage.upgrades.push({ name: 'host-layout-2', apply: async () => { applied.push('host-layout-2'); } });
|
|
80
|
+
// The host starts its job as it is told; the second time, starting it
|
|
81
|
+
// fails, which the host reports itself.
|
|
82
|
+
const told = [];
|
|
83
|
+
const app = new Hono();
|
|
84
|
+
app.use('/api/repos/:repo/*', createRepositoryGate(storage, (r) => r, {
|
|
85
|
+
applyUpgrades: false,
|
|
86
|
+
onUpgradePending: (name, upgrades) => {
|
|
87
|
+
told.push([name, upgrades]);
|
|
88
|
+
if (told.length === 2)
|
|
89
|
+
throw new Error('the job did not start');
|
|
90
|
+
},
|
|
91
|
+
}));
|
|
92
|
+
app.post('/api/repos/:repo/workspaces/:ws/dataflow/cancel', (c) => c.text('the cancel route ran'));
|
|
93
|
+
app.get('/api/repos/:repo/workspaces/:ws/status', (c) => c.text('the status route ran'));
|
|
94
|
+
// Nothing runs in the repository, and still no request applies the step.
|
|
95
|
+
for (let i = 0; i < 2; i++) {
|
|
96
|
+
const refused = await app.request(`/api/repos/${repo}/workspaces/main/status`);
|
|
97
|
+
assert.equal(refused.status, 503);
|
|
98
|
+
assert.equal(refused.headers.get('Retry-After'), '5');
|
|
99
|
+
assert.deepEqual(await refused.json(), {
|
|
100
|
+
error: {
|
|
101
|
+
type: 'repository_upgrade_pending',
|
|
102
|
+
message: 'the repository gated owes the upgrade "host-layout-2", which a job applies before the repository is read — retry once it has',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const cancel = await app.request(`/api/repos/${repo}/workspaces/main/dataflow/cancel`, { method: 'POST' });
|
|
107
|
+
assert.equal(await cancel.text(), 'the cancel route ran');
|
|
108
|
+
assert.deepEqual(told, [['gated', ['host-layout-2']], ['gated', ['host-layout-2']], ['gated', ['host-layout-2']]]);
|
|
109
|
+
assert.deepEqual(applied, []);
|
|
110
|
+
// The host's job opens the repository, which applies the step.
|
|
111
|
+
await repositoryOpen(storage, repo);
|
|
112
|
+
assert.deepEqual(applied, ['host-layout-2']);
|
|
113
|
+
const status = await app.request(`/api/repos/${repo}/workspaces/main/status`);
|
|
114
|
+
assert.equal(await status.text(), 'the status route ran');
|
|
115
|
+
assert.equal(told.length, 3, 'a repository that owes nothing tells the host nothing');
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=repository.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.spec.js","sourceRoot":"","sources":["../../../src/middleware/repository.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,41 +7,122 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Functions touch no datasets, so they are callable at the package level
|
|
9
9
|
* (imported in a repo, no workspace) and at the workspace level (resolved
|
|
10
|
-
* from the deployed package). Both mount the same handlers.
|
|
10
|
+
* from the deployed package). Both mount the same handlers. A function runs
|
|
11
|
+
* on its author's runner for any caller the routes admit; a runner a call
|
|
12
|
+
* names instead is held to the caller's grant, which the routes take as the
|
|
13
|
+
* one-shot routes do.
|
|
11
14
|
*
|
|
12
|
-
* One-shot is workspace-scoped, caller-supplied IR
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* One-shot is workspace-scoped, caller-supplied IR. Who may run what is the
|
|
16
|
+
* host's to say, since only its auth knows who the caller is: the route takes
|
|
17
|
+
* a {@link OneShotAccess}, which gives each request's caller a grant — `any`,
|
|
18
|
+
* `platform_free` or `none` — and e3-core's `oneShotExecute` runs the request
|
|
19
|
+
* under it. A caller who may read a workspace may run a platform-free
|
|
20
|
+
* one-shot, which can only compute over its arguments. A split call — a
|
|
21
|
+
* caller's program over a dataset's pieces — is launched under the same grant,
|
|
22
|
+
* and runs as a job the client polls.
|
|
17
23
|
*/
|
|
18
24
|
import { Hono } from 'hono';
|
|
19
|
-
import type {
|
|
25
|
+
import type { Context } from 'hono';
|
|
26
|
+
import type { ExecuteCeilings, OneShotGrant, StorageBackend, TaskRunner, TransferBackend } from '@elaraai/e3-core';
|
|
20
27
|
import type { Identity } from '../middleware/auth.js';
|
|
21
28
|
/**
|
|
22
29
|
* Per-repo TaskRunner accessor — the runner is injected (the local server
|
|
23
30
|
* passes LocalTaskRunner), mirroring the orchestrator runner-injection seam.
|
|
24
31
|
*/
|
|
25
32
|
export type GetRunner = (repoPath: string) => TaskRunner;
|
|
33
|
+
/**
|
|
34
|
+
* Gives each request's caller a one-shot grant. Only the host's auth knows who
|
|
35
|
+
* the caller is, so every host that mounts the one-shot routes decides.
|
|
36
|
+
*/
|
|
37
|
+
export type OneShotAccess = (c: Context) => OneShotGrant | Promise<OneShotGrant>;
|
|
38
|
+
/** Options for {@link createOneShotRoutes}. */
|
|
39
|
+
export interface OneShotRoutesOptions {
|
|
40
|
+
/** Who may run what. Required, so every host decides. */
|
|
41
|
+
access: OneShotAccess;
|
|
42
|
+
/** A sync call's deadline, under the host's request timeout (default
|
|
43
|
+
* 120 000 ms). */
|
|
44
|
+
syncDeadlineMs?: number;
|
|
45
|
+
/** The most a request may ask for, where a host's response limits are
|
|
46
|
+
* tighter than a server's default. */
|
|
47
|
+
ceilings?: ExecuteCeilings;
|
|
48
|
+
}
|
|
49
|
+
/** Options for the named function routes. */
|
|
50
|
+
export interface FunctionRoutesOptions {
|
|
51
|
+
/** A sync call's deadline, under the host's request timeout (default
|
|
52
|
+
* 120 000 ms). */
|
|
53
|
+
syncDeadlineMs?: number;
|
|
54
|
+
/**
|
|
55
|
+
* The grant each request's caller holds, as the one-shot routes' `access`
|
|
56
|
+
* gives it, which decides whether a call may give the function a platform
|
|
57
|
+
* package its own runner does not load: only `any` may. A call that names no
|
|
58
|
+
* runner, or one on a stock runtime with no package the function's does not
|
|
59
|
+
* load, runs for any caller; the `custom` runtime is refused every caller.
|
|
60
|
+
* Absent, no caller may add a package.
|
|
61
|
+
*/
|
|
62
|
+
access?: OneShotAccess;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The one-shot grant of a caller by the roles its token carries: `any` for an
|
|
66
|
+
* identity holding one of `elevated`, `platform_free` for any other identity,
|
|
67
|
+
* and `none` for a request with none.
|
|
68
|
+
*
|
|
69
|
+
* @param elevated - The roles that run any one-shot (default `admin` and
|
|
70
|
+
* `owner`)
|
|
71
|
+
* @returns The access a host with role-bearing tokens mounts
|
|
72
|
+
*/
|
|
73
|
+
export declare function oneShotAccessByRoles(elevated?: readonly string[]): OneShotAccess;
|
|
26
74
|
/**
|
|
27
75
|
* Package-scoped function routes, mounted at
|
|
28
76
|
* `/api/repos/:repo/packages/:pkg/:version/functions`.
|
|
77
|
+
*
|
|
78
|
+
* @param storage - Storage backend
|
|
79
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
80
|
+
* @param getRunner - Each repository's task runner
|
|
81
|
+
* @param options - The host's sync deadline, and the grant a runner a call
|
|
82
|
+
* names is held to
|
|
83
|
+
* @returns The routes
|
|
29
84
|
*/
|
|
30
|
-
export declare function createPackageFunctionRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, getRunner: GetRunner): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
85
|
+
export declare function createPackageFunctionRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, getRunner: GetRunner, options?: FunctionRoutesOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
31
86
|
/**
|
|
32
87
|
* Workspace-scoped function routes, mounted at
|
|
33
88
|
* `/api/repos/:repo/workspaces/:ws/functions`. The package is resolved from
|
|
34
89
|
* what's deployed in the workspace; the handlers are identical.
|
|
90
|
+
*
|
|
91
|
+
* @param storage - Storage backend
|
|
92
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
93
|
+
* @param getRunner - Each repository's task runner
|
|
94
|
+
* @param options - The host's sync deadline, and the grant a runner a call
|
|
95
|
+
* names is held to
|
|
96
|
+
* @returns The routes
|
|
35
97
|
*/
|
|
36
|
-
export declare function createWorkspaceFunctionRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, getRunner: GetRunner): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
98
|
+
export declare function createWorkspaceFunctionRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, getRunner: GetRunner, options?: FunctionRoutesOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
37
99
|
/**
|
|
38
100
|
* One-shot routes, mounted at `/api/repos/:repo/workspaces/:ws/one-shot`.
|
|
39
101
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
102
|
+
* - `POST /` takes the caller's grant from `options.access`, and runs the
|
|
103
|
+
* request under it through e3-core's `oneShotExecute`, stopped when the
|
|
104
|
+
* caller hangs up.
|
|
105
|
+
* - `POST /split` launches a split call under the same grant and answers its
|
|
106
|
+
* job's id; with `?explain=1` its job plans the call's pieces instead, and
|
|
107
|
+
* runs no unit.
|
|
108
|
+
* - `GET /split/:id` answers a split call's status: how far it has got, its
|
|
109
|
+
* result, the pieces an explain planned, or why e3 could not run it.
|
|
110
|
+
*
|
|
111
|
+
* A caller refused is answered `permission_denied` (`path` `one-shot`), and
|
|
112
|
+
* nothing runs. A caller whose grant is `none` polls no split call, and one
|
|
113
|
+
* whose grant is `platform_free` only a platform-free one, or one such a
|
|
114
|
+
* caller launched.
|
|
115
|
+
*
|
|
116
|
+
* @param storage - Storage backend
|
|
117
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
118
|
+
* @param transferBackend - Files and dispatches the jobs split calls run as,
|
|
119
|
+
* which outlast a request, on the runner the backend was given
|
|
120
|
+
* @param getRunner - Each repository's task runner
|
|
121
|
+
* @param options - Who may run what, the host's sync deadline and the most a
|
|
122
|
+
* request may ask for
|
|
123
|
+
* @returns The routes
|
|
43
124
|
*/
|
|
44
|
-
export declare function createOneShotRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, getRunner: GetRunner): Hono<{
|
|
125
|
+
export declare function createOneShotRoutes(storage: StorageBackend, getRepoPath: (repo: string) => string, transferBackend: TransferBackend, getRunner: GetRunner, options: OneShotRoutesOptions): Hono<{
|
|
45
126
|
Variables: {
|
|
46
127
|
identity?: Identity;
|
|
47
128
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/routes/functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/routes/functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAiBtD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,UAAU,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAEjF,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,MAAM,EAAE,aAAa,CAAC;IACtB;uBACmB;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;2CACuC;IACvC,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,6CAA6C;AAC7C,MAAM,WAAW,qBAAqB;IACpC;uBACmB;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAOD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,SAAS,MAAM,EAAuB,GAAG,aAAa,CAMpG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACrC,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,qBAA0B,8EA6BpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACrC,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,qBAA0B,8EAyCpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACrC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,oBAAoB;eAEK;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAE;0CAgD1D"}
|
|
@@ -7,28 +7,59 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Functions touch no datasets, so they are callable at the package level
|
|
9
9
|
* (imported in a repo, no workspace) and at the workspace level (resolved
|
|
10
|
-
* from the deployed package). Both mount the same handlers.
|
|
10
|
+
* from the deployed package). Both mount the same handlers. A function runs
|
|
11
|
+
* on its author's runner for any caller the routes admit; a runner a call
|
|
12
|
+
* names instead is held to the caller's grant, which the routes take as the
|
|
13
|
+
* one-shot routes do.
|
|
11
14
|
*
|
|
12
|
-
* One-shot is workspace-scoped, caller-supplied IR
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* One-shot is workspace-scoped, caller-supplied IR. Who may run what is the
|
|
16
|
+
* host's to say, since only its auth knows who the caller is: the route takes
|
|
17
|
+
* a {@link OneShotAccess}, which gives each request's caller a grant — `any`,
|
|
18
|
+
* `platform_free` or `none` — and e3-core's `oneShotExecute` runs the request
|
|
19
|
+
* under it. A caller who may read a workspace may run a platform-free
|
|
20
|
+
* one-shot, which can only compute over its arguments. A split call — a
|
|
21
|
+
* caller's program over a dataset's pieces — is launched under the same grant,
|
|
22
|
+
* and runs as a job the client polls.
|
|
17
23
|
*/
|
|
18
24
|
import { Hono } from 'hono';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { decodeBody, sendError } from '../beast2.js';
|
|
25
|
+
import { oneShotExecute, workspaceGetPackage } from '@elaraai/e3-core';
|
|
26
|
+
import { decodeBody, sendError, sendSuccess } from '../beast2.js';
|
|
22
27
|
import { errorToVariant } from '../errors.js';
|
|
23
|
-
import { FunctionCallRequestType, OneShotRequestType, ExecuteResultType, } from '../types.js';
|
|
24
|
-
import { listPackageFunctions, describePackageFunction, callFunctionSync,
|
|
25
|
-
/**
|
|
26
|
-
|
|
28
|
+
import { FunctionCallRequestType, OneShotRequestType, ExecuteResultType, PackageJobResponseType, SplitCallRequestType, SplitCallStatusType, } from '../types.js';
|
|
29
|
+
import { listPackageFunctions, describePackageFunction, callFunctionSync, getSplitCallStatus, startSplitCall, } from '../handlers/functions.js';
|
|
30
|
+
/** The grant of a function call's caller, by the routes' options. */
|
|
31
|
+
async function functionGrant(c, options) {
|
|
32
|
+
return options.access === undefined ? 'platform_free' : options.access(c);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The one-shot grant of a caller by the roles its token carries: `any` for an
|
|
36
|
+
* identity holding one of `elevated`, `platform_free` for any other identity,
|
|
37
|
+
* and `none` for a request with none.
|
|
38
|
+
*
|
|
39
|
+
* @param elevated - The roles that run any one-shot (default `admin` and
|
|
40
|
+
* `owner`)
|
|
41
|
+
* @returns The access a host with role-bearing tokens mounts
|
|
42
|
+
*/
|
|
43
|
+
export function oneShotAccessByRoles(elevated = ['admin', 'owner']) {
|
|
44
|
+
return (c) => {
|
|
45
|
+
const identity = c.get('identity');
|
|
46
|
+
if (identity === undefined)
|
|
47
|
+
return 'none';
|
|
48
|
+
return (identity.roles ?? []).some((role) => elevated.includes(role)) ? 'any' : 'platform_free';
|
|
49
|
+
};
|
|
50
|
+
}
|
|
27
51
|
/**
|
|
28
52
|
* Package-scoped function routes, mounted at
|
|
29
53
|
* `/api/repos/:repo/packages/:pkg/:version/functions`.
|
|
54
|
+
*
|
|
55
|
+
* @param storage - Storage backend
|
|
56
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
57
|
+
* @param getRunner - Each repository's task runner
|
|
58
|
+
* @param options - The host's sync deadline, and the grant a runner a call
|
|
59
|
+
* names is held to
|
|
60
|
+
* @returns The routes
|
|
30
61
|
*/
|
|
31
|
-
export function createPackageFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
62
|
+
export function createPackageFunctionRoutes(storage, getRepoPath, getRunner, options = {}) {
|
|
32
63
|
const app = new Hono();
|
|
33
64
|
// GET / - List functions with signatures
|
|
34
65
|
app.get('/', async (c) => {
|
|
@@ -44,8 +75,9 @@ export function createPackageFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
|
44
75
|
app.post('/:fn', async (c) => {
|
|
45
76
|
const repoPath = getRepoPath(c.req.param('repo'));
|
|
46
77
|
try {
|
|
78
|
+
const grant = await functionGrant(c, options);
|
|
47
79
|
const req = await decodeBody(c, FunctionCallRequestType);
|
|
48
|
-
return await callFunctionSync(storage, repoPath, getRunner(repoPath), c.req.param('pkg'), c.req.param('version'), c.req.param('fn'), req, c.req.query('verbose') === '1');
|
|
80
|
+
return await callFunctionSync(storage, repoPath, getRunner(repoPath), c.req.param('pkg'), c.req.param('version'), c.req.param('fn'), req, c.req.query('verbose') === '1', options.syncDeadlineMs, grant);
|
|
49
81
|
}
|
|
50
82
|
catch (err) {
|
|
51
83
|
return sendError(ExecuteResultType, errorToVariant(err));
|
|
@@ -57,8 +89,15 @@ export function createPackageFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
|
57
89
|
* Workspace-scoped function routes, mounted at
|
|
58
90
|
* `/api/repos/:repo/workspaces/:ws/functions`. The package is resolved from
|
|
59
91
|
* what's deployed in the workspace; the handlers are identical.
|
|
92
|
+
*
|
|
93
|
+
* @param storage - Storage backend
|
|
94
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
95
|
+
* @param getRunner - Each repository's task runner
|
|
96
|
+
* @param options - The host's sync deadline, and the grant a runner a call
|
|
97
|
+
* names is held to
|
|
98
|
+
* @returns The routes
|
|
60
99
|
*/
|
|
61
|
-
export function createWorkspaceFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
100
|
+
export function createWorkspaceFunctionRoutes(storage, getRepoPath, getRunner, options = {}) {
|
|
62
101
|
const app = new Hono();
|
|
63
102
|
const deployed = async (c) => {
|
|
64
103
|
const repoPath = getRepoPath(c.req.param('repo'));
|
|
@@ -87,8 +126,9 @@ export function createWorkspaceFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
|
87
126
|
app.post('/:fn', async (c) => {
|
|
88
127
|
try {
|
|
89
128
|
const { repoPath, name, version } = await deployed(c);
|
|
129
|
+
const grant = await functionGrant(c, options);
|
|
90
130
|
const req = await decodeBody(c, FunctionCallRequestType);
|
|
91
|
-
return await callFunctionSync(storage, repoPath, getRunner(repoPath), name, version, c.req.param('fn'), req, c.req.query('verbose') === '1');
|
|
131
|
+
return await callFunctionSync(storage, repoPath, getRunner(repoPath), name, version, c.req.param('fn'), req, c.req.query('verbose') === '1', options.syncDeadlineMs, grant);
|
|
92
132
|
}
|
|
93
133
|
catch (err) {
|
|
94
134
|
return sendError(ExecuteResultType, errorToVariant(err));
|
|
@@ -99,30 +139,76 @@ export function createWorkspaceFunctionRoutes(storage, getRepoPath, getRunner) {
|
|
|
99
139
|
/**
|
|
100
140
|
* One-shot routes, mounted at `/api/repos/:repo/workspaces/:ws/one-shot`.
|
|
101
141
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
142
|
+
* - `POST /` takes the caller's grant from `options.access`, and runs the
|
|
143
|
+
* request under it through e3-core's `oneShotExecute`, stopped when the
|
|
144
|
+
* caller hangs up.
|
|
145
|
+
* - `POST /split` launches a split call under the same grant and answers its
|
|
146
|
+
* job's id; with `?explain=1` its job plans the call's pieces instead, and
|
|
147
|
+
* runs no unit.
|
|
148
|
+
* - `GET /split/:id` answers a split call's status: how far it has got, its
|
|
149
|
+
* result, the pieces an explain planned, or why e3 could not run it.
|
|
150
|
+
*
|
|
151
|
+
* A caller refused is answered `permission_denied` (`path` `one-shot`), and
|
|
152
|
+
* nothing runs. A caller whose grant is `none` polls no split call, and one
|
|
153
|
+
* whose grant is `platform_free` only a platform-free one, or one such a
|
|
154
|
+
* caller launched.
|
|
155
|
+
*
|
|
156
|
+
* @param storage - Storage backend
|
|
157
|
+
* @param getRepoPath - A repository's identifier from its name
|
|
158
|
+
* @param transferBackend - Files and dispatches the jobs split calls run as,
|
|
159
|
+
* which outlast a request, on the runner the backend was given
|
|
160
|
+
* @param getRunner - Each repository's task runner
|
|
161
|
+
* @param options - Who may run what, the host's sync deadline and the most a
|
|
162
|
+
* request may ask for
|
|
163
|
+
* @returns The routes
|
|
105
164
|
*/
|
|
106
|
-
export function createOneShotRoutes(storage, getRepoPath, getRunner) {
|
|
165
|
+
export function createOneShotRoutes(storage, getRepoPath, transferBackend, getRunner, options) {
|
|
107
166
|
const app = new Hono();
|
|
108
|
-
// Role gate: identity is set by the auth middleware when configured.
|
|
109
|
-
app.use('*', async (c, next) => {
|
|
110
|
-
const identity = c.get('identity');
|
|
111
|
-
if (identity && !(identity.roles ?? []).some((r) => ONE_SHOT_ROLES.includes(r))) {
|
|
112
|
-
return sendError(ExecuteResultType, variant('permission_denied', { path: 'one-shot' }));
|
|
113
|
-
}
|
|
114
|
-
await next();
|
|
115
|
-
});
|
|
116
167
|
app.post('/', async (c) => {
|
|
117
168
|
const repoPath = getRepoPath(c.req.param('repo'));
|
|
118
169
|
try {
|
|
170
|
+
const grant = await options.access(c);
|
|
119
171
|
const req = await decodeBody(c, OneShotRequestType);
|
|
120
|
-
|
|
172
|
+
const result = await oneShotExecute(storage, getRunner(repoPath), repoPath, c.req.param('ws'), req, {
|
|
173
|
+
grant,
|
|
174
|
+
signal: c.req.raw.signal,
|
|
175
|
+
verbose: c.req.query('verbose') === '1',
|
|
176
|
+
...(options.syncDeadlineMs !== undefined && { syncDeadlineMs: options.syncDeadlineMs }),
|
|
177
|
+
...(options.ceilings !== undefined && { ceilings: options.ceilings }),
|
|
178
|
+
});
|
|
179
|
+
return sendSuccess(ExecuteResultType, result);
|
|
121
180
|
}
|
|
122
181
|
catch (err) {
|
|
123
182
|
return sendError(ExecuteResultType, errorToVariant(err));
|
|
124
183
|
}
|
|
125
184
|
});
|
|
185
|
+
// POST /split - Launch a split call (or, with ?explain=1, a job that plans
|
|
186
|
+
// its pieces)
|
|
187
|
+
app.post('/split', async (c) => {
|
|
188
|
+
const repo = c.req.param('repo');
|
|
189
|
+
try {
|
|
190
|
+
const grant = await options.access(c);
|
|
191
|
+
const req = await decodeBody(c, SplitCallRequestType);
|
|
192
|
+
return await startSplitCall(storage, getRepoPath(repo), repo, c.req.param('ws'), req, grant, transferBackend.splitCall, {
|
|
193
|
+
...(options.ceilings !== undefined && { ceilings: options.ceilings }),
|
|
194
|
+
explain: c.req.query('explain') === '1',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
return sendError(PackageJobResponseType, errorToVariant(err));
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
// GET /split/:id - Poll a split call
|
|
202
|
+
app.get('/split/:id', async (c) => {
|
|
203
|
+
const repo = c.req.param('repo');
|
|
204
|
+
try {
|
|
205
|
+
const grant = await options.access(c);
|
|
206
|
+
return await getSplitCallStatus(storage, getRepoPath(repo), transferBackend.splitCall, repo, c.req.param('ws'), c.req.param('id'), grant);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
return sendError(SplitCallStatusType, errorToVariant(err));
|
|
210
|
+
}
|
|
211
|
+
});
|
|
126
212
|
return app;
|
|
127
213
|
}
|
|
128
214
|
//# sourceMappingURL=functions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/routes/functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/routes/functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,6 @@ export { createObjectRoutes } from './objects.js';
|
|
|
13
13
|
export { createTransferRoutes, type TransferRouteOptions } from './transfer.js';
|
|
14
14
|
export { createPackageTransferRoutes } from './package-transfer.js';
|
|
15
15
|
export { createDataEndpoints } from './data.js';
|
|
16
|
-
export { createPackageFunctionRoutes, createWorkspaceFunctionRoutes, createOneShotRoutes, type GetRunner } from './functions.js';
|
|
16
|
+
export { createPackageFunctionRoutes, createWorkspaceFunctionRoutes, createOneShotRoutes, oneShotAccessByRoles, type GetRunner, type OneShotAccess, type OneShotRoutesOptions, type FunctionRoutesOptions, } from './functions.js';
|
|
17
17
|
export { createWorkspaceRecordRoutes } from './records.js';
|
|
18
18
|
//# sourceMappingURL=index.d.ts.map
|