fluncle 0.244.0 → 0.245.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/bin/fluncle.mjs +34 -10
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -622,7 +622,7 @@ function parseVersion(version) {
622
622
  var currentVersion;
623
623
  var init_version = __esm(() => {
624
624
  init_output();
625
- currentVersion = "0.244.0".trim() ? "0.244.0".trim() : "0.1.0";
625
+ currentVersion = "0.245.0".trim() ? "0.245.0".trim() : "0.1.0";
626
626
  });
627
627
 
628
628
  // src/update-notifier.ts
@@ -2335,7 +2335,7 @@ function parseVersion2(version) {
2335
2335
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2336
2336
  var init_version2 = __esm(() => {
2337
2337
  init_output();
2338
- currentVersion2 = "0.244.0".trim() ? "0.244.0".trim() : "0.1.0";
2338
+ currentVersion2 = "0.245.0".trim() ? "0.245.0".trim() : "0.1.0";
2339
2339
  });
2340
2340
 
2341
2341
  // ../../packages/registry/src/index.ts
@@ -12400,7 +12400,9 @@ var init_admin_projections = __esm(() => {
12400
12400
  artistQualification: ProjectionFamilyStatusSchema,
12401
12401
  crawlDueWork: ProjectionFamilyStatusSchema,
12402
12402
  publicAggregates: ProjectionFamilyStatusSchema.extend({ anchorsReady: boolean2() }),
12403
- trackDueWork: ProjectionFamilyStatusSchema
12403
+ trackDueWork: ProjectionFamilyStatusSchema.extend({
12404
+ catalogueRankMarkerAgeMs: CountSchema.nullable().optional()
12405
+ })
12404
12406
  }),
12405
12407
  readyToOpen: object({
12406
12408
  crawlDueWork: boolean2(),
@@ -16842,16 +16844,29 @@ async function getProjectionStatusCommand() {
16842
16844
  return adminApiGet("/api/v1/admin/projections/status");
16843
16845
  }
16844
16846
  async function advanceProjectionCommand(input) {
16845
- const { includeTerminalStatus = true, maxSteps = 1, target, ...body } = input;
16847
+ const {
16848
+ includeTerminalStatus = true,
16849
+ maxSteps = 1,
16850
+ now = () => Date.now(),
16851
+ target,
16852
+ wallMs,
16853
+ ...body
16854
+ } = input;
16846
16855
  if (!includeTerminalStatus && input.action !== "repair") {
16847
16856
  throw new Error("terminal status may be omitted only for repair automation");
16848
16857
  }
16849
16858
  const stepBody = maxSteps > 1 || !includeTerminalStatus ? { ...body, includeStatus: false } : body;
16859
+ const startedAt = now();
16850
16860
  let response = await adminApiPost(`/api/v1/admin/projections/${target}/advance`, stepBody);
16851
16861
  let steps = 1;
16852
16862
  let processed = response.processed;
16853
16863
  let scheduled = response.scheduled;
16864
+ let wallStopped = false;
16854
16865
  while (!response.complete && steps < maxSteps) {
16866
+ if (wallMs !== undefined && now() - startedAt >= wallMs) {
16867
+ wallStopped = true;
16868
+ break;
16869
+ }
16855
16870
  response = await adminApiPost(`/api/v1/admin/projections/${target}/advance`, stepBody);
16856
16871
  steps += 1;
16857
16872
  processed += response.processed;
@@ -16859,10 +16874,10 @@ async function advanceProjectionCommand(input) {
16859
16874
  }
16860
16875
  if (!includeTerminalStatus) {
16861
16876
  const { status: _status, ...withoutStatus } = response;
16862
- return { ...withoutStatus, processed, scheduled, steps };
16877
+ return { ...withoutStatus, processed, scheduled, steps, wallStopped };
16863
16878
  }
16864
16879
  const status = response.status ?? (await getProjectionStatusCommand()).status;
16865
- return { ...response, processed, scheduled, status, steps };
16880
+ return { ...response, processed, scheduled, status, steps, wallStopped };
16866
16881
  }
16867
16882
  async function setProjectionCutoverCommand(input) {
16868
16883
  const { enabled, target } = input;
@@ -16888,6 +16903,13 @@ function parseProjectionMaxSteps(value) {
16888
16903
  }
16889
16904
  return maxSteps;
16890
16905
  }
16906
+ function parseProjectionWallMs(value) {
16907
+ const wallMs = Number(value);
16908
+ if (!Number.isSafeInteger(wallMs) || wallMs < PROJECTION_WALL_MS_MIN || wallMs > PROJECTION_WALL_MS_MAX) {
16909
+ throw new Error(`--wall-ms must be a whole number of milliseconds from ${PROJECTION_WALL_MS_MIN} through ${PROJECTION_WALL_MS_MAX}`);
16910
+ }
16911
+ return wallMs;
16912
+ }
16891
16913
  function parseProjectionTarget(value) {
16892
16914
  if (value !== "artist_qualification" && value !== "crawl_due_work" && value !== "public_aggregates" && value !== "track_due_work") {
16893
16915
  throw new Error("--target must be artist_qualification, crawl_due_work, public_aggregates, or track_due_work");
@@ -16915,7 +16937,7 @@ function projectionStatusLines(status) {
16915
16937
  row("Artist qualification", status.projections.artistQualification, status.cutovers.publicProjections)
16916
16938
  ];
16917
16939
  }
16918
- var PROJECTION_MAX_STEPS = 100;
16940
+ var PROJECTION_MAX_STEPS = 100, PROJECTION_WALL_MS_MIN = 1000, PROJECTION_WALL_MS_MAX = 600000;
16919
16941
  var init_admin_projections2 = __esm(() => {
16920
16942
  init_orpc();
16921
16943
  init_api();
@@ -21744,7 +21766,7 @@ JSON field reference:
21744
21766
  console.log(projectionStatusLines(result.status).join(`
21745
21767
  `));
21746
21768
  });
21747
- adminProjections.command("advance").description("Run bounded, resumable rebuild, repair, or audit steps").requiredOption("--target <target>", "track_due_work, crawl_due_work, public_aggregates, or artist_qualification").requiredOption("--action <action>", "rebuild, repair, or audit").option("--limit <limit>", "Maximum rows or repairs in this request (1-500)", "100").option("--max-steps <steps>", "Maximum sequential advance calls (1-100)").option("--no-terminal-status", "Omit the terminal readiness snapshot (JSON repair automation only)").option("--json", "Print the aggregate result and default readiness as JSON", false).action(async (options) => {
21769
+ adminProjections.command("advance").description("Run bounded, resumable rebuild, repair, or audit steps").requiredOption("--target <target>", "track_due_work, crawl_due_work, public_aggregates, or artist_qualification").requiredOption("--action <action>", "rebuild, repair, or audit").option("--limit <limit>", "Maximum rows or repairs in this request (1-500)", "100").option("--max-steps <steps>", "Maximum sequential advance calls (1-100)").option("--wall-ms <ms>", "Stop issuing further steps once this many milliseconds have elapsed (1000-600000)").option("--no-terminal-status", "Omit the terminal readiness snapshot (JSON repair automation only)").option("--json", "Print the aggregate result and default readiness as JSON", false).action(async (options) => {
21748
21770
  const projections = await Promise.resolve().then(() => (init_admin_projections2(), {}));
21749
21771
  const action = parseProjectionAction(options.action);
21750
21772
  if (!options.terminalStatus && (!options.json || action !== "repair")) {
@@ -21755,13 +21777,14 @@ JSON field reference:
21755
21777
  includeTerminalStatus: options.terminalStatus,
21756
21778
  limit: parseProjectionLimit(options.limit),
21757
21779
  maxSteps: options.maxSteps === undefined ? undefined : parseProjectionMaxSteps(options.maxSteps),
21758
- target: parseProjectionTarget(options.target)
21780
+ target: parseProjectionTarget(options.target),
21781
+ wallMs: options.wallMs === undefined ? undefined : parseProjectionWallMs(options.wallMs)
21759
21782
  });
21760
21783
  if (options.json) {
21761
21784
  printJson(result);
21762
21785
  return;
21763
21786
  }
21764
- console.log(`${result.target} ${result.action}: steps ${result.steps}, processed ${result.processed}, scheduled ${result.scheduled}, ${result.complete ? "complete" : "more work remains"}.`);
21787
+ console.log(`${result.target} ${result.action}: steps ${result.steps}, processed ${result.processed}, scheduled ${result.scheduled}, ${result.complete ? "complete" : result.wallStopped ? "wall budget spent, more work remains" : "more work remains"}.`);
21765
21788
  });
21766
21789
  adminProjections.command("set").description("Open or close one readiness-gated projection cutover").requiredOption("--target <target>", "track_due_work, crawl_due_work, or public_projections").requiredOption("--enabled <boolean>", "true opens; false closes unconditionally").option("--json", "Print the stored flag and current readiness as JSON", false).action(async (options) => {
21767
21790
  const projections = await Promise.resolve().then(() => (init_admin_projections2(), {}));
@@ -25820,6 +25843,7 @@ var stringOptions = new Set([
25820
25843
  "--video-url",
25821
25844
  "--view",
25822
25845
  "--voice-id",
25846
+ "--wall-ms",
25823
25847
  "--window-since",
25824
25848
  "--window-until"
25825
25849
  ]);
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.244.0"
34
+ "version": "0.245.0"
35
35
  }