mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
fix(migrate): run migrate deploy in a UTC session
Prisma ignores PGTZ, so a database whose default zone is not UTC ran every migration in that zone, and a migration mixing timestamp and timestamptz wrote shifted values. The boot wrapper now appends -c TimeZone=UTC to the options parameter of DATABASE_URL for its Prisma calls, honouring DATABASE_SESSION_OPTIONS_DISABLED like the app does.
This commit is contained in:
1 parent
67cc56f707
commit
b90c82cba3
4 files changed
+264
No files matched your search
@@ -24,7 +24,9 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
import {
|
||||
decideLockRetry,
|
||||
lockTimeoutInReport,
|
||||
prismaEnv,
|
||||
retryDelays,
|
||||
utcSessionUrl,
|
||||
} from "../migrate-deploy.mjs";
|
||||
|
||||
const P3018_LOCK = `Applying migration \`0412_measurement_hot_updates\`
|
||||
@@ -167,6 +169,53 @@ describe("which failure is retried", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the session time zone Prisma migrates in", () => {
|
||||
const options = (url: string | undefined) =>
|
||||
new URL(url ?? "").searchParams.get("options");
|
||||
|
||||
it("pins TimeZone=UTC through the libpq options parameter", () => {
|
||||
const url = utcSessionUrl(
|
||||
"postgresql://u:p@db:5432/healthlog?schema=public",
|
||||
);
|
||||
expect(options(url)).toBe("-c TimeZone=UTC");
|
||||
expect(new URL(url ?? "").searchParams.get("schema")).toBe("public");
|
||||
});
|
||||
|
||||
it("appends to options the operator set, so a later -c wins", () => {
|
||||
const url = utcSessionUrl(
|
||||
"postgresql://u:p@db/h?options=-c%20TimeZone%3DEurope%2FBerlin",
|
||||
);
|
||||
expect(options(url)).toBe("-c TimeZone=Europe/Berlin -c TimeZone=UTC");
|
||||
// Running it again adds nothing.
|
||||
expect(utcSessionUrl(url)).toBe(url);
|
||||
});
|
||||
|
||||
it("leaves a URL alone when the startup options are switched off", () => {
|
||||
const raw = "postgresql://u:p@db/h?schema=public";
|
||||
expect(utcSessionUrl(raw, { optionsDisabled: true })).toBe(raw);
|
||||
expect(
|
||||
prismaEnv({ DATABASE_URL: raw, DATABASE_SESSION_OPTIONS_DISABLED: "1" })
|
||||
.DATABASE_URL,
|
||||
).toBe(raw);
|
||||
});
|
||||
|
||||
it("passes an unset or unparseable URL through untouched", () => {
|
||||
expect(utcSessionUrl(undefined)).toBeUndefined();
|
||||
expect(utcSessionUrl("")).toBe("");
|
||||
expect(utcSessionUrl("not a url")).toBe("not a url");
|
||||
expect(prismaEnv({}).DATABASE_URL).toBeUndefined();
|
||||
});
|
||||
|
||||
it("hands Prisma the pinned URL and keeps the rest of the environment", () => {
|
||||
const env = prismaEnv({
|
||||
DATABASE_URL: "postgresql://u:p@db/h",
|
||||
HEALTHLOG_X: "1",
|
||||
});
|
||||
expect(options(env.DATABASE_URL)).toBe("-c TimeZone=UTC");
|
||||
expect(env.HEALTHLOG_X).toBe("1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("the retry loop", () => {
|
||||
const dirs: string[] = [];
|
||||
afterEach(() => {
|
||||
|
||||
Reference in new issue
Block a user