fluncle 0.244.0 → 0.246.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.
- package/bin/fluncle.mjs +118 -12
- 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.
|
|
625
|
+
currentVersion = "0.246.0".trim() ? "0.246.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.
|
|
2338
|
+
currentVersion2 = "0.246.0".trim() ? "0.246.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -12341,7 +12341,7 @@ var init_admin_prompts = __esm(() => {
|
|
|
12341
12341
|
});
|
|
12342
12342
|
|
|
12343
12343
|
// ../../packages/contracts/src/orpc/admin-projections.ts
|
|
12344
|
-
var PROJECTION_STEP_LIMIT_MAX = 500, ProjectionTargetSchema, ProjectionCutoverSchema, ProjectionStepActionSchema, CountSchema, BoundedCountSchema, DigestSchema2, RebuildSchema, BacklogSchema, RepairSchema, OldestOutstandingMarkerAgeSchema, ConvergenceSchema, ProjectionFamilyStatusSchema, ProjectionStatusSchema, getProjectionStatus, advanceProjection, setProjectionCutover, adminProjectionsContract;
|
|
12344
|
+
var PROJECTION_STEP_LIMIT_MAX = 500, ProjectionTargetSchema, ProjectionCutoverSchema, ProjectionStepActionSchema, CountSchema, BoundedCountSchema, DigestSchema2, RebuildSchema, BacklogSchema, RepairSchema, OldestOutstandingMarkerAgeSchema, ConvergenceSchema, ProjectionFamilyStatusSchema, ProjectionStatusSchema, getProjectionStatus, advanceProjection, setProjectionCutover, DUE_WORK_REKEY_LIMIT_MAX = 500, rekeyDueWorkQueue, adminProjectionsContract;
|
|
12345
12345
|
var init_admin_projections = __esm(() => {
|
|
12346
12346
|
init_dist3();
|
|
12347
12347
|
init_zod();
|
|
@@ -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(),
|
|
@@ -12431,6 +12433,8 @@ var init_admin_projections = __esm(() => {
|
|
|
12431
12433
|
complete: boolean2(),
|
|
12432
12434
|
ok: literal(true),
|
|
12433
12435
|
processed: CountSchema,
|
|
12436
|
+
rebuildRowsWalked: CountSchema.optional(),
|
|
12437
|
+
rebuildStaleFamilies: CountSchema.optional(),
|
|
12434
12438
|
scheduled: CountSchema,
|
|
12435
12439
|
status: ProjectionStatusSchema.optional(),
|
|
12436
12440
|
target: ProjectionTargetSchema,
|
|
@@ -12448,9 +12452,33 @@ var init_admin_projections = __esm(() => {
|
|
|
12448
12452
|
status: ProjectionStatusSchema,
|
|
12449
12453
|
target: ProjectionCutoverSchema
|
|
12450
12454
|
}));
|
|
12455
|
+
rekeyDueWorkQueue = oc.route({
|
|
12456
|
+
method: "POST",
|
|
12457
|
+
operationId: "rekeyDueWorkQueue",
|
|
12458
|
+
path: "/admin/projections/due-work/{workKind}/rekey",
|
|
12459
|
+
summary: "Mark one due-work queue for re-keying under today's order definition",
|
|
12460
|
+
tags: ["Admin"]
|
|
12461
|
+
}).input(object({
|
|
12462
|
+
apply: boolean2().default(false),
|
|
12463
|
+
cursor: string2().max(200).nullable().default(null),
|
|
12464
|
+
limit: number2().int().min(1).max(DUE_WORK_REKEY_LIMIT_MAX).default(DUE_WORK_REKEY_LIMIT_MAX),
|
|
12465
|
+
workKind: string2().min(1).max(64)
|
|
12466
|
+
})).output(object({
|
|
12467
|
+
applied: boolean2(),
|
|
12468
|
+
cursor: string2().nullable(),
|
|
12469
|
+
definitionVersion: string2(),
|
|
12470
|
+
hasMore: boolean2(),
|
|
12471
|
+
marked: CountSchema,
|
|
12472
|
+
matched: CountSchema,
|
|
12473
|
+
ok: literal(true),
|
|
12474
|
+
remaining: BoundedCountSchema,
|
|
12475
|
+
subjectType: string2(),
|
|
12476
|
+
workKind: string2()
|
|
12477
|
+
}));
|
|
12451
12478
|
adminProjectionsContract = {
|
|
12452
12479
|
advance_projection: advanceProjection,
|
|
12453
12480
|
get_projection_status: getProjectionStatus,
|
|
12481
|
+
rekey_due_work_queue: rekeyDueWorkQueue,
|
|
12454
12482
|
set_projection_cutover: setProjectionCutover
|
|
12455
12483
|
};
|
|
12456
12484
|
});
|
|
@@ -16842,32 +16870,84 @@ async function getProjectionStatusCommand() {
|
|
|
16842
16870
|
return adminApiGet("/api/v1/admin/projections/status");
|
|
16843
16871
|
}
|
|
16844
16872
|
async function advanceProjectionCommand(input) {
|
|
16845
|
-
const {
|
|
16873
|
+
const {
|
|
16874
|
+
includeTerminalStatus = true,
|
|
16875
|
+
maxSteps = 1,
|
|
16876
|
+
now = () => Date.now(),
|
|
16877
|
+
target,
|
|
16878
|
+
wallMs,
|
|
16879
|
+
...body
|
|
16880
|
+
} = input;
|
|
16846
16881
|
if (!includeTerminalStatus && input.action !== "repair") {
|
|
16847
16882
|
throw new Error("terminal status may be omitted only for repair automation");
|
|
16848
16883
|
}
|
|
16849
16884
|
const stepBody = maxSteps > 1 || !includeTerminalStatus ? { ...body, includeStatus: false } : body;
|
|
16885
|
+
const startedAt = now();
|
|
16850
16886
|
let response = await adminApiPost(`/api/v1/admin/projections/${target}/advance`, stepBody);
|
|
16851
16887
|
let steps = 1;
|
|
16852
16888
|
let processed = response.processed;
|
|
16853
16889
|
let scheduled = response.scheduled;
|
|
16890
|
+
let wallStopped = false;
|
|
16891
|
+
let rebuildRowsWalked = response.rebuildRowsWalked ?? 0;
|
|
16854
16892
|
while (!response.complete && steps < maxSteps) {
|
|
16893
|
+
if (wallMs !== undefined && now() - startedAt >= wallMs) {
|
|
16894
|
+
wallStopped = true;
|
|
16895
|
+
break;
|
|
16896
|
+
}
|
|
16855
16897
|
response = await adminApiPost(`/api/v1/admin/projections/${target}/advance`, stepBody);
|
|
16856
16898
|
steps += 1;
|
|
16857
16899
|
processed += response.processed;
|
|
16858
16900
|
scheduled += response.scheduled;
|
|
16901
|
+
rebuildRowsWalked += response.rebuildRowsWalked ?? 0;
|
|
16859
16902
|
}
|
|
16903
|
+
const rebuild = response.rebuildStaleFamilies === undefined ? {} : { rebuildRowsWalked, rebuildStaleFamilies: response.rebuildStaleFamilies };
|
|
16860
16904
|
if (!includeTerminalStatus) {
|
|
16861
16905
|
const { status: _status, ...withoutStatus } = response;
|
|
16862
|
-
return { ...withoutStatus, processed, scheduled, steps };
|
|
16906
|
+
return { ...withoutStatus, ...rebuild, processed, scheduled, steps, wallStopped };
|
|
16863
16907
|
}
|
|
16864
16908
|
const status = response.status ?? (await getProjectionStatusCommand()).status;
|
|
16865
|
-
return { ...response, processed, scheduled, status, steps };
|
|
16909
|
+
return { ...response, ...rebuild, processed, scheduled, status, steps, wallStopped };
|
|
16866
16910
|
}
|
|
16867
16911
|
async function setProjectionCutoverCommand(input) {
|
|
16868
16912
|
const { enabled, target } = input;
|
|
16869
16913
|
return adminApiPut(`/api/v1/admin/projections/${target}/cutover`, { enabled });
|
|
16870
16914
|
}
|
|
16915
|
+
async function rekeyDueWorkQueueCommand(input) {
|
|
16916
|
+
const { apply, limit, maxPages, workKind } = input;
|
|
16917
|
+
let cursor = input.cursor;
|
|
16918
|
+
let response = await adminApiPost(`/api/v1/admin/projections/due-work/${encodeURIComponent(workKind)}/rekey`, { apply, cursor, limit });
|
|
16919
|
+
let pages = 1;
|
|
16920
|
+
let marked = response.marked;
|
|
16921
|
+
let matched = response.matched;
|
|
16922
|
+
cursor = response.cursor;
|
|
16923
|
+
while (apply && response.hasMore && response.cursor !== null && pages < maxPages) {
|
|
16924
|
+
response = await adminApiPost(`/api/v1/admin/projections/due-work/${encodeURIComponent(workKind)}/rekey`, { apply, cursor, limit });
|
|
16925
|
+
pages += 1;
|
|
16926
|
+
marked += response.marked;
|
|
16927
|
+
matched += response.matched;
|
|
16928
|
+
cursor = response.cursor;
|
|
16929
|
+
}
|
|
16930
|
+
return { ...response, cursor, marked, matched, pages };
|
|
16931
|
+
}
|
|
16932
|
+
function parseDueWorkRekeyLimit(value) {
|
|
16933
|
+
const limit = Number(value);
|
|
16934
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > DUE_WORK_REKEY_LIMIT_MAX) {
|
|
16935
|
+
throw new Error(`--limit must be a whole number from 1 through ${DUE_WORK_REKEY_LIMIT_MAX}`);
|
|
16936
|
+
}
|
|
16937
|
+
return limit;
|
|
16938
|
+
}
|
|
16939
|
+
function parseDueWorkRekeyMaxPages(value) {
|
|
16940
|
+
const pages = Number(value);
|
|
16941
|
+
if (!Number.isSafeInteger(pages) || pages < 1 || pages > DUE_WORK_REKEY_MAX_PAGES) {
|
|
16942
|
+
throw new Error(`--max-pages must be a whole number from 1 through ${DUE_WORK_REKEY_MAX_PAGES}`);
|
|
16943
|
+
}
|
|
16944
|
+
return pages;
|
|
16945
|
+
}
|
|
16946
|
+
function dueWorkRekeyLine(result) {
|
|
16947
|
+
const remaining = `${result.remaining.count}${result.remaining.truncated ? "+" : ""}`;
|
|
16948
|
+
const verb = result.applied ? `marked ${result.marked}` : `would mark ${result.matched}`;
|
|
16949
|
+
return `${result.workKind} re-key — ${verb} over ${result.pages} page(s); ${remaining} still on the old key; cursor ${result.cursor ?? "start"}; definition ${result.definitionVersion}.`;
|
|
16950
|
+
}
|
|
16871
16951
|
function parseProjectionEnabled(value) {
|
|
16872
16952
|
if (value !== "true" && value !== "false") {
|
|
16873
16953
|
throw new Error("--enabled must be true or false");
|
|
@@ -16888,6 +16968,13 @@ function parseProjectionMaxSteps(value) {
|
|
|
16888
16968
|
}
|
|
16889
16969
|
return maxSteps;
|
|
16890
16970
|
}
|
|
16971
|
+
function parseProjectionWallMs(value) {
|
|
16972
|
+
const wallMs = Number(value);
|
|
16973
|
+
if (!Number.isSafeInteger(wallMs) || wallMs < PROJECTION_WALL_MS_MIN || wallMs > PROJECTION_WALL_MS_MAX) {
|
|
16974
|
+
throw new Error(`--wall-ms must be a whole number of milliseconds from ${PROJECTION_WALL_MS_MIN} through ${PROJECTION_WALL_MS_MAX}`);
|
|
16975
|
+
}
|
|
16976
|
+
return wallMs;
|
|
16977
|
+
}
|
|
16891
16978
|
function parseProjectionTarget(value) {
|
|
16892
16979
|
if (value !== "artist_qualification" && value !== "crawl_due_work" && value !== "public_aggregates" && value !== "track_due_work") {
|
|
16893
16980
|
throw new Error("--target must be artist_qualification, crawl_due_work, public_aggregates, or track_due_work");
|
|
@@ -16915,7 +17002,7 @@ function projectionStatusLines(status) {
|
|
|
16915
17002
|
row("Artist qualification", status.projections.artistQualification, status.cutovers.publicProjections)
|
|
16916
17003
|
];
|
|
16917
17004
|
}
|
|
16918
|
-
var PROJECTION_MAX_STEPS = 100;
|
|
17005
|
+
var PROJECTION_MAX_STEPS = 100, DUE_WORK_REKEY_MAX_PAGES = 200, PROJECTION_WALL_MS_MIN = 1000, PROJECTION_WALL_MS_MAX = 600000;
|
|
16919
17006
|
var init_admin_projections2 = __esm(() => {
|
|
16920
17007
|
init_orpc();
|
|
16921
17008
|
init_api();
|
|
@@ -21744,7 +21831,7 @@ JSON field reference:
|
|
|
21744
21831
|
console.log(projectionStatusLines(result.status).join(`
|
|
21745
21832
|
`));
|
|
21746
21833
|
});
|
|
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) => {
|
|
21834
|
+
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
21835
|
const projections = await Promise.resolve().then(() => (init_admin_projections2(), {}));
|
|
21749
21836
|
const action = parseProjectionAction(options.action);
|
|
21750
21837
|
if (!options.terminalStatus && (!options.json || action !== "repair")) {
|
|
@@ -21755,13 +21842,29 @@ JSON field reference:
|
|
|
21755
21842
|
includeTerminalStatus: options.terminalStatus,
|
|
21756
21843
|
limit: parseProjectionLimit(options.limit),
|
|
21757
21844
|
maxSteps: options.maxSteps === undefined ? undefined : parseProjectionMaxSteps(options.maxSteps),
|
|
21758
|
-
target: parseProjectionTarget(options.target)
|
|
21845
|
+
target: parseProjectionTarget(options.target),
|
|
21846
|
+
wallMs: options.wallMs === undefined ? undefined : parseProjectionWallMs(options.wallMs)
|
|
21847
|
+
});
|
|
21848
|
+
if (options.json) {
|
|
21849
|
+
printJson(result);
|
|
21850
|
+
return;
|
|
21851
|
+
}
|
|
21852
|
+
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"}.`);
|
|
21853
|
+
});
|
|
21854
|
+
adminProjections.command("rekey").description("Mark one due-work queue for re-keying under today's order definition").requiredOption("--work-kind <kind>", "Physical queue, e.g. capture-catalogue").option("--cursor <subjectId>", "Resume after this subject id").option("--limit <limit>", "Rows per page (1-500)", "500").option("--max-pages <pages>", "Maximum pages to mark in one run (1-200)", "1").option("--apply", "Write the repair markers; omit for a dry run", false).option("--json", "Print the page result as JSON", false).action(async (options) => {
|
|
21855
|
+
const projections = await Promise.resolve().then(() => (init_admin_projections2(), {}));
|
|
21856
|
+
const result = await rekeyDueWorkQueueCommand({
|
|
21857
|
+
apply: options.apply,
|
|
21858
|
+
cursor: options.cursor ?? null,
|
|
21859
|
+
limit: parseDueWorkRekeyLimit(options.limit),
|
|
21860
|
+
maxPages: parseDueWorkRekeyMaxPages(options.maxPages),
|
|
21861
|
+
workKind: options.workKind
|
|
21759
21862
|
});
|
|
21760
21863
|
if (options.json) {
|
|
21761
21864
|
printJson(result);
|
|
21762
21865
|
return;
|
|
21763
21866
|
}
|
|
21764
|
-
console.log(
|
|
21867
|
+
console.log(dueWorkRekeyLine(result));
|
|
21765
21868
|
});
|
|
21766
21869
|
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
21870
|
const projections = await Promise.resolve().then(() => (init_admin_projections2(), {}));
|
|
@@ -25762,6 +25865,7 @@ var stringOptions = new Set([
|
|
|
25762
25865
|
"--lens",
|
|
25763
25866
|
"--limit",
|
|
25764
25867
|
"--max-hop",
|
|
25868
|
+
"--max-pages",
|
|
25765
25869
|
"--max-steps",
|
|
25766
25870
|
"--max-overlap",
|
|
25767
25871
|
"--metrics",
|
|
@@ -25820,8 +25924,10 @@ var stringOptions = new Set([
|
|
|
25820
25924
|
"--video-url",
|
|
25821
25925
|
"--view",
|
|
25822
25926
|
"--voice-id",
|
|
25927
|
+
"--wall-ms",
|
|
25823
25928
|
"--window-since",
|
|
25824
|
-
"--window-until"
|
|
25929
|
+
"--window-until",
|
|
25930
|
+
"--work-kind"
|
|
25825
25931
|
]);
|
|
25826
25932
|
var rootHelpSections = `
|
|
25827
25933
|
|
package/package.json
CHANGED