@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
|
@@ -3,62 +3,25 @@
|
|
|
3
3
|
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* Handlers for named package functions
|
|
6
|
+
* Handlers for named package functions.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* A call reduces to the graph-free `runDetached` primitive: marshal inputs →
|
|
9
9
|
* run a body IR on a runner → return the result inline. Nothing durable is
|
|
10
10
|
* written — no output object, no execution record, no logs, no dataset ref.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* routes/functions.ts)
|
|
11
|
+
* Named functions are author-published IR (same trust as a deployed task),
|
|
12
|
+
* which any caller the route admits runs on the function's own runner; a
|
|
13
|
+
* runner the caller names instead is held to its grant (`callFunctionSync`).
|
|
14
|
+
* One-shot, whose IR is the caller's, runs through e3-core's `oneShotExecute`
|
|
15
|
+
* under the grant the host gives the caller (routes/functions.ts), and so does
|
|
16
|
+
* a split call's launch, which runs as a job the client polls.
|
|
16
17
|
*/
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { randomUUID } from 'node:crypto';
|
|
19
|
+
import { ArrayType, none, some, variant } from '@elaraai/east';
|
|
20
|
+
import { packageRead, PermissionDeniedError, TaskNotFoundError, detachedToExecuteResult, invalidExecuteResult, resolveExecuteLimits, resolveJobLimits, splitCallInvalid, splitCallPlatformFree, splitCallPrepare, splitCallResult, } from '@elaraai/e3-core';
|
|
19
21
|
import { decodeFunctionObject } from '@elaraai/e3-types';
|
|
20
22
|
import { sendSuccess, sendError } from '../beast2.js';
|
|
21
23
|
import { errorToVariant } from '../errors.js';
|
|
22
|
-
import { FunctionSignatureType, ExecuteResultType, } from '../types.js';
|
|
23
|
-
// =============================================================================
|
|
24
|
-
// Limits (server-owned, clamped)
|
|
25
|
-
// =============================================================================
|
|
26
|
-
/** Default per-call timeout when the request doesn't specify one. */
|
|
27
|
-
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
28
|
-
/** Hard ceiling on any call's timeout (async included). */
|
|
29
|
-
const MAX_TIMEOUT_MS = 10 * 60_000;
|
|
30
|
-
/** Sync calls additionally respect a server-owned wall-clock deadline so the
|
|
31
|
-
* caller gets a structured `timed_out` instead of a transport cut. (The
|
|
32
|
-
* cloud sets this below API Gateway's 29 s; locally we can be generous.) */
|
|
33
|
-
const SERVER_SYNC_DEADLINE_MS = 120_000;
|
|
34
|
-
/** Default + ceiling for the inline result size (see design §9: 1 MB leaves
|
|
35
|
-
* 3-4x headroom under the base64-inflated Lambda ceiling and still allows
|
|
36
|
-
* multi-thousand-row tables inline). Requests may lower it, never raise it. */
|
|
37
|
-
const MAX_RESULT_BYTES = 1024 * 1024;
|
|
38
|
-
/** Default + ceiling for each captured log stream's tail. */
|
|
39
|
-
const MAX_LOG_BYTES = 256 * 1024;
|
|
40
|
-
const DEFAULT_LOG_BYTES = 64 * 1024;
|
|
41
|
-
function resolveLimits(limits, sync) {
|
|
42
|
-
const req = limits.type === 'some' ? limits.value : undefined;
|
|
43
|
-
let timeoutMs = req && req.timeoutMs.type === 'some'
|
|
44
|
-
? Number(req.timeoutMs.value)
|
|
45
|
-
: DEFAULT_TIMEOUT_MS;
|
|
46
|
-
timeoutMs = Math.min(Math.max(1, timeoutMs), MAX_TIMEOUT_MS);
|
|
47
|
-
if (sync)
|
|
48
|
-
timeoutMs = Math.min(timeoutMs, SERVER_SYNC_DEADLINE_MS);
|
|
49
|
-
let maxResultBytes = req && req.maxResultBytes.type === 'some'
|
|
50
|
-
? Number(req.maxResultBytes.value)
|
|
51
|
-
: MAX_RESULT_BYTES;
|
|
52
|
-
maxResultBytes = Math.min(Math.max(1, maxResultBytes), MAX_RESULT_BYTES);
|
|
53
|
-
let maxLogBytes = req && req.maxLogBytes.type === 'some'
|
|
54
|
-
? Number(req.maxLogBytes.value)
|
|
55
|
-
: DEFAULT_LOG_BYTES;
|
|
56
|
-
maxLogBytes = Math.min(Math.max(0, maxLogBytes), MAX_LOG_BYTES);
|
|
57
|
-
return { timeoutMs, maxResultBytes, maxLogBytes };
|
|
58
|
-
}
|
|
59
|
-
// =============================================================================
|
|
60
|
-
// Shared helpers
|
|
61
|
-
// =============================================================================
|
|
24
|
+
import { FunctionSignatureType, ExecuteResultType, PackageJobResponseType, SplitCallStatusType, } from '../types.js';
|
|
62
25
|
/**
|
|
63
26
|
* Resolve a named function in a package to its FunctionObject.
|
|
64
27
|
*
|
|
@@ -76,104 +39,66 @@ async function resolveFunction(storage, repoPath, pkgName, version, fnName) {
|
|
|
76
39
|
const fnData = await storage.objects.read(repoPath, fnHash);
|
|
77
40
|
return decodeFunctionObject(Buffer.from(fnData));
|
|
78
41
|
}
|
|
79
|
-
/**
|
|
80
|
-
function
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
42
|
+
/**
|
|
43
|
+
* The runner a call names in place of the function's own, as the caller's
|
|
44
|
+
* grant allows it: the `invalid` result that refuses it, or `null` when it
|
|
45
|
+
* runs.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* A function's body is its author's, and runs on its author's runner as a
|
|
49
|
+
* task's does, so a call that names no runner runs for any caller the route
|
|
50
|
+
* admits. A runner the call names is the caller's:
|
|
51
|
+
* - the `custom` runtime is refused whatever the grant, since it would run a
|
|
52
|
+
* command of the caller's own;
|
|
53
|
+
* - a stock runtime given a platform package the function's own runner does
|
|
54
|
+
* not load makes more reachable than the author gave the body, and runs only
|
|
55
|
+
* under the elevated grant (`any`);
|
|
56
|
+
* - any other — the function's packages, or fewer, on a stock runtime — runs
|
|
57
|
+
* for any caller.
|
|
58
|
+
*
|
|
59
|
+
* @throws {PermissionDeniedError} When the runner gives a package the
|
|
60
|
+
* function's does not load, and the grant is not `any` (`path` `runner`).
|
|
61
|
+
*/
|
|
62
|
+
function overrideRefusal(stored, override, grant) {
|
|
63
|
+
if (override.type === 'custom') {
|
|
64
|
+
return invalidExecuteResult('the call names the custom runtime to run the function on, which runs a command of its own: '
|
|
65
|
+
+ 'a function runs on its own runner, or on a stock runtime the call names — east_c, east_node or east_py');
|
|
96
66
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
diagnostics: [{ message, filename: none, line: none, column: none }],
|
|
103
|
-
}),
|
|
104
|
-
stdout: '',
|
|
105
|
-
stderr: '',
|
|
106
|
-
stdoutTruncated: false,
|
|
107
|
-
stderrTruncated: false,
|
|
108
|
-
};
|
|
67
|
+
const loaded = stored.type === 'custom' ? [] : stored.value.platforms;
|
|
68
|
+
if (grant !== 'any' && override.value.platforms.some((platform) => !loaded.includes(platform))) {
|
|
69
|
+
throw new PermissionDeniedError('runner');
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
109
72
|
}
|
|
110
73
|
/**
|
|
111
|
-
* Execute a resolved named function: arity check →
|
|
112
|
-
*
|
|
74
|
+
* Execute a resolved named function: arity check → the caller's runner, when
|
|
75
|
+
* it names one → read bodyIr → runDetached. Never throws for execution
|
|
76
|
+
* outcomes — only for storage/infra errors, and a runner the caller's grant
|
|
77
|
+
* does not allow.
|
|
113
78
|
*/
|
|
114
|
-
async function executeFunction(storage, repoPath, runner, fnObj, req,
|
|
79
|
+
async function executeFunction(storage, repoPath, runner, fnObj, req, syncDeadlineMs, grant, signal, verbose) {
|
|
115
80
|
// Signature validation: arity is checked here, before anything runs.
|
|
116
81
|
// Per-element type errors surface as a runtime decode failure (`failed`)
|
|
117
82
|
// from the runner.
|
|
118
83
|
if (req.args.length !== fnObj.inputTypes.length) {
|
|
119
|
-
return
|
|
84
|
+
return invalidExecuteResult(`Expected ${fnObj.inputTypes.length} argument(s), got ${req.args.length}`);
|
|
85
|
+
}
|
|
86
|
+
if (req.runner.type === 'some') {
|
|
87
|
+
const refused = overrideRefusal(fnObj.runner, req.runner.value, grant);
|
|
88
|
+
if (refused !== null)
|
|
89
|
+
return refused;
|
|
120
90
|
}
|
|
121
91
|
const bodyIr = await storage.objects.read(repoPath, fnObj.bodyIr);
|
|
122
92
|
const runnerValue = req.runner.type === 'some' ? req.runner.value : fnObj.runner;
|
|
123
|
-
const limits =
|
|
93
|
+
const limits = resolveExecuteLimits(req.limits, syncDeadlineMs === undefined ? {} : { syncDeadlineMs });
|
|
124
94
|
const result = await runner.runDetached({
|
|
125
95
|
bodyIr,
|
|
126
|
-
args: req.args
|
|
96
|
+
args: req.args,
|
|
127
97
|
runner: runnerValue,
|
|
128
98
|
limits,
|
|
129
99
|
environment: fnObj.environment.type === 'some' ? fnObj.environment.value : undefined,
|
|
130
100
|
}, { signal, storage, verbose });
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Resolve one-shot args: inline values pass through; dataset paths are
|
|
135
|
-
* resolved + pinned by content hash at launch (objects are immutable, so no
|
|
136
|
-
* lock is needed — snapshot consistency) and handed to the runner by that
|
|
137
|
-
* hash, which it stages as a task input is: never read here, whatever its
|
|
138
|
-
* size.
|
|
139
|
-
*
|
|
140
|
-
* @returns The args, or an `invalid` ExecuteResult if a dataset arg is
|
|
141
|
-
* unassigned.
|
|
142
|
-
*/
|
|
143
|
-
async function resolveOneShotArgs(storage, repoPath, workspace, args) {
|
|
144
|
-
const resolved = [];
|
|
145
|
-
for (let i = 0; i < args.length; i++) {
|
|
146
|
-
const arg = args[i];
|
|
147
|
-
if (arg.type === 'value') {
|
|
148
|
-
resolved.push(arg.value);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
const path = arg.value;
|
|
152
|
-
const { refType, hash } = await workspaceGetDatasetHash(storage, repoPath, workspace, path);
|
|
153
|
-
if (refType !== 'value' || hash === null) {
|
|
154
|
-
return {
|
|
155
|
-
ok: false,
|
|
156
|
-
invalid: invalidResult(`Dataset argument ${i} is not assigned (ref type: ${refType})`),
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
resolved.push({ dataset: hash });
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return { ok: true, args: resolved };
|
|
163
|
-
}
|
|
164
|
-
/** Execute a one-shot request (bodyIr from the request). */
|
|
165
|
-
async function executeOneShot(storage, repoPath, workspace, runner, req, sync, signal, verbose) {
|
|
166
|
-
const resolved = await resolveOneShotArgs(storage, repoPath, workspace, req.args);
|
|
167
|
-
if (!resolved.ok) {
|
|
168
|
-
return resolved.invalid;
|
|
169
|
-
}
|
|
170
|
-
const limits = resolveLimits(req.limits, sync);
|
|
171
|
-
const result = await runner.runDetached({
|
|
172
|
-
bodyIr: req.bodyIr,
|
|
173
|
-
args: resolved.args,
|
|
174
|
-
runner: req.runner,
|
|
175
|
-
limits,
|
|
176
|
-
}, { signal, verbose, storage });
|
|
101
|
+
// A named function reads no dataset: its result names none.
|
|
177
102
|
return detachedToExecuteResult(result);
|
|
178
103
|
}
|
|
179
104
|
// =============================================================================
|
|
@@ -221,35 +146,169 @@ export async function describePackageFunction(storage, repoPath, pkgName, versio
|
|
|
221
146
|
}
|
|
222
147
|
/**
|
|
223
148
|
* Call a named function synchronously: resolve → validate arity → run →
|
|
224
|
-
* 200 ExecuteResult. The
|
|
225
|
-
* caller gets a structured `timed_out` instead of a
|
|
149
|
+
* 200 ExecuteResult. The call's timeout is clamped under the host's sync
|
|
150
|
+
* deadline, so the caller gets a structured `timed_out` instead of a
|
|
151
|
+
* transport cut.
|
|
152
|
+
*
|
|
153
|
+
* @remarks
|
|
154
|
+
* A call that names no runner runs the function on its own, whatever the
|
|
155
|
+
* caller's grant. One that names a runner is refused the `custom` runtime
|
|
156
|
+
* (`invalid`), and a platform package the function's own runner does not
|
|
157
|
+
* load unless the grant is `any` (`permission_denied`, `path` `runner`).
|
|
158
|
+
*
|
|
159
|
+
* @param storage - Storage backend
|
|
160
|
+
* @param repoPath - The repository
|
|
161
|
+
* @param runner - The repository's task runner
|
|
162
|
+
* @param pkgName - The package
|
|
163
|
+
* @param version - Its version
|
|
164
|
+
* @param fnName - The function
|
|
165
|
+
* @param req - The arguments, and any runner and limits the caller names
|
|
166
|
+
* @param verbose - Pass `-v` to a stock runner
|
|
167
|
+
* @param syncDeadlineMs - The host's deadline for a sync call, under its
|
|
168
|
+
* request timeout (default 120 000 ms)
|
|
169
|
+
* @param grant - The caller's one-shot grant, which decides whether its call
|
|
170
|
+
* may give the function a platform package the function does not load:
|
|
171
|
+
* only `any` may (default `platform_free`)
|
|
172
|
+
* @returns The call's result, or the error that stopped it
|
|
226
173
|
*/
|
|
227
|
-
export async function callFunctionSync(storage, repoPath, runner, pkgName, version, fnName, req, verbose) {
|
|
174
|
+
export async function callFunctionSync(storage, repoPath, runner, pkgName, version, fnName, req, verbose, syncDeadlineMs, grant = 'platform_free') {
|
|
228
175
|
try {
|
|
229
176
|
const fnObj = await resolveFunction(storage, repoPath, pkgName, version, fnName);
|
|
230
|
-
const result = await executeFunction(storage, repoPath, runner, fnObj, req,
|
|
177
|
+
const result = await executeFunction(storage, repoPath, runner, fnObj, req, syncDeadlineMs, grant, undefined, verbose);
|
|
231
178
|
return sendSuccess(ExecuteResultType, result);
|
|
232
179
|
}
|
|
233
180
|
catch (err) {
|
|
234
181
|
return sendError(ExecuteResultType, errorToVariant(err));
|
|
235
182
|
}
|
|
236
183
|
}
|
|
237
|
-
// =============================================================================
|
|
238
|
-
// One-shot handlers (workspace-scoped; anonymous caller-supplied IR)
|
|
239
|
-
// =============================================================================
|
|
240
184
|
/**
|
|
241
|
-
*
|
|
242
|
-
*
|
|
185
|
+
* Launch a split call, as a job the client polls; or an explain of one, a job
|
|
186
|
+
* that plans its pieces.
|
|
187
|
+
*
|
|
188
|
+
* @remarks
|
|
189
|
+
* The launch applies the caller's grant, pins the call's dataset arguments and
|
|
190
|
+
* writes what the job runs (e3-core `splitCallPrepare`), then files the job and
|
|
191
|
+
* dispatches it to the compute the store chooses. An explain launches the same
|
|
192
|
+
* way, and its job plans the pieces, which stores them for the run to take up:
|
|
193
|
+
* the request does no more than the launch's small writes. A request found
|
|
194
|
+
* wrong is filed as a job already `completed` with its `invalid` result, so
|
|
195
|
+
* every call's result, whatever it is, comes back through the poll. The job
|
|
196
|
+
* records whether a caller whose grant is `platform_free` may poll it
|
|
197
|
+
* (e3-core `splitCallPlatformFree`).
|
|
198
|
+
*
|
|
199
|
+
* @param storage - Storage backend
|
|
200
|
+
* @param repoPath - Repository identifier
|
|
201
|
+
* @param repo - The repository's name, which the job is filed under
|
|
202
|
+
* @param workspace - The workspace whose datasets the call reads
|
|
203
|
+
* @param request - The call
|
|
204
|
+
* @param grant - What the caller may run: the grant the host's auth gave it
|
|
205
|
+
* @param splitCallStore - Where the job is filed, and dispatched from
|
|
206
|
+
* @param options - The ceilings the call's limits are held to, and whether
|
|
207
|
+
* the job only explains it
|
|
208
|
+
* @returns The response: the job's id, or the error — `permission_denied`
|
|
209
|
+
* (`path` `one-shot`) for a caller whose grant does not run the call
|
|
243
210
|
*/
|
|
244
|
-
export async function
|
|
211
|
+
export async function startSplitCall(storage, repoPath, repo, workspace, request, grant, splitCallStore, options = {}) {
|
|
245
212
|
try {
|
|
246
|
-
|
|
247
|
-
await
|
|
248
|
-
const
|
|
249
|
-
|
|
213
|
+
const { ceilings } = options;
|
|
214
|
+
const launched = await splitCallPrepare(storage, repoPath, workspace, request, { grant, ...(ceilings !== undefined && { ceilings }) });
|
|
215
|
+
const id = randomUUID();
|
|
216
|
+
const filed = {
|
|
217
|
+
repo,
|
|
218
|
+
workspace,
|
|
219
|
+
explain: options.explain ?? false,
|
|
220
|
+
platformFree: splitCallPlatformFree(request, grant),
|
|
221
|
+
createdAt: new Date(),
|
|
222
|
+
};
|
|
223
|
+
if ('outcome' in launched) {
|
|
224
|
+
const limits = resolveJobLimits(request.limits, ceilings);
|
|
225
|
+
await splitCallStore.create(id, {
|
|
226
|
+
...filed,
|
|
227
|
+
task: '',
|
|
228
|
+
inputs: [],
|
|
229
|
+
objects: [],
|
|
230
|
+
then: none,
|
|
231
|
+
limits: { timeoutMs: BigInt(limits.timeoutMs), maxResultBytes: BigInt(limits.maxResultBytes), maxLogBytes: BigInt(limits.maxLogBytes) },
|
|
232
|
+
read: [],
|
|
233
|
+
status: variant('completed', splitCallInvalid(launched)),
|
|
234
|
+
});
|
|
235
|
+
return sendSuccess(PackageJobResponseType, { id });
|
|
236
|
+
}
|
|
237
|
+
await splitCallStore.create(id, {
|
|
238
|
+
...filed,
|
|
239
|
+
task: launched.task,
|
|
240
|
+
inputs: [...launched.inputs],
|
|
241
|
+
objects: launched.objects.map((index) => BigInt(index)),
|
|
242
|
+
then: launched.then === null ? none : some(launched.then),
|
|
243
|
+
limits: {
|
|
244
|
+
timeoutMs: BigInt(launched.limits.timeoutMs),
|
|
245
|
+
maxResultBytes: BigInt(launched.limits.maxResultBytes),
|
|
246
|
+
maxLogBytes: BigInt(launched.limits.maxLogBytes),
|
|
247
|
+
},
|
|
248
|
+
read: launched.read,
|
|
249
|
+
status: variant('processing', none),
|
|
250
|
+
});
|
|
251
|
+
await splitCallStore.execute(id, repo);
|
|
252
|
+
return sendSuccess(PackageJobResponseType, { id });
|
|
250
253
|
}
|
|
251
254
|
catch (err) {
|
|
252
|
-
return sendError(
|
|
255
|
+
return sendError(PackageJobResponseType, errorToVariant(err));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* A split call's status: how far its job has got, its result, the pieces an
|
|
260
|
+
* explain planned, or why e3 could not run it.
|
|
261
|
+
*
|
|
262
|
+
* @remarks
|
|
263
|
+
* A job's record holds hashes: a finished call's value is read from the store
|
|
264
|
+
* and answered inline up to the call's `maxResultBytes`, a collection spliced,
|
|
265
|
+
* and over that the result is `too_large` and names the assembled output, which
|
|
266
|
+
* the caller reads by its hash.
|
|
267
|
+
*
|
|
268
|
+
* A caller whose grant is `none` polls no job, and one whose grant is
|
|
269
|
+
* `platform_free` only a job its record lets it (`platformFree`): a result
|
|
270
|
+
* persists and is found by its id, so a reader never reads that of a call only
|
|
271
|
+
* an elevated grant could run.
|
|
272
|
+
*
|
|
273
|
+
* @param storage - Storage backend
|
|
274
|
+
* @param repoPath - Repository identifier
|
|
275
|
+
* @param splitCallStore - Where the job is filed
|
|
276
|
+
* @param repo - The repository's name
|
|
277
|
+
* @param workspace - Workspace name
|
|
278
|
+
* @param id - The job's id
|
|
279
|
+
* @param grant - What the caller may run: the grant the host's auth gave it
|
|
280
|
+
* @returns The response: the status; or the error — `permission_denied`
|
|
281
|
+
* (`path` `one-shot`) for a caller whose grant does not poll the job, and
|
|
282
|
+
* `internal` when this workspace launched no such job
|
|
283
|
+
*/
|
|
284
|
+
export async function getSplitCallStatus(storage, repoPath, splitCallStore, repo, workspace, id, grant) {
|
|
285
|
+
try {
|
|
286
|
+
if (grant === 'none')
|
|
287
|
+
throw new PermissionDeniedError('one-shot');
|
|
288
|
+
const job = await splitCallStore.get(id);
|
|
289
|
+
if (job === null || job.repo !== repo || job.workspace !== workspace) {
|
|
290
|
+
return sendError(SplitCallStatusType, variant('internal', {
|
|
291
|
+
message: `workspace '${workspace}' has no split call '${id}'`,
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
if (grant === 'platform_free' && !job.platformFree)
|
|
295
|
+
throw new PermissionDeniedError('one-shot');
|
|
296
|
+
const status = job.status;
|
|
297
|
+
switch (status.type) {
|
|
298
|
+
case 'processing':
|
|
299
|
+
return sendSuccess(SplitCallStatusType, variant('processing', status.value));
|
|
300
|
+
case 'failed':
|
|
301
|
+
return sendSuccess(SplitCallStatusType, variant('failed', status.value));
|
|
302
|
+
case 'planned':
|
|
303
|
+
return sendSuccess(SplitCallStatusType, variant('planned', status.value));
|
|
304
|
+
case 'completed': {
|
|
305
|
+
const result = await splitCallResult(storage, repoPath, status.value, job.read, Number(job.limits.maxResultBytes));
|
|
306
|
+
return sendSuccess(SplitCallStatusType, variant('completed', { result, output: status.value.output }));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
return sendError(SplitCallStatusType, errorToVariant(err));
|
|
253
312
|
}
|
|
254
313
|
}
|
|
255
314
|
//# sourceMappingURL=functions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/handlers/functions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/handlers/functions.ts"],"names":[],"mappings":"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"}
|