@nylorun/runtime 0.51.0-beta → 0.51.2-beta
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/CHANGELOG.md +12 -0
- package/dist/harness/main.js +4 -3
- package/dist/harness/pod.d.ts +17 -0
- package/dist/harness/pod.js +32 -0
- package/dist/management-openapi.json +1 -1
- package/dist/openapi.json +1 -1
- package/dist/tenant/runtime.js +14 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.51.2-beta
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b04a877: Pods on Agent Substrate (preview): a pod's engine tries its first join again while the edge can't be reached. A new actor can start before its egress policy reaches Substrate's egress, so the first join failed at the network ("fetch failed") and the engine exited; Substrate doesn't restart an actor's main process, so the actor stayed RUNNING with no engine and the start failed at the ready deadline (E13 on kind: 2 of 3 first starts). The first join is now tried again from 250 ms, doubling to 5 s, for up to 4 minutes (`sandbox_join_retry` in the engine's log); a refusal is still final at once.
|
|
8
|
+
|
|
9
|
+
## 0.51.1-beta
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 8451138: Pods on Agent Substrate (preview): a drain is recorded as soon as the moved pod's engine connects again. After suspend before drain, the restored engine redials with its host token (no join), and nothing asked the Runtime to reconcile the pod, so `agent.suspended` with reason `drain` waited for the next turn or idle timer (E13 on kind: not within two minutes). A pod engine's connection now asks for its sandbox's reconcile.
|
|
14
|
+
|
|
3
15
|
## 0.51.0-beta
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/harness/main.js
CHANGED
|
@@ -27,7 +27,7 @@ import { createHostLogger } from "../host/logger.js";
|
|
|
27
27
|
import { RUNTIME_VERSION } from "../version.js";
|
|
28
28
|
import { localBackend, localExec } from "../adapters/sandbox/local.js";
|
|
29
29
|
import { awaitNetworkPolicy } from "../sandbox/pods/network-gate.js";
|
|
30
|
-
import { podHost } from "./pod.js";
|
|
30
|
+
import { firstJoin, podHost } from "./pod.js";
|
|
31
31
|
import { prepareDisk } from "./setup.js";
|
|
32
32
|
import { harnessRunTokens } from "./run-tokens.js";
|
|
33
33
|
import { startHarnessService } from "./service.js";
|
|
@@ -59,8 +59,9 @@ export async function runHarness(stack, baseline) {
|
|
|
59
59
|
caBundleFile: join(config.root, "egress-ca-bundle.pem"),
|
|
60
60
|
...(config.pod.egressCaFile ? { extraCaFile: config.pod.egressCaFile } : {}),
|
|
61
61
|
});
|
|
62
|
-
// Join, then make the disk ready (R2d step 2) before taking any turn.
|
|
63
|
-
|
|
62
|
+
// Join, then make the disk ready (R2d step 2) before taking any turn. The first join is tried
|
|
63
|
+
// again while the edge can't be reached yet (a new Agent Substrate actor's egress policy).
|
|
64
|
+
await firstJoin(pod, (message, fields) => logger.warn(message, fields));
|
|
64
65
|
const host = pod;
|
|
65
66
|
prepare = () => prepareDisk({
|
|
66
67
|
host,
|
package/dist/harness/pod.d.ts
CHANGED
|
@@ -52,6 +52,23 @@ export interface PodHost {
|
|
|
52
52
|
setupFile(index: number, path?: string): Promise<Response>;
|
|
53
53
|
stop(): void;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* The engine's first join, tried again while the edge can't be reached. On Agent Substrate a new
|
|
57
|
+
* actor can start before its egress policy reaches the egress gateway, so its first request to
|
|
58
|
+
* the edge fails at the network ("fetch failed"), and an engine that then exited stayed down: an
|
|
59
|
+
* actor's main process is not restarted the way a pod's container is (E13, 2 of 3 first starts on
|
|
60
|
+
* a GitHub runner). A refusal (400, 401) is final at once; anything else is tried again with a
|
|
61
|
+
* pause from 250 ms doubling to 5 s, until `budgetMs` (default 4 min, inside the Runtime's 5-minute
|
|
62
|
+
* ready deadline) has passed.
|
|
63
|
+
*/
|
|
64
|
+
export declare function firstJoin(host: Pick<PodHost, "token">, log: (message: string, fields: Record<string, unknown>) => void, options?: {
|
|
65
|
+
budgetMs?: number;
|
|
66
|
+
firstWaitMs?: number;
|
|
67
|
+
sleep?: (ms: number) => Promise<void>;
|
|
68
|
+
now?: () => number;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
/** Whether `error` is the Runtime refusing a join or a renewal (final), not the network. */
|
|
71
|
+
export declare function isRefused(error: unknown): boolean;
|
|
55
72
|
export declare function podHost(config: PodHostConfig, logger: {
|
|
56
73
|
info(message: string, fields?: Record<string, unknown>): void;
|
|
57
74
|
warn(message: string, fields?: Record<string, unknown>): void;
|
package/dist/harness/pod.js
CHANGED
|
@@ -29,6 +29,38 @@ const TRUST_VARIABLES = [
|
|
|
29
29
|
];
|
|
30
30
|
class Refused extends Error {
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* The engine's first join, tried again while the edge can't be reached. On Agent Substrate a new
|
|
34
|
+
* actor can start before its egress policy reaches the egress gateway, so its first request to
|
|
35
|
+
* the edge fails at the network ("fetch failed"), and an engine that then exited stayed down: an
|
|
36
|
+
* actor's main process is not restarted the way a pod's container is (E13, 2 of 3 first starts on
|
|
37
|
+
* a GitHub runner). A refusal (400, 401) is final at once; anything else is tried again with a
|
|
38
|
+
* pause from 250 ms doubling to 5 s, until `budgetMs` (default 4 min, inside the Runtime's 5-minute
|
|
39
|
+
* ready deadline) has passed.
|
|
40
|
+
*/
|
|
41
|
+
export async function firstJoin(host, log, options = {}) {
|
|
42
|
+
const now = options.now ?? Date.now;
|
|
43
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
44
|
+
const deadline = now() + (options.budgetMs ?? 240_000);
|
|
45
|
+
let wait = options.firstWaitMs ?? 250;
|
|
46
|
+
for (let attempt = 1;; attempt += 1) {
|
|
47
|
+
try {
|
|
48
|
+
await host.token();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof Refused || now() + wait > deadline)
|
|
53
|
+
throw error;
|
|
54
|
+
log("sandbox_join_retry", { attempt, waitMs: wait, error: error instanceof Error ? error.message : String(error) });
|
|
55
|
+
await sleep(wait);
|
|
56
|
+
wait = Math.min(wait * 2, 5_000);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Whether `error` is the Runtime refusing a join or a renewal (final), not the network. */
|
|
61
|
+
export function isRefused(error) {
|
|
62
|
+
return error instanceof Refused;
|
|
63
|
+
}
|
|
32
64
|
export function podHost(config, logger, options = {}) {
|
|
33
65
|
const call = options.fetch ?? fetch;
|
|
34
66
|
const imageEngine = options.imageEngine ?? isBuiltinEngine(import.meta.url);
|
package/dist/openapi.json
CHANGED
package/dist/tenant/runtime.js
CHANGED
|
@@ -392,7 +392,20 @@ export class TenantRuntime {
|
|
|
392
392
|
return this.ctx.onSweep(hook);
|
|
393
393
|
}
|
|
394
394
|
attachHarness(channel, peer) {
|
|
395
|
-
|
|
395
|
+
const detach = this.ctx.harness.attach(channel, peer);
|
|
396
|
+
// A pod's engine that (re)connects asks for its sandbox's reconcile: after a drain (Agent
|
|
397
|
+
// Substrate's eviction contract) the restored engine redials with its host token and no join,
|
|
398
|
+
// and this is what lets the Runtime see the move (`drainedAt`, `agent.suspended` reason
|
|
399
|
+
// `drain`) at once rather than at the next turn or idle timer.
|
|
400
|
+
const sandboxId = peer.host?.sandboxId;
|
|
401
|
+
if (sandboxId !== undefined)
|
|
402
|
+
void this.ctx.store
|
|
403
|
+
.tx((t) => t.signalSandbox(sandboxId, { kind: "reconcile" }))
|
|
404
|
+
.catch((error) => this.ctx.config.logger.warn("sandbox reconcile after connect failed", {
|
|
405
|
+
sandboxId,
|
|
406
|
+
error: error instanceof Error ? error.message : String(error),
|
|
407
|
+
}));
|
|
408
|
+
return detach;
|
|
396
409
|
}
|
|
397
410
|
harnessStatus() {
|
|
398
411
|
return harnessStatusOf(this.ctx);
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const RUNTIME_VERSION = "0.51.
|
|
1
|
+
export declare const RUNTIME_VERSION = "0.51.2-beta";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Kept in step with package.json by runtime/server/scripts/check-package.mjs, which runs in npm run check.
|
|
2
2
|
// release:prepare also rewrites this when it bumps @nylorun/runtime.
|
|
3
|
-
export const RUNTIME_VERSION = "0.51.
|
|
3
|
+
export const RUNTIME_VERSION = "0.51.2-beta";
|
package/package.json
CHANGED