@ricsam/r5d-worker 0.0.179 → 0.0.180

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.179",
3
+ "version": "0.0.180",
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.179";
20608
+ if (true) return "0.0.180";
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.179" : "development"}`);
10
+ console.log(`r5d-worker ${true ? "0.0.180" : "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.179" : "development"
18
+ true ? "0.0.180" : "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.179",
3
+ "version": "0.0.180",
4
4
  "type": "module"
5
5
  }
@@ -254,11 +254,17 @@ async function startPersonalWorker(options, version) {
254
254
  root,
255
255
  async close() {
256
256
  stopped = true;
257
- await terminalStream.close();
258
- await loop;
259
- await scheduler.drain();
260
- await runtime.close();
261
- ledger.close();
257
+ try {
258
+ await terminalStream.close();
259
+ await loop;
260
+ await scheduler.drain();
261
+ } finally {
262
+ try {
263
+ await runtime.close();
264
+ } finally {
265
+ ledger.close();
266
+ }
267
+ }
262
268
  }
263
269
  };
264
270
  }
@@ -509,10 +509,18 @@ exec ${quote(executable)} ${quote(cli)} "$@"
509
509
  async close() {
510
510
  closing = true;
511
511
  clearInterval(publicationTimer);
512
- await publication;
513
- await tcp.close();
514
- await authority.close();
515
- await daemon.close();
512
+ try {
513
+ await publication;
514
+ } catch (error) {
515
+ process.stderr.write(`[r5d-worker] final publication cycle failed: ${error instanceof WorkspaceError ? error.code : "publication_failed"}
516
+ `);
517
+ }
518
+ try {
519
+ await tcp.close();
520
+ await authority.close();
521
+ } finally {
522
+ await daemon.close();
523
+ }
516
524
  }
517
525
  };
518
526
  } catch (error) {
@@ -2031,6 +2031,7 @@ class WorkspaceAuthority {
2031
2031
  await Promise.allSettled([...this.actions]);
2032
2032
  await Promise.allSettled([...this.queues.values()]);
2033
2033
  for (const b of this.benches.values()) await this.refresh(b);
2034
+ await this.drainLiveRuns();
2034
2035
  if ([...this.benches.values()].some(
2035
2036
  (b) => b.state.blocked || Object.values(b.state.runs).some((r) => !["completed", "cancelled", "rejected_capacity"].includes(r.state))
2036
2037
  ))
@@ -2043,6 +2044,32 @@ class WorkspaceAuthority {
2043
2044
  await fs.rm(path.join(this.config.root, ".sync-lock"), { recursive: true });
2044
2045
  this.closed = true;
2045
2046
  }
2047
+ /** A stop ends what the keeper tracks. Live runs (an open shell, an agent
2048
+ * command) are cancelled through the executor and waited for, the way a
2049
+ * supervisor drain would, so that an orderly stop leaves cancelled receipts
2050
+ * behind rather than a lock nobody can release: the process is going away
2051
+ * either way. Outcomes that stay unknown after the drain still retain the
2052
+ * lock for review. */
2053
+ async drainLiveRuns() {
2054
+ const live = (b) => Object.entries(b.state.runs).filter(([, run]) => !["completed", "cancelled", "rejected_capacity", "unknown"].includes(run.state));
2055
+ if (![...this.benches.values()].some((b) => live(b).length)) return;
2056
+ for (const b of this.benches.values()) {
2057
+ for (const [operationId, run] of live(b)) {
2058
+ try {
2059
+ const identity = { userId: b.config.userId, sessionId: run.sessionId ?? b.config.sessionId };
2060
+ const route = await this.route(b, identity);
2061
+ await route.client.cancel({ ...identity, operationId, fence: route.workerFence }, `drain-${this.lockId.slice(0, 8)}-${sha256(operationId).slice(0, 16)}`);
2062
+ } catch {
2063
+ }
2064
+ }
2065
+ }
2066
+ const deadline = Date.now() + 15e3;
2067
+ for (; ; ) {
2068
+ for (const b of this.benches.values()) await this.refresh(b);
2069
+ if (![...this.benches.values()].some((b) => live(b).length) || Date.now() >= deadline) return;
2070
+ await new Promise((resolve) => setTimeout(resolve, 200));
2071
+ }
2072
+ }
2046
2073
  }
2047
2074
  export {
2048
2075
  WorkspaceAuthority
@@ -500,4 +500,11 @@ export declare class WorkspaceAuthority {
500
500
  cancel(identity: WorkspaceIdentity, run: RunIdentity, actionId: string): Promise<import("..").ActionReceipt>;
501
501
  close(): Promise<void>;
502
502
  private finishClose;
503
+ /** A stop ends what the keeper tracks. Live runs (an open shell, an agent
504
+ * command) are cancelled through the executor and waited for, the way a
505
+ * supervisor drain would, so that an orderly stop leaves cancelled receipts
506
+ * behind rather than a lock nobody can release: the process is going away
507
+ * either way. Outcomes that stay unknown after the drain still retain the
508
+ * lock for review. */
509
+ private drainLiveRuns;
503
510
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/r5d-worker",
3
- "version": "0.0.179",
3
+ "version": "0.0.180",
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.179",
24
+ "@ricsam/r5d-api": "^0.0.180",
25
25
  "node-pty": "1.1.0",
26
26
  "zod": "^4.1.13",
27
27
  "picomatch": "^4.0.3"