@nowcrew/daemon 0.6.47 → 0.6.49

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.
@@ -4,6 +4,8 @@ export function createCompletionRetransmitter(options) {
4
4
  const maxAttempts = options.maxAttempts ?? 20;
5
5
  const maxAgeMs = options.maxAgeMs ?? 10 * 60 * 1_000;
6
6
  const pending = new Map();
7
+ // This set suppresses duplicate exhaustion telemetry across reconnects. It must
8
+ // never gate journal replay: an unacknowledged completion remains deliverable.
7
9
  const exhausted = new Set();
8
10
  let active = false;
9
11
  let stopped = false;
@@ -16,12 +18,14 @@ export function createCompletionRetransmitter(options) {
16
18
  const expire = (entry, reason) => {
17
19
  clear(entry);
18
20
  pending.delete(entry.frame.executionId);
19
- exhausted.add(entry.frame.executionId);
20
- options.onRetryExhausted?.({
21
- executionId: entry.frame.executionId,
22
- attempts: entry.attempts,
23
- reason,
24
- });
21
+ if (!exhausted.has(entry.frame.executionId)) {
22
+ exhausted.add(entry.frame.executionId);
23
+ options.onRetryExhausted?.({
24
+ executionId: entry.frame.executionId,
25
+ attempts: entry.attempts,
26
+ reason,
27
+ });
28
+ }
25
29
  };
26
30
  const ageRemainingMs = (entry) => maxAgeMs - (Date.now() - entry.startedAtMs);
27
31
  function schedule(entry) {
@@ -74,7 +78,7 @@ export function createCompletionRetransmitter(options) {
74
78
  }
75
79
  return {
76
80
  track(frame) {
77
- if (stopped || pending.has(frame.executionId) || exhausted.has(frame.executionId))
81
+ if (stopped || pending.has(frame.executionId))
78
82
  return;
79
83
  const entry = { frame, startedAtMs: Date.now(), attempts: 0, timer: null };
80
84
  pending.set(frame.executionId, entry);
@@ -86,8 +86,10 @@ function reservation(prerequisite, acquire) {
86
86
  granted = true;
87
87
  return lease;
88
88
  });
89
- const neverReady = new Promise(() => { });
90
- const ready = acquisition.then((lease) => lease === null ? neverReady : undefined);
89
+ const ready = acquisition.then((lease) => {
90
+ if (lease === null)
91
+ throw new HostReservationCancelledError();
92
+ });
91
93
  void ready.catch(() => undefined);
92
94
  return {
93
95
  ready,
package/dist/serve.js CHANGED
@@ -571,9 +571,8 @@ export function serve(config, opts = {}) {
571
571
  });
572
572
  };
573
573
  const cancellation = cancellationFor(spec.executionId);
574
- const slotForReservation = (attemptReservation, queueEnteredAt) => ({
575
- state: attemptReservation.state ?? (attemptReservation.isQueued() ? "queued" : "ready"),
576
- ready: attemptReservation.ready.then(() => {
574
+ const slotForReservation = (attemptReservation, queueEnteredAt) => {
575
+ const ready = attemptReservation.ready.then(() => {
577
576
  markExecutionTaskKeyActive();
578
577
  attemptReservation.markPreparing();
579
578
  concurrencyTelemetry.transition(executionConcurrencyIdentity, "preparing", {
@@ -597,8 +596,16 @@ export function serve(config, opts = {}) {
597
596
  memory_prune_starting_total: snapshot.memoryPruneStartingTotal,
598
597
  memory_prune_running_total: snapshot.memoryPruneRunningTotal,
599
598
  });
600
- }),
601
- });
599
+ });
600
+ // Cancellation can win while this derived promise is still queued. Keep the
601
+ // rejection observable to the runner while preventing an unhandled rejection
602
+ // when the runner has already stopped waiting for the slot.
603
+ void ready.catch(() => undefined);
604
+ return {
605
+ state: attemptReservation.state ?? (attemptReservation.isQueued() ? "queued" : "ready"),
606
+ ready,
607
+ };
608
+ };
602
609
  const onRetry = async ({ attempt, reason, }) => {
603
610
  if (stopped || cancellation.isRequested())
604
611
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nowcrew/daemon",
3
- "version": "0.6.47",
3
+ "version": "0.6.49",
4
4
  "type": "module",
5
5
  "description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
6
6
  "license": "Apache-2.0",