fix: close Release A monitor migration blockers
This commit is contained in:
@@ -37,7 +37,7 @@ import { probeSentinelRuntimeHealthEndpoint, runSentinelDashboard, runSentinelEr
|
||||
import { runChildCli, sentinelP5Next } from "./hwlab-node-web-sentinel-p5-observe";
|
||||
import { emitWebProbeSentinelSpan, webProbeSentinelOtelSummary } from "./hwlab-node-web-sentinel-otel";
|
||||
import { exportMonitorSqliteSnapshot, planMonitorSqliteSources, verifyMonitorSqliteSnapshot, type MonitorSqliteSource } from "./monitor-sqlite-migration";
|
||||
import { releaseAMonitorManifests } from "./hwlab-node-web-probe-monitor";
|
||||
import { releaseAMonitorManifests, releaseAMonitorMigrationPool } from "./hwlab-node-web-probe-monitor";
|
||||
import {
|
||||
arrayAt,
|
||||
arrayAtNullable,
|
||||
@@ -209,25 +209,28 @@ function runSentinelMigration(spec: HwlabRuntimeLaneSpec, options: Extract<WebPr
|
||||
}
|
||||
if (options.snapshotPath === null) throw new Error(`web-probe sentinel migration ${options.action} requires --snapshot`);
|
||||
const snapshot = JSON.parse(readFileSync(options.snapshotPath, "utf8")) as Parameters<typeof verifyMonitorSqliteSnapshot>[0];
|
||||
const source = sources.find((item) => sameMigrationSource(item, snapshot.source));
|
||||
if (source === undefined) throw new Error("migration snapshot source is not in the current resolved registry");
|
||||
const verification = verifyMonitorSqliteSnapshot(snapshot);
|
||||
if (verification.ok !== true) throw new Error("migration snapshot verification failed");
|
||||
if (options.action === "import") {
|
||||
const source = sources.find((item) => item.sentinelId === snapshot.source.sentinelId && item.runtimeConfigRef === snapshot.source.runtimeConfigRef);
|
||||
if (source === undefined) throw new Error("migration snapshot source is not in the current resolved registry");
|
||||
const runtime = recordTarget(readWebProbeSentinelConfigRefTarget(spec, source.runtimeConfigRef), source.runtimeConfigRef);
|
||||
const poolMax = numberAtNullable(runtime, "monitor.migration.poolMax");
|
||||
const idleTimeoutSeconds = numberAtNullable(runtime, "monitor.migration.idleTimeoutSeconds");
|
||||
if (stringAtNullable(runtime, "monitor.migration.databaseUrlSourceRef") === null || stringAtNullable(runtime, "monitor.migration.databaseUrlTargetKey") !== "DATABASE_URL" || poolMax === null || idleTimeoutSeconds === null) throw new Error("monitor.migration must declare databaseUrlSourceRef, databaseUrlTargetKey=DATABASE_URL, poolMax, and idleTimeoutSeconds");
|
||||
if (!process.env.DATABASE_URL) throw new Error("monitor migration DATABASE_URL must be injected by the controlled Secret consumer");
|
||||
const result = runCommand(["bun", "scripts/monitor-sqlite-migration-import.ts", options.snapshotPath], repoRoot, { timeoutMs: 120_000, env: { ...process.env, MONITOR_CENTRAL_PG_POOL_MAX: String(poolMax), MONITOR_CENTRAL_PG_IDLE_TIMEOUT_SECONDS: String(idleTimeoutSeconds) } });
|
||||
const pool = releaseAMonitorMigrationPool(spec, source);
|
||||
const result = runCommand(["bun", "scripts/monitor-sqlite-migration-import.ts", options.snapshotPath], repoRoot, { timeoutMs: 120_000, env: { ...process.env, MONITOR_CENTRAL_PG_POOL_MAX: String(pool.poolMax), MONITOR_CENTRAL_PG_IDLE_TIMEOUT_SECONDS: String(pool.idleTimeoutSeconds) } });
|
||||
const projection = parseJsonObject(result.stdout) ?? { ok: false, command, error: "monitor-migration-import-unparseable", stderr: short(result.stderr), valuesRedacted: true };
|
||||
return rendered(projection.ok === true, command, renderMigrationCompact(projection), projection);
|
||||
}
|
||||
if (!process.env.DATABASE_URL) throw new Error("monitor migration verify requires DATABASE_URL projected from hwlab-web-probe-monitor-db/DATABASE_URL");
|
||||
const result = runCommand(["bun", "scripts/monitor-sqlite-migration-verify.ts", options.snapshotPath], repoRoot, { timeoutMs: 120_000, env: { ...process.env, MONITOR_CENTRAL_PG_POOL_MAX: "4", MONITOR_CENTRAL_PG_IDLE_TIMEOUT_SECONDS: "30" } });
|
||||
const pool = releaseAMonitorMigrationPool(spec, source);
|
||||
const result = runCommand(["bun", "scripts/monitor-sqlite-migration-verify.ts", options.snapshotPath], repoRoot, { timeoutMs: 120_000, env: { ...process.env, MONITOR_CENTRAL_PG_POOL_MAX: String(pool.poolMax), MONITOR_CENTRAL_PG_IDLE_TIMEOUT_SECONDS: String(pool.idleTimeoutSeconds) } });
|
||||
const projection = parseJsonObject(result.stdout) ?? { ok: false, command, error: "monitor-migration-verify-unparseable", stderr: short(result.stderr), valuesRedacted: true };
|
||||
return rendered(projection.ok === true, command, renderMigrationCompact(projection), projection);
|
||||
}
|
||||
|
||||
function sameMigrationSource(left: MonitorSqliteSource, right: MonitorSqliteSource): boolean {
|
||||
return left.sentinelId === right.sentinelId && left.node === right.node && left.lane === right.lane && left.path === right.path && left.runtimeConfigRef === right.runtimeConfigRef && left.stateRoot === right.stateRoot && left.ownerPvc === right.ownerPvc;
|
||||
}
|
||||
|
||||
function resolvedMigrationSources(spec: HwlabRuntimeLaneSpec, sentinelId: string | null): readonly MonitorSqliteSource[] {
|
||||
const ids = sentinelId === null ? webProbeSentinelRegistryRows(spec).filter((item) => item.enabled).map((item) => item.id) : [sentinelId];
|
||||
return ids.map((id) => {
|
||||
@@ -1302,7 +1305,7 @@ function renderSentinelManifests(
|
||||
spec: { type: "ClusterIP", selector: { "app.kubernetes.io/name": deploymentName }, ports: [{ name: "http", port: servicePort, targetPort: "http" }] },
|
||||
},
|
||||
...(cadenceJob === null ? [] : [cadenceJob]),
|
||||
...releaseAMonitorManifests(spec),
|
||||
...releaseAMonitorManifests(spec, image.ref, resolvedMigrationSources(spec, sentinelId)[0] ?? (() => { throw new Error("Release A monitor requires one resolved migration source"); })()),
|
||||
{
|
||||
apiVersion: "apps/v1",
|
||||
kind: "Deployment",
|
||||
|
||||
Reference in New Issue
Block a user