Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,6 @@ async function main(): Promise<void> {
"gittensory_jobs_dead_total",
"gittensory_jobs_rate_limited_total",
"gittensory_jobs_rate_limit_deferred_total",
"gittensory_jobs_deferred_total",
"gittensory_jobs_coalesced_total",
"gittensory_jobs_recovered_total",
]) {
Expand Down
33 changes: 33 additions & 0 deletions test/unit/server-persisted-job-metrics.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";

const read = (path: string) => readFileSync(path, "utf8");

// Regression for #2508: gittensory_jobs_deferred_total was registered as a persisted gauge in server.ts
// but no queue driver ever called recordQueueMetric with that name -- dead instrumentation that always
// reported 0. Pin the invariant the fix establishes: every metric name in server.ts's persisted-gauge list
// must have a real recordQueueMetric call site in BOTH queue drivers, so a future dead entry can't sneak
// back in the same way. Source-text assertions, not a runtime harness: server.ts has no test harness
// (it's Codecov-ignored) and this is a static wiring invariant, not runtime behavior.
describe("server.ts persisted job-queue metrics (#2508)", () => {
it("registers only metric names both sqlite-queue.ts and pg-queue.ts actually record", () => {
const server = read("src/server.ts");
const sqliteQueue = read("src/selfhost/sqlite-queue.ts");
const pgQueue = read("src/selfhost/pg-queue.ts");

const listMatch = server.match(
/const durableJobMetric[\s\S]*?for \(const name of \[([\s\S]*?)\]\) \{/,
);
expect(listMatch, "persisted-gauge metric list not found in server.ts").not.toBeNull();
const registered = [...listMatch![1]!.matchAll(/"([a-z_]+)"/g)].map((m) => m[1]!);
expect(registered.length).toBeGreaterThan(0);

for (const name of registered) {
const callSite = `recordQueueMetric(driver, "${name}"`;
expect(sqliteQueue.includes(callSite), `sqlite-queue.ts never calls recordQueueMetric for "${name}"`).toBe(true);
expect(pgQueue.includes(`recordQueueMetric("${name}"`), `pg-queue.ts never calls recordQueueMetric for "${name}"`).toBe(true);
}

expect(registered).not.toContain("gittensory_jobs_deferred_total");
});
});
Loading