deepline 0.3.128 → 0.3.129
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/dist/bundling-sources/sdk/src/client.ts +34 -9
- package/dist/bundling-sources/sdk/src/http.ts +22 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +22 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +265 -2
- package/dist/bundling-sources/shared_libs/play-runtime/bounded-batch-function.ts +682 -0
- package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +21 -5
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5390 -1732
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +107 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +229 -7
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +25 -4
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-capacity.ts +71 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +694 -28
- package/dist/bundling-sources/shared_libs/play-runtime/egress-bandwidth-probe.ts +167 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +103 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-receipt-output-reference.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-response-size.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +425 -71
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +210 -32
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +27 -13
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +19 -6
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +61 -2
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +33 -1
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +42 -1
- package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +11 -11
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +49 -16
- package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +1653 -98
- package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +807 -0
- package/dist/bundling-sources/shared_libs/play-runtime/memory-pressure-signal.ts +138 -0
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +85 -3
- package/dist/bundling-sources/shared_libs/play-runtime/persistence-latch.ts +60 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +46 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +70 -27
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/adaptive-provider-capacity-controller.ts +192 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/epoch-aimd-rate-controller.ts +194 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/fixture-capacity-simulator.ts +220 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/gradient2-concurrency-controller.ts +214 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-capacity-policy.ts +43 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-concurrency-policy.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-rate-policy.ts +95 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-throttle-classifier.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +1535 -11
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +49 -2
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +55 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +221 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +339 -29
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +28 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +192 -165
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +90 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +281 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +27 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +11 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api-compression.ts +276 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +723 -115
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +98 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +3 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +41 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +448 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-map-row-feed.ts +215 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +161 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-value.ts +184 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +607 -121
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-placement-policy.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-writer.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +15 -2
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +71 -14
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +288 -119
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +8 -6
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +28 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/canonical-integration-operation-store.ts +179 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +80 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +31 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-store-contract.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-reference.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-retirement.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-storage.ts +420 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +41 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +134 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +1657 -95
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +885 -73
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-completion-coalescer.ts +452 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +601 -42
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-value-storage.ts +371 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +86 -7
- package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +153 -22
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +188 -38
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +28 -13
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +44 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +56 -4
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +16 -10
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +4 -1
- package/dist/cli/index.js +250 -38
- package/dist/cli/index.mjs +250 -38
- package/dist/{compiler-manifest-DfSnbCTW.d.mts → compiler-manifest-BIqRyj5m.d.mts} +1 -1
- package/dist/{compiler-manifest-DfSnbCTW.d.ts → compiler-manifest-BIqRyj5m.d.ts} +1 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +231 -35
- package/dist/index.mjs +231 -35
- package/dist/install-integrity.json +31 -2
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +65 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PlayRunnerEvent } from '../protocol';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from '../runtime-contract';
|
|
2
|
+
import { jsonByteLengthUpTo } from '../output-size-limits';
|
|
3
|
+
import { RUNTIME_RUNNER_TERMINAL_PROGRESS_MAX_EVENTS } from '../runtime-contract';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Push-execution live progress channel (runs INSIDE the Daytona sandbox).
|
|
@@ -31,6 +30,11 @@ export const RUNNER_PROGRESS_PUSH_STOP_TIMEOUT_MS = 5_000;
|
|
|
31
30
|
const APP_RUNTIME_COMPAT_PATH = '/api/v2/plays/runtime';
|
|
32
31
|
|
|
33
32
|
export interface RunnerProgressPusher {
|
|
33
|
+
snapshot: () => {
|
|
34
|
+
retainedBytes: number;
|
|
35
|
+
retainedEvents: number;
|
|
36
|
+
omittedEvents: number;
|
|
37
|
+
};
|
|
34
38
|
/** Enqueue one progress event for the next batch flush. */
|
|
35
39
|
enqueue: (event: PlayRunnerEvent) => void;
|
|
36
40
|
/** Stop delivery and return all observations not known to be delivered. */
|
|
@@ -100,19 +104,20 @@ async function defaultSendBatch(input: {
|
|
|
100
104
|
await response.text().catch(() => '');
|
|
101
105
|
}
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
export const RUNNER_PROGRESS_MAX_RETAINED_BYTES = 2 * 1024 * 1024;
|
|
108
|
+
export const RUNNER_PROGRESS_MAX_RETAINED_EVENTS = 4_000;
|
|
109
|
+
const RUNNER_PROGRESS_BATCH_MAX_BYTES = 128 * 1024;
|
|
110
|
+
const RUNNER_PROGRESS_SEND_TIMEOUT_MS = 5_000;
|
|
111
|
+
|
|
112
|
+
type PendingEvent = {
|
|
113
|
+
event: PlayRunnerEvent;
|
|
114
|
+
bytes: number;
|
|
115
|
+
logOffset: number;
|
|
107
116
|
};
|
|
108
117
|
|
|
109
|
-
function
|
|
110
|
-
return
|
|
111
|
-
|
|
112
|
-
event.type === 'log' && event.source !== 'worker' && event.line.length > 0
|
|
113
|
-
? count + 1
|
|
114
|
-
: count,
|
|
115
|
-
0,
|
|
118
|
+
function isDurableLog(event: PlayRunnerEvent): boolean {
|
|
119
|
+
return (
|
|
120
|
+
event.type === 'log' && event.source !== 'worker' && event.line.length > 0
|
|
116
121
|
);
|
|
117
122
|
}
|
|
118
123
|
|
|
@@ -120,202 +125,224 @@ export function createRunnerProgressPusher(
|
|
|
120
125
|
options: RunnerProgressPushOptions,
|
|
121
126
|
): RunnerProgressPusher {
|
|
122
127
|
const sendBatch = options.sendBatch ?? defaultSendBatch;
|
|
128
|
+
const warn =
|
|
129
|
+
options.warn ??
|
|
130
|
+
((message, detail) =>
|
|
131
|
+
console.warn('[play-runner.progress-push]', message, detail));
|
|
123
132
|
const setIntervalImpl =
|
|
124
|
-
options.setIntervalImpl ??
|
|
125
|
-
((fn, ms) => setInterval(fn, ms) as unknown as { unref?: () => void });
|
|
133
|
+
options.setIntervalImpl ?? ((fn, ms) => setInterval(fn, ms));
|
|
126
134
|
const clearIntervalImpl =
|
|
127
135
|
options.clearIntervalImpl ??
|
|
128
136
|
((handle) => clearInterval(handle as ReturnType<typeof setInterval>));
|
|
129
|
-
const warn =
|
|
130
|
-
options.warn ??
|
|
131
|
-
((message, detail) =>
|
|
132
|
-
console.warn(`[play-runner.progress-push] ${message}`, detail));
|
|
133
|
-
const batchMs = options.batchMs ?? RUNNER_PROGRESS_PUSH_BATCH_MS;
|
|
134
137
|
const maxBatch = options.maxBatch ?? RUNNER_PROGRESS_PUSH_MAX_BATCH;
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
// that failed before that boundary so the terminal request can
|
|
142
|
-
// carry it to whichever healthy replica Fly selects next.
|
|
143
|
-
const failedBatches: ProgressBatch[] = [];
|
|
144
|
-
const activeBatches = new Map<AbortController, ProgressBatch>();
|
|
145
|
-
let nextBatchLiveLogOffset = 0;
|
|
146
|
-
let deliveryBroken = false;
|
|
138
|
+
const pending: PendingEvent[] = [];
|
|
139
|
+
let active: PendingEvent[] = [];
|
|
140
|
+
let failed: PendingEvent[] = [];
|
|
141
|
+
let retainedBytes = 0;
|
|
142
|
+
let nextLogOffset = 0;
|
|
143
|
+
let omittedEvents = 0;
|
|
147
144
|
let stopped = false;
|
|
148
145
|
let abandoned = false;
|
|
149
|
-
let
|
|
150
|
-
let
|
|
151
|
-
let
|
|
146
|
+
let deliveryBroken = false;
|
|
147
|
+
let controller: AbortController | null = null;
|
|
148
|
+
let inFlight: Promise<void> | null = null;
|
|
149
|
+
|
|
150
|
+
const forget = (entries: PendingEvent[]) => {
|
|
151
|
+
for (const entry of entries) retainedBytes -= entry.bytes;
|
|
152
|
+
};
|
|
153
|
+
const enforceBudget = () => {
|
|
154
|
+
let dropped = 0;
|
|
155
|
+
// Never evict the active request: its ambiguous outcome must remain owned.
|
|
156
|
+
// Evict only a prefix, preserving absolute log offsets for the existing
|
|
157
|
+
// durable ingestion gap marker.
|
|
158
|
+
while (
|
|
159
|
+
retainedBytes > RUNNER_PROGRESS_MAX_RETAINED_BYTES ||
|
|
160
|
+
active.length + failed.length + pending.length >
|
|
161
|
+
RUNNER_PROGRESS_MAX_RETAINED_EVENTS
|
|
162
|
+
) {
|
|
163
|
+
const entry = failed.shift() ?? pending.shift();
|
|
164
|
+
if (!entry) break;
|
|
165
|
+
retainedBytes -= entry.bytes;
|
|
166
|
+
dropped++;
|
|
167
|
+
}
|
|
168
|
+
if (dropped) {
|
|
169
|
+
omittedEvents += dropped;
|
|
170
|
+
if (omittedEvents === dropped)
|
|
171
|
+
warn('progress_buffer_limited', {
|
|
172
|
+
runId: options.runId,
|
|
173
|
+
omittedEvents,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
};
|
|
152
177
|
|
|
153
178
|
const flush = (): Promise<void> => {
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
return
|
|
179
|
+
if (inFlight) return inFlight;
|
|
180
|
+
if (abandoned || deliveryBroken || !pending.length)
|
|
181
|
+
return Promise.resolve();
|
|
182
|
+
let bytes = 0;
|
|
183
|
+
let count = 0;
|
|
184
|
+
while (count < pending.length && count < maxBatch) {
|
|
185
|
+
const next = pending[count]!;
|
|
186
|
+
const previous = pending[count - 1];
|
|
187
|
+
if (
|
|
188
|
+
previous &&
|
|
189
|
+
next.logOffset !==
|
|
190
|
+
previous.logOffset + Number(isDurableLog(previous.event))
|
|
191
|
+
)
|
|
192
|
+
break;
|
|
193
|
+
if (count && bytes + next.bytes > RUNNER_PROGRESS_BATCH_MAX_BYTES) break;
|
|
194
|
+
bytes += next.bytes;
|
|
195
|
+
count++;
|
|
157
196
|
}
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.then(async () => {
|
|
169
|
-
// stop() can time out while this batch waits behind an earlier upload.
|
|
170
|
-
// Do not start it after the authoritative terminal has been emitted.
|
|
171
|
-
if (abandoned) return;
|
|
172
|
-
if (deliveryBroken) {
|
|
173
|
-
const queuedIndex = queuedBatches.indexOf(batch);
|
|
174
|
-
if (queuedIndex >= 0) queuedBatches.splice(queuedIndex, 1);
|
|
175
|
-
failedBatches.push(batch);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const controller = new AbortController();
|
|
179
|
-
const queuedIndex = queuedBatches.indexOf(batch);
|
|
180
|
-
if (queuedIndex >= 0) queuedBatches.splice(queuedIndex, 1);
|
|
181
|
-
activeBatches.set(controller, batch);
|
|
182
|
-
try {
|
|
183
|
-
await sendBatch({
|
|
197
|
+
active = pending.splice(0, count);
|
|
198
|
+
const batch = active;
|
|
199
|
+
const requestController = new AbortController();
|
|
200
|
+
controller = requestController;
|
|
201
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
202
|
+
inFlight = Promise.resolve().then(async () => {
|
|
203
|
+
if (abandoned) return;
|
|
204
|
+
try {
|
|
205
|
+
await Promise.race([
|
|
206
|
+
sendBatch({
|
|
184
207
|
gatewayBaseUrl: options.gatewayBaseUrl,
|
|
185
208
|
executorToken: options.executorToken,
|
|
186
209
|
runId: options.runId,
|
|
187
210
|
playName: options.playName,
|
|
188
|
-
events: batch.
|
|
189
|
-
liveLogOffset: batch
|
|
190
|
-
signal:
|
|
211
|
+
events: batch.map(({ event }) => event),
|
|
212
|
+
liveLogOffset: batch[0]!.logOffset,
|
|
213
|
+
signal: requestController.signal,
|
|
214
|
+
}),
|
|
215
|
+
new Promise<never>((_, reject) => {
|
|
216
|
+
timeout = setTimeout(() => {
|
|
217
|
+
requestController.abort();
|
|
218
|
+
reject(new Error('Progress delivery timed out.'));
|
|
219
|
+
}, RUNNER_PROGRESS_SEND_TIMEOUT_MS);
|
|
220
|
+
}),
|
|
221
|
+
]);
|
|
222
|
+
if (!abandoned) forget(batch);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (!abandoned) {
|
|
225
|
+
failed = batch;
|
|
226
|
+
deliveryBroken = true;
|
|
227
|
+
warn('batch_failed', {
|
|
228
|
+
runId: options.runId,
|
|
229
|
+
count: batch.length,
|
|
230
|
+
error: error instanceof Error ? error.message : String(error),
|
|
191
231
|
});
|
|
192
|
-
} catch (error) {
|
|
193
|
-
if (!abandoned) {
|
|
194
|
-
failedBatches.push(batch);
|
|
195
|
-
// Offsets are positional. After one unknown delivery outcome, keep
|
|
196
|
-
// the remaining contiguous suffix for the terminal request rather
|
|
197
|
-
// than sending holes that another replica could misinterpret.
|
|
198
|
-
deliveryBroken = true;
|
|
199
|
-
}
|
|
200
|
-
if (!suppressWarnings) {
|
|
201
|
-
warn('batch_failed', {
|
|
202
|
-
runId: options.runId,
|
|
203
|
-
count: batch.events.length,
|
|
204
|
-
error: error instanceof Error ? error.message : String(error),
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
} finally {
|
|
208
|
-
activeBatches.delete(controller);
|
|
209
232
|
}
|
|
210
|
-
}
|
|
233
|
+
} finally {
|
|
234
|
+
if (timeout) clearTimeout(timeout);
|
|
235
|
+
active = [];
|
|
236
|
+
controller = null;
|
|
237
|
+
inFlight = null;
|
|
238
|
+
enforceBudget();
|
|
239
|
+
if (!stopped && pending.length >= maxBatch) void flush();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
211
242
|
return inFlight;
|
|
212
243
|
};
|
|
213
|
-
|
|
214
|
-
handle = setIntervalImpl(() => {
|
|
244
|
+
const timer = setIntervalImpl(() => {
|
|
215
245
|
void flush();
|
|
216
|
-
}, batchMs);
|
|
217
|
-
|
|
246
|
+
}, options.batchMs ?? RUNNER_PROGRESS_PUSH_BATCH_MS);
|
|
247
|
+
timer.unref?.();
|
|
218
248
|
|
|
249
|
+
const abandon = () => {
|
|
250
|
+
abandoned = true;
|
|
251
|
+
controller?.abort();
|
|
252
|
+
pending.length = 0;
|
|
253
|
+
failed = [];
|
|
254
|
+
active = [];
|
|
255
|
+
retainedBytes = 0;
|
|
256
|
+
};
|
|
219
257
|
return {
|
|
220
258
|
enqueue(event) {
|
|
221
259
|
if (stopped) return;
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
|
|
260
|
+
const logOffset = nextLogOffset;
|
|
261
|
+
if (isDurableLog(event)) nextLogOffset++;
|
|
262
|
+
// Short-circuit size inspection avoids serializing an arbitrarily large
|
|
263
|
+
// row-update merely to decide it cannot fit observability.
|
|
264
|
+
const measured = jsonByteLengthUpTo(
|
|
265
|
+
event,
|
|
266
|
+
RUNNER_PROGRESS_BATCH_MAX_BYTES,
|
|
267
|
+
);
|
|
268
|
+
if (measured.exceeded) {
|
|
269
|
+
omittedEvents++;
|
|
270
|
+
if (omittedEvents === 1)
|
|
271
|
+
warn('progress_event_too_large', { runId: options.runId });
|
|
272
|
+
return;
|
|
225
273
|
}
|
|
274
|
+
const bytes = measured.bytes;
|
|
275
|
+
pending.push({ event, bytes, logOffset });
|
|
276
|
+
retainedBytes += bytes;
|
|
277
|
+
enforceBudget();
|
|
278
|
+
if (pending.length >= maxBatch) void flush();
|
|
279
|
+
},
|
|
280
|
+
snapshot() {
|
|
281
|
+
return {
|
|
282
|
+
retainedBytes,
|
|
283
|
+
retainedEvents: active.length + failed.length + pending.length,
|
|
284
|
+
omittedEvents,
|
|
285
|
+
};
|
|
226
286
|
},
|
|
227
287
|
sealForTerminal() {
|
|
228
|
-
if (stopped) return { events: [], liveLogOffset:
|
|
288
|
+
if (stopped) return { events: [], liveLogOffset: nextLogOffset };
|
|
229
289
|
stopped = true;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
// Preserve every batch removed from `pending`, including batches queued
|
|
235
|
-
// behind an earlier upload. The terminal request is the final owner of
|
|
236
|
-
// these observations; do not drop a burst merely because it has not yet
|
|
237
|
-
// acquired an AbortController.
|
|
238
|
-
const retainedBatches: ProgressBatch[] = [
|
|
239
|
-
...failedBatches,
|
|
240
|
-
...activeBatches.values(),
|
|
241
|
-
...queuedBatches,
|
|
242
|
-
...(pending.length
|
|
243
|
-
? [{ events: [...pending], liveLogOffset: nextBatchLiveLogOffset }]
|
|
244
|
-
: []),
|
|
245
|
-
];
|
|
246
|
-
const unboundedTail = retainedBatches.flatMap((batch) => batch.events);
|
|
247
|
-
const droppedEvents = Math.max(
|
|
290
|
+
clearIntervalImpl(timer);
|
|
291
|
+
const retained = [...failed, ...active, ...pending];
|
|
292
|
+
let start = Math.max(
|
|
248
293
|
0,
|
|
249
|
-
|
|
250
|
-
);
|
|
251
|
-
const droppedPrefix = unboundedTail.slice(0, droppedEvents);
|
|
252
|
-
const tail = unboundedTail.slice(
|
|
253
|
-
-RUNTIME_RUNNER_TERMINAL_PROGRESS_MAX_EVENTS,
|
|
294
|
+
retained.length - RUNTIME_RUNNER_TERMINAL_PROGRESS_MAX_EVENTS,
|
|
254
295
|
);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
296
|
+
for (let index = start + 1; index < retained.length; index++) {
|
|
297
|
+
const previous = retained[index - 1]!;
|
|
298
|
+
if (
|
|
299
|
+
retained[index]!.logOffset !==
|
|
300
|
+
previous.logOffset + Number(isDurableLog(previous.event))
|
|
301
|
+
)
|
|
302
|
+
start = index;
|
|
303
|
+
}
|
|
304
|
+
const tail = retained.slice(start);
|
|
305
|
+
if (tail.length < retained.length || omittedEvents)
|
|
259
306
|
warn('terminal_tail_truncated', {
|
|
260
307
|
runId: options.runId,
|
|
261
308
|
retainedEvents: tail.length,
|
|
262
|
-
droppedEvents:
|
|
309
|
+
droppedEvents: retained.length - tail.length + omittedEvents,
|
|
263
310
|
});
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
for (const controller of activeBatches.keys()) controller.abort();
|
|
271
|
-
return { events: tail, liveLogOffset };
|
|
311
|
+
const result = {
|
|
312
|
+
events: tail.map(({ event }) => event),
|
|
313
|
+
liveLogOffset: tail[0]?.logOffset ?? nextLogOffset,
|
|
314
|
+
};
|
|
315
|
+
abandon();
|
|
316
|
+
return result;
|
|
272
317
|
},
|
|
273
318
|
async stop() {
|
|
274
319
|
if (stopped) return;
|
|
275
320
|
stopped = true;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
handle = null;
|
|
279
|
-
}
|
|
321
|
+
clearIntervalImpl(timer);
|
|
322
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
280
323
|
const drain = async () => {
|
|
281
|
-
|
|
282
|
-
while (pending.length > 0 && !deliveryBroken) {
|
|
324
|
+
while (!abandoned && !deliveryBroken && (pending.length || inFlight))
|
|
283
325
|
await flush();
|
|
284
|
-
}
|
|
285
|
-
await inFlight.catch(() => {});
|
|
286
|
-
if (deliveryBroken) pending.length = 0;
|
|
287
326
|
};
|
|
288
|
-
let stopTimeoutHandle: ReturnType<typeof setTimeout> | null = null;
|
|
289
327
|
const outcome = await Promise.race([
|
|
290
|
-
drain().then(() => 'drained'
|
|
291
|
-
new Promise<
|
|
292
|
-
|
|
328
|
+
drain().then(() => 'drained'),
|
|
329
|
+
new Promise<string>((resolve) => {
|
|
330
|
+
timeout = setTimeout(
|
|
293
331
|
() => resolve('timed_out'),
|
|
294
|
-
stopTimeoutMs,
|
|
332
|
+
options.stopTimeoutMs ?? RUNNER_PROGRESS_PUSH_STOP_TIMEOUT_MS,
|
|
295
333
|
);
|
|
296
334
|
}),
|
|
297
335
|
]);
|
|
298
|
-
if (
|
|
299
|
-
if (outcome === '
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const inFlightEvents = [...activeBatches.values()].reduce(
|
|
309
|
-
(sum, batch) => sum + batch.events.length,
|
|
310
|
-
0,
|
|
311
|
-
);
|
|
312
|
-
for (const controller of activeBatches.keys()) controller.abort();
|
|
313
|
-
warn('drain_timed_out', {
|
|
314
|
-
runId: options.runId,
|
|
315
|
-
timeoutMs: stopTimeoutMs,
|
|
316
|
-
pendingEvents,
|
|
317
|
-
inFlightEvents,
|
|
318
|
-
});
|
|
336
|
+
if (timeout) clearTimeout(timeout);
|
|
337
|
+
if (outcome === 'timed_out')
|
|
338
|
+
warn('drain_timed_out', {
|
|
339
|
+
runId: options.runId,
|
|
340
|
+
timeoutMs:
|
|
341
|
+
options.stopTimeoutMs ?? RUNNER_PROGRESS_PUSH_STOP_TIMEOUT_MS,
|
|
342
|
+
pendingEvents: pending.length,
|
|
343
|
+
inFlightEvents: active.length,
|
|
344
|
+
});
|
|
345
|
+
abandon();
|
|
319
346
|
},
|
|
320
347
|
};
|
|
321
348
|
}
|
package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts
CHANGED
|
@@ -657,6 +657,12 @@ async function acquireOneShotDaytonaSandbox(input: {
|
|
|
657
657
|
createRetriedOneShotDaytonaSandbox(input),
|
|
658
658
|
)
|
|
659
659
|
: await createRetriedOneShotDaytonaSandbox(input);
|
|
660
|
+
// The runner's egress probe measures the sandbox-to-estate round trip; the
|
|
661
|
+
// sandbox's target names the region that round trip crosses.
|
|
662
|
+
console.info('[play-runner.daytona.sandbox_acquired]', {
|
|
663
|
+
sandboxId: result.sandbox.id,
|
|
664
|
+
target: (result.sandbox as { target?: unknown }).target ?? null,
|
|
665
|
+
});
|
|
660
666
|
const granted = {
|
|
661
667
|
cpu: result.sandbox.cpu,
|
|
662
668
|
memoryGiB: result.sandbox.memory,
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
} from '../../output-size-limits';
|
|
25
25
|
import {
|
|
26
26
|
RUNTIME_SANDBOX_KILLED_MESSAGE,
|
|
27
|
+
RUNTIME_SANDBOX_MEMORY_ABORT_CODE,
|
|
28
|
+
RUNTIME_SANDBOX_MEMORY_ABORT_MESSAGE,
|
|
27
29
|
RUNTIME_SANDBOX_OOM_MESSAGE,
|
|
28
30
|
} from '../../run-failure';
|
|
29
31
|
import {
|
|
@@ -37,7 +39,11 @@ import type {
|
|
|
37
39
|
DaytonaSandbox,
|
|
38
40
|
DaytonaStageEmitter,
|
|
39
41
|
} from './daytona-lifecycle';
|
|
40
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
buildDaytonaRuntimeWatchdogSource,
|
|
44
|
+
PLAY_RUNNER_UV_THREADPOOL_SIZE,
|
|
45
|
+
RUNTIME_SANDBOX_MEMORY_ABORT_REASON,
|
|
46
|
+
} from './daytona-runtime-watchdog';
|
|
41
47
|
|
|
42
48
|
type DaytonaRemoteRuntimeContext = PlayRunnerExecutionConfig['context'];
|
|
43
49
|
|
|
@@ -51,6 +57,12 @@ type DaytonaRemoteRuntimeContext = PlayRunnerExecutionConfig['context'];
|
|
|
51
57
|
*/
|
|
52
58
|
export const DAYTONA_CRASH_PUSHER_POST_EVENT_DIAGNOSTIC_HEADROOM_BYTES =
|
|
53
59
|
RUNNER_POST_TERMINAL_DIAGNOSTIC_MAX_BYTES;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Ledger evidence carried on a memory-abort cause. The ledger is diagnostic,
|
|
63
|
+
* not the terminal itself, so it is bounded well below the terminal envelope.
|
|
64
|
+
*/
|
|
65
|
+
export const DAYTONA_CRASH_PUSHER_MEMORY_LEDGER_MAX_BYTES = 8 * 1024;
|
|
54
66
|
export const DAYTONA_CRASH_PUSHER_OUTPUT_TAIL_MAX_BYTES =
|
|
55
67
|
RUNNER_TERMINAL_PUSH_MAX_BODY_BYTES +
|
|
56
68
|
DAYTONA_CRASH_PUSHER_POST_EVENT_DIAGNOSTIC_HEADROOM_BYTES;
|
|
@@ -68,6 +80,8 @@ export type StagedDaytonaPayload = {
|
|
|
68
80
|
|
|
69
81
|
export type RemoteRunnerPayloadSandbox = {
|
|
70
82
|
id: string;
|
|
83
|
+
/** Daytona target (region) the sandbox runs in, when the provider reports it. */
|
|
84
|
+
target?: string;
|
|
71
85
|
uploadFile(content: Buffer, path: string): Promise<void>;
|
|
72
86
|
};
|
|
73
87
|
|
|
@@ -255,6 +269,48 @@ function watchdogObservedChildSigkill() {
|
|
|
255
269
|
return false;
|
|
256
270
|
}
|
|
257
271
|
|
|
272
|
+
// The watchdog stopped the runner at the memory abort threshold. Its
|
|
273
|
+
// diagnostic is the only place the observed usage/limit and the runtime's byte
|
|
274
|
+
// ledger survive the child's death, so the terminal is synthesized from it.
|
|
275
|
+
function watchdogMemoryAbortDiagnostic() {
|
|
276
|
+
try {
|
|
277
|
+
if (!terminationDiagnosticPath) return null;
|
|
278
|
+
const diagnostic = JSON.parse(
|
|
279
|
+
fs.readFileSync(terminationDiagnosticPath, 'utf8'),
|
|
280
|
+
);
|
|
281
|
+
if (
|
|
282
|
+
diagnostic &&
|
|
283
|
+
diagnostic.schemaVersion === 1 &&
|
|
284
|
+
diagnostic.reason === ${JSON.stringify(RUNTIME_SANDBOX_MEMORY_ABORT_REASON)}
|
|
285
|
+
) {
|
|
286
|
+
return diagnostic;
|
|
287
|
+
}
|
|
288
|
+
} catch {}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function memoryAbortCause(diagnostic) {
|
|
293
|
+
const parts = [
|
|
294
|
+
${JSON.stringify(`${RUNTIME_SANDBOX_MEMORY_ABORT_CODE}: ${RUNTIME_SANDBOX_MEMORY_ABORT_MESSAGE}`)},
|
|
295
|
+
'usage=' + String(diagnostic.memoryUsageBytes),
|
|
296
|
+
'limit=' + String(diagnostic.memoryLimitBytes),
|
|
297
|
+
'ratio=' + String(diagnostic.memoryUsageRatio),
|
|
298
|
+
'source=' + String(diagnostic.memorySource),
|
|
299
|
+
];
|
|
300
|
+
if (diagnostic.memoryLedger !== null && diagnostic.memoryLedger !== undefined) {
|
|
301
|
+
try {
|
|
302
|
+
parts.push(
|
|
303
|
+
'ledger=' +
|
|
304
|
+
truncateUtf8(
|
|
305
|
+
JSON.stringify(diagnostic.memoryLedger),
|
|
306
|
+
${DAYTONA_CRASH_PUSHER_MEMORY_LEDGER_MAX_BYTES},
|
|
307
|
+
),
|
|
308
|
+
);
|
|
309
|
+
} catch {}
|
|
310
|
+
}
|
|
311
|
+
return parts.join(' ');
|
|
312
|
+
}
|
|
313
|
+
|
|
258
314
|
function terminalResultForTransport(result) {
|
|
259
315
|
if (
|
|
260
316
|
result &&
|
|
@@ -312,10 +368,15 @@ async function main() {
|
|
|
312
368
|
// runner child's signal. Read the watchdog's strict marker so a child
|
|
313
369
|
// SIGKILL does not collapse into the wrapper's generic exit code 1.
|
|
314
370
|
const sandboxKilled = exitCode === 137 || watchdogObservedChildSigkill();
|
|
371
|
+
const memoryAbort = watchdogMemoryAbortDiagnostic();
|
|
315
372
|
const sandboxOom =
|
|
316
|
-
|
|
373
|
+
!memoryAbort &&
|
|
374
|
+
sandboxKilled &&
|
|
375
|
+
(outputHasExplicitOomSignature() || cgroupOomKillObserved());
|
|
317
376
|
const synthesizedError = runtimeLimitExceeded
|
|
318
377
|
? 'RUNTIME_LIMIT_EXCEEDED: ' + ${JSON.stringify(runtimeLimitMessage)}
|
|
378
|
+
: memoryAbort
|
|
379
|
+
? memoryAbortCause(memoryAbort)
|
|
319
380
|
: sandboxOom
|
|
320
381
|
? 'RUNTIME_SANDBOX_OOM: ' + ${JSON.stringify(RUNTIME_SANDBOX_OOM_MESSAGE)}
|
|
321
382
|
: sandboxKilled
|
|
@@ -336,6 +397,15 @@ async function main() {
|
|
|
336
397
|
cause: synthesizedError,
|
|
337
398
|
}]
|
|
338
399
|
: undefined,
|
|
400
|
+
...(memoryAbort && !runtimeLimitExceeded
|
|
401
|
+
? { errors: [{
|
|
402
|
+
code: ${JSON.stringify(RUNTIME_SANDBOX_MEMORY_ABORT_CODE)},
|
|
403
|
+
phase: 'infrastructure',
|
|
404
|
+
message: ${JSON.stringify(RUNTIME_SANDBOX_MEMORY_ABORT_MESSAGE)},
|
|
405
|
+
retryable: false,
|
|
406
|
+
cause: synthesizedError,
|
|
407
|
+
}] }
|
|
408
|
+
: {}),
|
|
339
409
|
...(sandboxOom
|
|
340
410
|
? { errors: [{
|
|
341
411
|
code: 'RUNTIME_SANDBOX_OOM',
|
|
@@ -345,7 +415,7 @@ async function main() {
|
|
|
345
415
|
cause: synthesizedError,
|
|
346
416
|
}] }
|
|
347
417
|
: {}),
|
|
348
|
-
...(sandboxKilled && !sandboxOom
|
|
418
|
+
...(sandboxKilled && !sandboxOom && !memoryAbort
|
|
349
419
|
? { errors: [{
|
|
350
420
|
code: 'RUNTIME_SANDBOX_KILLED',
|
|
351
421
|
phase: 'infrastructure',
|
|
@@ -590,6 +660,8 @@ export async function stageRunnerPayload(input: {
|
|
|
590
660
|
const runtimeCompletedPath = `${workDir}/deepline-play-runtime-completed-${randomUUID()}.json`;
|
|
591
661
|
const runtimeLimitMarkerPath = `${workDir}/deepline-play-runtime-limit-${randomUUID()}.txt`;
|
|
592
662
|
const terminationDiagnosticPath = `${workDir}/deepline-play-termination-${randomUUID()}.json`;
|
|
663
|
+
const memoryLedgerPath = `${workDir}/deepline-play-memory-ledger-${randomUUID()}.json`;
|
|
664
|
+
const memoryPressurePath = `${workDir}/deepline-play-memory-pressure-${randomUUID()}.json`;
|
|
593
665
|
const progressEventPath = `${workDir}/deepline-play-progress-${randomUUID()}.jsonl`;
|
|
594
666
|
const startupDiagnosticPath = `${workDir}/deepline-play-startup-${randomUUID()}.json`;
|
|
595
667
|
const runnerTraceEnv =
|
|
@@ -597,6 +669,13 @@ export async function stageRunnerPayload(input: {
|
|
|
597
669
|
? 'DEEPLINE_RUNTIME_RECEIPT_TRACE=1 '
|
|
598
670
|
: '';
|
|
599
671
|
const runtimeReliabilityEnv = runtimeReliabilityEnvironmentPrefix();
|
|
672
|
+
// The runner's egress probe prints this next to its round-trip timings so
|
|
673
|
+
// a slow sandbox-to-estate path can be read against the region it crosses.
|
|
674
|
+
const sandboxTarget = input.sandbox.target;
|
|
675
|
+
const sandboxTargetEnv =
|
|
676
|
+
typeof sandboxTarget === 'string' && sandboxTarget.trim()
|
|
677
|
+
? `DEEPLINE_SANDBOX_TARGET=${shellQuote(sandboxTarget.trim())} `
|
|
678
|
+
: '';
|
|
600
679
|
const watchedRunnerCommand = [
|
|
601
680
|
'node',
|
|
602
681
|
'-e',
|
|
@@ -610,6 +689,8 @@ export async function stageRunnerPayload(input: {
|
|
|
610
689
|
String(PLAY_RUNNER_TERMINAL_GRACE_SECONDS * 1_000),
|
|
611
690
|
shellQuote(runtimeLimitMarkerPath),
|
|
612
691
|
shellQuote(terminationDiagnosticPath),
|
|
692
|
+
shellQuote(memoryLedgerPath),
|
|
693
|
+
shellQuote(memoryPressurePath),
|
|
613
694
|
].join(' ');
|
|
614
695
|
const runnerCommand = `${nodeMaterializePayloadCommand({
|
|
615
696
|
envelopePath,
|
|
@@ -618,7 +699,7 @@ export async function stageRunnerPayload(input: {
|
|
|
618
699
|
artifactCodePath,
|
|
619
700
|
artifactSourceMapPath,
|
|
620
701
|
crashPusherPath,
|
|
621
|
-
})} && DEEPLINE_PLAY_RUNNER_RUNTIME_STARTED_PATH=${shellQuote(runtimeStartedPath)} DEEPLINE_PLAY_RUNNER_RUNTIME_COMPLETED_PATH=${shellQuote(runtimeCompletedPath)} DEEPLINE_PLAY_RUNNER_PROGRESS_EVENT_PATH=${shellQuote(progressEventPath)} DEEPLINE_PLAY_RUNNER_STARTUP_DIAGNOSTIC_PATH=${shellQuote(startupDiagnosticPath)} DEEPLINE_PLAY_RUNNER_STDOUT_EVENT_MODE=compact ${runtimeReliabilityEnv}${runnerTraceEnv}${watchedRunnerCommand}`;
|
|
702
|
+
})} && DEEPLINE_PLAY_RUNNER_RUNTIME_STARTED_PATH=${shellQuote(runtimeStartedPath)} DEEPLINE_PLAY_RUNNER_RUNTIME_COMPLETED_PATH=${shellQuote(runtimeCompletedPath)} DEEPLINE_PLAY_RUNNER_PROGRESS_EVENT_PATH=${shellQuote(progressEventPath)} DEEPLINE_PLAY_RUNNER_STARTUP_DIAGNOSTIC_PATH=${shellQuote(startupDiagnosticPath)} DEEPLINE_PLAY_RUNNER_STDOUT_EVENT_MODE=compact UV_THREADPOOL_SIZE=${PLAY_RUNNER_UV_THREADPOOL_SIZE} ${runtimeReliabilityEnv}${runnerTraceEnv}${sandboxTargetEnv}${watchedRunnerCommand}`;
|
|
622
703
|
// Crash-containment epilogue: runs UNCONDITIONALLY after the runner exits and
|
|
623
704
|
// pushes the parsed (or synthesized) terminal to the gateway so the parked
|
|
624
705
|
// worker wakes within seconds of ANY runner death — process.exit abuse, OOM
|
|
@@ -627,7 +708,7 @@ export async function stageRunnerPayload(input: {
|
|
|
627
708
|
// Its own retry diagnostics are kept in a separate log: appending them to
|
|
628
709
|
// `outputPath` after a near-gateway-sized result could hide that result from
|
|
629
710
|
// a later bounded-tail recovery read.
|
|
630
|
-
const command = `rm -f ${shellQuote(outputPath)} ${shellQuote(crashPusherLogPath)} ${shellQuote(exitCodePath)} ${shellQuote(oomKillBaselinePath)} ${shellQuote(runtimeStartedPath)} ${shellQuote(runtimeCompletedPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(terminationDiagnosticPath)} ${shellQuote(progressEventPath)} ${shellQuote(`${progressEventPath}.*`)} ${shellQuote(startupDiagnosticPath)}; ( awk '$1 == "oom_kill" { print $2 }' /sys/fs/cgroup/memory.events 2>/dev/null || true ) > ${shellQuote(oomKillBaselinePath)}; ( ${runnerCommand} ) > ${shellQuote(outputPath)} 2>&1; code=$?; printf '%s' "$code" > ${shellQuote(exitCodePath)}; ${runtimeReliabilityEnv}node ${shellQuote(crashPusherPath)} ${shellQuote(configPath)} "$code" ${shellQuote(outputPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(oomKillBaselinePath)} /sys/fs/cgroup/memory.events ${shellQuote(terminationDiagnosticPath)} > ${shellQuote(crashPusherLogPath)} 2>&1 || true; printf 'deepline runner output captured: %s\\n' ${shellQuote(outputPath)}; exit "$code"`;
|
|
711
|
+
const command = `rm -f ${shellQuote(outputPath)} ${shellQuote(crashPusherLogPath)} ${shellQuote(exitCodePath)} ${shellQuote(oomKillBaselinePath)} ${shellQuote(runtimeStartedPath)} ${shellQuote(runtimeCompletedPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(terminationDiagnosticPath)} ${shellQuote(memoryLedgerPath)} ${shellQuote(`${memoryLedgerPath}.tmp`)} ${shellQuote(memoryPressurePath)} ${shellQuote(progressEventPath)} ${shellQuote(`${progressEventPath}.*`)} ${shellQuote(startupDiagnosticPath)}; ( awk '$1 == "oom_kill" { print $2 }' /sys/fs/cgroup/memory.events 2>/dev/null || true ) > ${shellQuote(oomKillBaselinePath)}; ( ${runnerCommand} ) > ${shellQuote(outputPath)} 2>&1; code=$?; printf '%s' "$code" > ${shellQuote(exitCodePath)}; ${runtimeReliabilityEnv}node ${shellQuote(crashPusherPath)} ${shellQuote(configPath)} "$code" ${shellQuote(outputPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(oomKillBaselinePath)} /sys/fs/cgroup/memory.events ${shellQuote(terminationDiagnosticPath)} > ${shellQuote(crashPusherLogPath)} 2>&1 || true; printf 'deepline runner output captured: %s\\n' ${shellQuote(outputPath)}; exit "$code"`;
|
|
631
712
|
|
|
632
713
|
return {
|
|
633
714
|
workDir: input.workDir,
|
|
@@ -650,6 +731,10 @@ export async function stageDaytonaRunnerPayload(
|
|
|
650
731
|
...input,
|
|
651
732
|
sandbox: {
|
|
652
733
|
id: input.sandbox.id,
|
|
734
|
+
target:
|
|
735
|
+
typeof (input.sandbox as { target?: unknown }).target === 'string'
|
|
736
|
+
? ((input.sandbox as { target: string }).target ?? undefined)
|
|
737
|
+
: undefined,
|
|
653
738
|
uploadFile: (content, path) => input.sandbox.fs.uploadFile(content, path),
|
|
654
739
|
},
|
|
655
740
|
});
|