@ricsam/r5d-worker 0.0.178 → 0.0.179

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.178",
3
+ "version": "0.0.179",
4
4
  "type": "commonjs"
5
5
  }
@@ -20605,7 +20605,7 @@ function resolveEntrypointPath(entrypoint) {
20605
20605
  }
20606
20606
  }
20607
20607
  function getR5dctlVersion() {
20608
- if (true) return "0.0.178";
20608
+ if (true) return "0.0.179";
20609
20609
  const entrypoint = process.argv[1] ? resolveEntrypointPath(process.argv[1]) : null;
20610
20610
  let current = entrypoint ? import_node_path2.default.dirname(entrypoint) : process.cwd();
20611
20611
  for (let index = 0; index < 12; index += 1) {
package/dist/mjs/main.mjs CHANGED
@@ -7,7 +7,7 @@ import { startManagerRpc } from "./runtime/releases/rpc-main.mjs";
7
7
  import { ManagerRpcConfig } from "./runtime/releases/rpc-protocol.mjs";
8
8
  const args = process.argv.slice(2);
9
9
  if (args.includes("--version")) {
10
- console.log(`r5d-worker ${true ? "0.0.178" : "development"}`);
10
+ console.log(`r5d-worker ${true ? "0.0.179" : "development"}`);
11
11
  } else if (!args.length || args.includes("--help")) {
12
12
  console.log(
13
13
  "Usage: r5d-worker start --label <label> [--root <dir>] [--base-url <url>] [--token <worker-token>] [--initial-sync merge|reset]\n r5d-worker executor /absolute/private/config.json\n r5d-worker manager /absolute/private/config.json\n\nRun independently supervised durable runtime services. Provision configuration with r5dinfra."
@@ -15,7 +15,7 @@ if (args.includes("--version")) {
15
15
  } else if (args[0] === "start") {
16
16
  const runtime = await startPersonalWorker(
17
17
  parsePersonalWorkerOptions(args.slice(1)),
18
- true ? "0.0.178" : "development"
18
+ true ? "0.0.179" : "development"
19
19
  );
20
20
  console.log(`Worker connected: ${runtime.resourceId}`);
21
21
  let closing = false;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.178",
3
+ "version": "0.0.179",
4
4
  "type": "module"
5
5
  }
@@ -25,6 +25,8 @@ class PersonalResponseError extends Error {
25
25
  rejectedBeforeAdmission;
26
26
  }
27
27
  const storageErrorCodes = /* @__PURE__ */ new Set(["invalid_input", "conflict", "not_found", "busy", "stale_fence", "unknown", "unsafe_path", "git_failed"]);
28
+ const POLL_TIMEOUT_MS = 1e4;
29
+ const isStaleFence = (error) => error?.code === "stale_fence";
28
30
  function parsePersonalWorkerOptions(args, environment = process.env) {
29
31
  const values = {};
30
32
  const allowed = /* @__PURE__ */ new Set(["label", "base-url", "token", "api-key", "config", "root", "initial-sync"]);
@@ -90,13 +92,13 @@ async function startPersonalWorker(options, version) {
90
92
  }
91
93
  }
92
94
  const endpoint = `/api/personal/resources/worker/${encodeURIComponent(identity.resourceId)}`;
93
- async function request(pathname, body) {
95
+ async function request(pathname, body, timeoutMs = 3e4) {
94
96
  const response = await fetch(options.baseUrl + pathname, {
95
97
  method: "POST",
96
98
  headers: { authorization: `Bearer ${options.credential}`, "content-type": "application/json" },
97
99
  redirect: "error",
98
100
  body: JSON.stringify(body),
99
- signal: AbortSignal.timeout(3e4)
101
+ signal: AbortSignal.timeout(timeoutMs)
100
102
  });
101
103
  const data = await response.json();
102
104
  if (!response.ok) {
@@ -105,7 +107,7 @@ async function startPersonalWorker(options, version) {
105
107
  return data;
106
108
  }
107
109
  const cli = await resolvePersonalCliEntrypoint(options.cliEntrypoint, version);
108
- const bootId = randomUUID();
110
+ let bootId = randomUUID();
109
111
  const metadata = () => ({
110
112
  version,
111
113
  bootId,
@@ -203,19 +205,47 @@ async function startPersonalWorker(options, version) {
203
205
  const terminalStream = startTerminalStream({ url: streamUrl.toString(), credential: options.credential, version, runtime });
204
206
  const loop = (async () => {
205
207
  while (!stopped) {
208
+ let response;
206
209
  try {
207
210
  const sendMetadata = Date.now() - metadataAt > 6e4;
208
- const response = await request(`${endpoint}/poll`, {
209
- instanceId: identity.instanceId,
210
- ...sendMetadata ? { metadata: metadata() } : {}
211
- });
211
+ response = await request(
212
+ `${endpoint}/poll`,
213
+ { instanceId: identity.instanceId, ...sendMetadata ? { metadata: metadata() } : {} },
214
+ options.pollTimeoutMs ?? POLL_TIMEOUT_MS
215
+ );
212
216
  if (sendMetadata) metadataAt = Date.now();
213
- await runtime.renew({ ...grant, ...response });
214
- scheduler.accept(response.actions ?? []);
215
217
  } catch (error) {
216
218
  process.stderr.write(`[r5d-worker] ${safeError(error)}; reconnecting without replacing the local keeper
217
219
  `);
220
+ await Bun.sleep(250);
221
+ continue;
222
+ }
223
+ try {
224
+ await runtime.renew({ ...grant, ...response });
225
+ } catch (error) {
226
+ if (!isStaleFence(error)) {
227
+ process.stderr.write(`[r5d-worker] ${safeError(error)}; reconnecting without replacing the local keeper
228
+ `);
229
+ await Bun.sleep(250);
230
+ continue;
231
+ }
232
+ try {
233
+ bootId = randomUUID();
234
+ const rotated = PersonalWorkerGrant.parse(
235
+ await request("/api/personal/resources/register", { kind: "worker", ...identity, label: options.label, metadata: metadata() })
236
+ );
237
+ metadataAt = Date.now();
238
+ await runtime.renew(rotated);
239
+ process.stderr.write(`[r5d-worker] executor authority lapsed locally; re-registered with a new boot id (epoch ${rotated.workerFence.epoch})
240
+ `);
241
+ } catch (rotation) {
242
+ process.stderr.write(`[r5d-worker] ${safeError(rotation)}; authority rotation pending
243
+ `);
244
+ await Bun.sleep(250);
245
+ continue;
246
+ }
218
247
  }
248
+ scheduler.accept(response.actions ?? []);
219
249
  await Bun.sleep(250);
220
250
  }
221
251
  })();
@@ -11,6 +11,7 @@ export type PersonalWorkerOptions = {
11
11
  root: string;
12
12
  cliEntrypoint?: string;
13
13
  initialSync?: PersonalWorkerInitialSync;
14
+ pollTimeoutMs?: number;
14
15
  };
15
16
  export declare function parsePersonalWorkerOptions(args: string[], environment?: Record<string, string | undefined>): PersonalWorkerOptions;
16
17
  /** HTTP reconnects never replace the local source/PTY keeper. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.178",
3
+ "version": "0.0.179",
4
4
  "type": "module",
5
5
  "main": "./dist/mjs/main.mjs",
6
6
  "module": "./dist/mjs/main.mjs",
@@ -21,7 +21,7 @@
21
21
  "r5d-worker": "dist/mjs/main.mjs"
22
22
  },
23
23
  "dependencies": {
24
- "@ricsam/r5d-api": "^0.0.178",
24
+ "@ricsam/r5d-api": "^0.0.179",
25
25
  "node-pty": "1.1.0",
26
26
  "zod": "^4.1.13",
27
27
  "picomatch": "^4.0.3"