@botbuddy/cli 1.36.0 → 1.36.1
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/package.json +1 -1
- package/src/stack.mjs +31 -6
package/package.json
CHANGED
package/src/stack.mjs
CHANGED
|
@@ -1587,19 +1587,24 @@ export async function cmdUp(opts, {
|
|
|
1587
1587
|
}), opts, EXIT.OK);
|
|
1588
1588
|
}
|
|
1589
1589
|
|
|
1590
|
-
async function cmdStatus(leaseId, opts, { rpc = retryingStackCall() } = {}) {
|
|
1590
|
+
export async function cmdStatus(leaseId, opts, { rpc = retryingStackCall(), emitResult = emit } = {}) {
|
|
1591
1591
|
const auth = await rpc.init();
|
|
1592
|
-
if (!auth) return
|
|
1592
|
+
if (!auth) return emitResult(buildReceipt({ command: "status", outcome: "error", lease_id: leaseId, error: "not authenticated — run `botbuddy login`" }), opts, EXIT.AUTH);
|
|
1593
1593
|
const got = await rpc.call("get_stack_lease", { lease_id: leaseId });
|
|
1594
1594
|
if (!got.ok) return got.auth
|
|
1595
|
-
?
|
|
1596
|
-
:
|
|
1595
|
+
? emitResult(buildReceipt({ command: "status", outcome: "error", lease_id: leaseId, error: got.error }), opts, EXIT.AUTH)
|
|
1596
|
+
: emitResult(buildReceipt({ command: "status", outcome: "error", lease_id: leaseId, error: got.error }), opts, EXIT.BACKEND);
|
|
1597
1597
|
const g = got.data;
|
|
1598
|
-
if (!g.success) return
|
|
1599
|
-
return
|
|
1598
|
+
if (!g.success) return emitResult(buildReceipt({ command: "status", outcome: "error", lease_id: leaseId, code: g.code, error: g.code }), opts, EXIT.BACKEND);
|
|
1599
|
+
return emitResult(buildReceipt({
|
|
1600
1600
|
command: "status", outcome: g.state, lease_id: leaseId, state: g.state,
|
|
1601
1601
|
host_key: g.host_key, slot: g.slot, connection: g.connection,
|
|
1602
1602
|
queue_position: g.queue_position, idle_ttl_secs: g.idle_ttl_secs, queued: g.queued,
|
|
1603
|
+
// BOT-1960: a lease fenced in `reaping` says since when, and — once the server gave up
|
|
1604
|
+
// retrying its failed reap — that it is reap_failed and why.
|
|
1605
|
+
...(g.reap_requested_at ? { reap_requested_at: g.reap_requested_at } : {}),
|
|
1606
|
+
...(g.reap_failed_at ? { reap_failed: true, reap_failed_at: g.reap_failed_at } : {}),
|
|
1607
|
+
...(g.state === "reaping" && g.error ? { error: g.error } : {}),
|
|
1603
1608
|
}), opts, EXIT.OK);
|
|
1604
1609
|
}
|
|
1605
1610
|
|
|
@@ -1803,7 +1808,27 @@ export async function cmdDone(leaseId, opts, {
|
|
|
1803
1808
|
if (fin.ok && fin.data?.success) state = fin.data.state;
|
|
1804
1809
|
else process.stderr.write(`${yellow("⚠")} stack: finalize failed (${fin.error || fin.data?.code}); the reaper will reconcile.\n`);
|
|
1805
1810
|
}
|
|
1811
|
+
// BOT-1960: on a lease fenced in `reaping` by a FAILED reap, the server re-enqueues the
|
|
1812
|
+
// reap (the first time also resetting its retry budget) — or, once that budget is spent,
|
|
1813
|
+
// refuses. Say which, instead of a `released` that changed nothing.
|
|
1814
|
+
const retry = r.data.reap_retry;
|
|
1815
|
+
if (state === "reaping" && retry?.code === "REAP_RETRY_BUDGET_SPENT") {
|
|
1816
|
+
const since = r.data.reap_failed_at ? ` (since ${r.data.reap_failed_at})` : "";
|
|
1817
|
+
return emitResult(buildReceipt({ command: "done", outcome: "reap_failed", lease_id: leaseId, state, disposition,
|
|
1818
|
+
reap_failed_at: r.data.reap_failed_at ?? null, reap_retry: { enqueued: false, code: retry.code },
|
|
1819
|
+
error: `the reap failed on every retry${since}; no retries left — the lease stays reaping and its slot stays fenced. ` +
|
|
1820
|
+
"Remove the project's leftover containers (operator / `botbuddy docker hygiene`); the container census then finalizes the lease.",
|
|
1821
|
+
}), opts, EXIT.LEASE_FAILED);
|
|
1822
|
+
}
|
|
1823
|
+
const retried = retry?.code === "REAP_RETRY_ENQUEUED"
|
|
1824
|
+
? {
|
|
1825
|
+
reap_retry: { enqueued: true, attempt: retry.attempt, budget_reset: retry.budget_reset === true },
|
|
1826
|
+
note: `the previous reap failed; a new reap job (attempt ${retry.attempt}) was enqueued` +
|
|
1827
|
+
(retry.budget_reset === true ? " and the reap retry budget was reset" : ""),
|
|
1828
|
+
}
|
|
1829
|
+
: {};
|
|
1806
1830
|
return emitResult(buildReceipt({ command: "done", outcome: "released", lease_id: leaseId, state, disposition,
|
|
1831
|
+
...retried,
|
|
1807
1832
|
...(helperTeardown ? { teardown: "helper" } : {}),
|
|
1808
1833
|
...(legacyTargetProof ? { legacy_target_proof: legacyTargetProof } : {}) }), opts, EXIT.OK);
|
|
1809
1834
|
}
|