Make OrganizationDataStoresRegistry deterministic on overlap

Sort findMany() by `key` for a stable winner when multiple rows assign the
same `${orgId}:${kind}`, and log an error identifying the winning and
ignored rows instead of overwriting silently. Does not fail the load —
failing the registry would break every customer, not just the misconfigured
orgs.

Co-Authored-By: Matt Aitken <matt@mattaitken.com>
This commit is contained in:
Devin AI
2026-04-17 11:27:52 +00:00
committed by Matt Aitken
parent 40f95a7ba7
commit 20fad45651
@@ -33,10 +33,18 @@ export class OrganizationDataStoresRegistry {
}
async loadFromDatabase(): Promise<void> {
const rows = await this._prisma.organizationDataStore.findMany();
// Sort by `key` (unique, immutable) to ensure a deterministic winner when the
// same `${orgId}:${kind}` appears in multiple rows. The registry must never
// throw on overlap — failing the load would break every customer, not just the
// misconfigured orgs — so we keep the first entry and log an error instead.
const rows = await this._prisma.organizationDataStore.findMany({
orderBy: { key: "asc" },
});
const secretStore = getSecretStore("DATABASE", { prismaClient: this._prisma });
const lookup = new Map<string, ParsedDataStore>();
/** Tracks which row's `key` already owns each `${orgId}:${kind}` so we can log conflicts. */
const winnerByLookupKey = new Map<string, string>();
for (const row of rows) {
let parsed: ParsedDataStore | null = null;
@@ -75,8 +83,16 @@ export class OrganizationDataStoresRegistry {
}
for (const orgId of row.organizationIds) {
const key = `${orgId}:${row.kind}`;
lookup.set(key, parsed);
const lookupKey = `${orgId}:${row.kind}`;
const existingWinner = winnerByLookupKey.get(lookupKey);
if (existingWinner) {
console.error(
`[OrganizationDataStoresRegistry] Overlapping OrganizationDataStore assignment for orgId="${orgId}" kind=${row.kind}: already routed to "${existingWinner}", ignoring "${row.key}". Pick one store per (org, kind) to resolve.`
);
continue;
}
winnerByLookupKey.set(lookupKey, row.key);
lookup.set(lookupKey, parsed);
}
}