@rulvar/cli 1.81.1 → 1.82.0

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.
Files changed (2) hide show
  1. package/dist/index.js +62 -44
  2. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -690,58 +690,74 @@ function createWorker(engine, options) {
690
690
  await releaseQuietly(lease);
691
691
  }
692
692
  }
693
- async function sweep() {
694
- if (stopping || sweeping) return 0;
695
- sweeping = true;
696
- try {
697
- let picked = 0;
698
- const metas = options.retention === void 0 ? await store.listRuns({ statuses: [...CANDIDATE_STATUSES] }) : await store.listRuns();
699
- const candidateIds = new Set(metas.filter((meta) => CANDIDATE_STATUSES.has(meta.status)).map((meta) => meta.runId));
700
- for (const runId of [...suspendedAt.keys()]) if (!candidateIds.has(runId)) suspendedAt.delete(runId);
701
- for (const runId of [...poisoned.keys()]) if (!candidateIds.has(runId)) poisoned.delete(runId);
702
- for (const meta of metas) {
703
- if (active.size >= concurrency) break;
704
- if (!CANDIDATE_STATUSES.has(meta.status)) {
705
- if (options.retention !== void 0 && !active.has(meta.runId)) await applyRetention(meta).catch((thrown) => {
706
- reportError(meta.runId, thrown);
707
- });
693
+ /** The sweep in flight, so stop() can wait it out before snapshotting. */
694
+ let sweepInFlight;
695
+ async function sweepBody() {
696
+ let picked = 0;
697
+ const metas = options.retention === void 0 ? await store.listRuns({ statuses: [...CANDIDATE_STATUSES] }) : await store.listRuns();
698
+ const candidateIds = new Set(metas.filter((meta) => CANDIDATE_STATUSES.has(meta.status)).map((meta) => meta.runId));
699
+ for (const runId of [...suspendedAt.keys()]) if (!candidateIds.has(runId)) suspendedAt.delete(runId);
700
+ for (const runId of [...poisoned.keys()]) if (!candidateIds.has(runId)) poisoned.delete(runId);
701
+ for (const meta of metas) {
702
+ if (stopping) break;
703
+ if (!CANDIDATE_STATUSES.has(meta.status)) {
704
+ if (options.retention !== void 0 && !active.has(meta.runId)) await applyRetention(meta).catch((thrown) => {
705
+ reportError(meta.runId, thrown);
706
+ });
707
+ continue;
708
+ }
709
+ if (active.size >= concurrency) {
710
+ if (options.retention === void 0) break;
711
+ continue;
712
+ }
713
+ if (active.has(meta.runId)) continue;
714
+ if (poisoned.has(meta.runId)) {
715
+ if (poisoned.get(meta.runId) === meta.genesis) continue;
716
+ poisoned.delete(meta.runId);
717
+ }
718
+ let lease;
719
+ try {
720
+ lease = await store.acquire(meta.runId, owner);
721
+ } catch (thrown) {
722
+ if (thrown instanceof LeaseHeldError) continue;
723
+ throw thrown;
724
+ }
725
+ try {
726
+ const entries = (await store.load(meta.runId)).map((raw) => normalizeEntry(raw));
727
+ scanJournalCompatibility(meta.runId, entries, registry);
728
+ const cached = suspendedAt.get(meta.runId);
729
+ if (meta.status === "suspended" && cached !== void 0 && cached.length === entries.length && cached.genesis === meta.genesis) {
730
+ await releaseQuietly(lease);
708
731
  continue;
709
732
  }
710
- if (active.has(meta.runId)) continue;
711
- if (poisoned.has(meta.runId)) {
712
- if (poisoned.get(meta.runId) === meta.genesis) continue;
713
- poisoned.delete(meta.runId);
714
- }
715
- let lease;
716
- try {
717
- lease = await store.acquire(meta.runId, owner);
718
- } catch (thrown) {
719
- if (thrown instanceof LeaseHeldError) continue;
720
- throw thrown;
721
- }
722
- try {
723
- const entries = (await store.load(meta.runId)).map((raw) => normalizeEntry(raw));
724
- scanJournalCompatibility(meta.runId, entries, registry);
725
- const cached = suspendedAt.get(meta.runId);
726
- if (meta.status === "suspended" && cached !== void 0 && cached.length === entries.length && cached.genesis === meta.genesis) {
727
- await releaseQuietly(lease);
728
- continue;
729
- }
730
- picked += 1;
731
- drive(meta.runId, meta, lease);
732
- } catch (thrown) {
733
+ if (stopping) {
733
734
  await releaseQuietly(lease);
734
- if (thrown instanceof JournalCompatibilityError || thrown instanceof ConfigError) {
735
- poisoned.set(meta.runId, meta.genesis);
736
- reportError(meta.runId, thrown);
737
- continue;
738
- }
735
+ break;
736
+ }
737
+ picked += 1;
738
+ drive(meta.runId, meta, lease);
739
+ } catch (thrown) {
740
+ await releaseQuietly(lease);
741
+ if (thrown instanceof JournalCompatibilityError || thrown instanceof ConfigError) {
742
+ poisoned.set(meta.runId, meta.genesis);
739
743
  reportError(meta.runId, thrown);
744
+ continue;
740
745
  }
746
+ reportError(meta.runId, thrown);
741
747
  }
742
- return picked;
748
+ }
749
+ return picked;
750
+ }
751
+ async function sweep() {
752
+ if (stopping || sweeping) return 0;
753
+ sweeping = true;
754
+ const work = sweepBody();
755
+ sweepInFlight = work.then(() => void 0, () => void 0);
756
+ try {
757
+ return await work;
743
758
  } finally {
744
759
  sweeping = false;
760
+ sweepInFlight = void 0;
745
761
  }
746
762
  }
747
763
  return {
@@ -759,6 +775,8 @@ function createWorker(engine, options) {
759
775
  clearInterval(pollTimer);
760
776
  pollTimer = void 0;
761
777
  }
778
+ const inFlight = sweepInFlight;
779
+ if (inFlight !== void 0) await inFlight;
762
780
  const held = [...active.values()];
763
781
  await Promise.all(held.map(async (run) => {
764
782
  await run.cancel("worker stopping");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rulvar/cli",
3
- "version": "1.81.1",
3
+ "version": "1.82.0",
4
4
  "description": "Rulvar shell: run/resume/runs/inspect/plan/kb commands, TUI progress, createServer, createWorker, OTel exporter.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,17 +22,17 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
- "@rulvar/core": "1.81.1"
25
+ "@rulvar/core": "1.82.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.20.0",
29
29
  "tsdown": "^0.22.3",
30
30
  "typescript": "~6.0.3",
31
- "@rulvar/testing": "1.81.1",
32
- "@rulvar/store-sqlite": "1.81.1",
33
- "@rulvar/plan": "1.81.1",
34
- "@rulvar/evals": "1.81.1",
35
- "@rulvar/planner": "1.81.1"
31
+ "@rulvar/store-sqlite": "1.82.0",
32
+ "@rulvar/testing": "1.82.0",
33
+ "@rulvar/planner": "1.82.0",
34
+ "@rulvar/evals": "1.82.0",
35
+ "@rulvar/plan": "1.82.0"
36
36
  },
37
37
  "bin": {
38
38
  "rulvar": "./dist/cli.js"