mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-26 17:12:27 +03:00
fix(sessions): preserve legacy data when exclusive projection fails (#11469)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. - Focused test: exclusive-session-observability.test.ts — part of sub-batch's 165/165 node:test run - typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK - Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff Thanks for the narrow failure boundary and the privacy-conscious warning (proven not to leak the caught error's sensitive fields) — a projection failure discarding valid legacy data was a real regression from #11389.
This commit is contained in:
@@ -2,7 +2,7 @@ import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import test, { mock } from "node:test";
|
||||
|
||||
import {
|
||||
buildExclusiveDashboardSessions,
|
||||
@@ -319,6 +319,84 @@ test("sessions API keeps legacy fields additive and decorates only in-flight lea
|
||||
assert.deepEqual(releasedBody.exclusiveSessions, []);
|
||||
});
|
||||
|
||||
test("sessions API deduplicates projection warnings per contiguous outage", async () => {
|
||||
const secretFailure = {
|
||||
ownerHash: "d".repeat(64),
|
||||
generation: 91,
|
||||
apiKeyId: "private-api-key-id",
|
||||
credential: "private-credential",
|
||||
token: "private-token",
|
||||
connectionIdentity: "private-connection-identity",
|
||||
leaseOwnership: "private-lease-ownership",
|
||||
fencingMaterial: "private-fencing-material",
|
||||
};
|
||||
const nowMock = mock.method(Date, "now", () => BASE_TIME);
|
||||
sessionManager.touchSession("legacy-fallback", "legacy-connection");
|
||||
sessionManager.registerKeySession("legacy-key", "legacy-fallback");
|
||||
|
||||
const db = core.getDbInstance();
|
||||
const originalPrepare = db.prepare.bind(db);
|
||||
let projectionFails = true;
|
||||
const prepareMock = mock.method(db, "prepare", (sql: string) => {
|
||||
if (projectionFails) throw new Error(JSON.stringify(secretFailure));
|
||||
return originalPrepare(sql);
|
||||
});
|
||||
const warnings: unknown[][] = [];
|
||||
const warnMock = mock.method(console, "warn", (...args: unknown[]) => {
|
||||
warnings.push(args);
|
||||
});
|
||||
|
||||
try {
|
||||
const firstResponse = await sessionsRoute.GET();
|
||||
const firstBody = (await firstResponse.json()) as {
|
||||
count: number;
|
||||
sessions: Array<{ sessionId: string; connectionId: string | null }>;
|
||||
byApiKey: Record<string, number>;
|
||||
exclusiveSessions: unknown[];
|
||||
};
|
||||
const secondResponse = await sessionsRoute.GET();
|
||||
const secondBody = (await secondResponse.json()) as typeof firstBody;
|
||||
|
||||
assert.equal(firstResponse.status, 200);
|
||||
assert.equal(secondResponse.status, 200);
|
||||
assert.deepEqual(secondBody, firstBody);
|
||||
assert.equal(firstBody.count, 1);
|
||||
assert.equal(firstBody.sessions[0].sessionId, "legacy-fallback");
|
||||
assert.equal(firstBody.sessions[0].connectionId, "legacy-connection");
|
||||
assert.deepEqual(firstBody.byApiKey, { "legacy-key": 1 });
|
||||
assert.deepEqual(firstBody.exclusiveSessions, []);
|
||||
assert.deepEqual(warnings, [["[SESSIONS] Exclusive session projection unavailable"]]);
|
||||
|
||||
projectionFails = false;
|
||||
const recoveredResponse = await sessionsRoute.GET();
|
||||
assert.equal(recoveredResponse.status, 200);
|
||||
projectionFails = true;
|
||||
|
||||
const laterOutageResponse = await sessionsRoute.GET();
|
||||
const laterOutageBody = (await laterOutageResponse.json()) as typeof firstBody;
|
||||
assert.equal(laterOutageResponse.status, 200);
|
||||
assert.deepEqual(laterOutageBody, firstBody);
|
||||
assert.deepEqual(warnings, [
|
||||
["[SESSIONS] Exclusive session projection unavailable"],
|
||||
["[SESSIONS] Exclusive session projection unavailable"],
|
||||
]);
|
||||
|
||||
const observableOutput = JSON.stringify({
|
||||
firstBody,
|
||||
secondBody,
|
||||
laterOutageBody,
|
||||
warnings,
|
||||
});
|
||||
for (const forbidden of Object.values(secretFailure)) {
|
||||
assert.equal(observableOutput.includes(String(forbidden)), false);
|
||||
}
|
||||
} finally {
|
||||
warnMock.mock.restore();
|
||||
prepareMock.mock.restore();
|
||||
nowMock.mock.restore();
|
||||
}
|
||||
});
|
||||
|
||||
test("sessions route keeps raw lease SQL out of the API and sanitizes failures", () => {
|
||||
const route = fs.readFileSync(
|
||||
new URL("../../src/app/api/sessions/route.ts", import.meta.url),
|
||||
|
||||
Reference in New Issue
Block a user