mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
test(backup): fill the parity account by key order and match audit rows by copy
A table read without an order comes back in whatever order its last updates left on disk, so the column fill could pick a different row of a two-row table from run to run. The audit rows of a restore are now found by the copy's id instead of by time, since the database clock and the test's clock do not agree to the millisecond. The golden copies are written again from the code before the restore and export moved.
This commit is contained in:
1 parent
e7b31fe8e0
commit
508e19f190
7 files changed
+85
-76
No files matched your search
@@ -249,20 +249,20 @@
|
||||
"id": "<id:4>",
|
||||
"type": "WEIGHT",
|
||||
"value": 74.2,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": null,
|
||||
"deviceType": null,
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -272,20 +272,20 @@
|
||||
"id": "<id:5>",
|
||||
"type": "IRREGULAR_RHYTHM_NOTIFICATION",
|
||||
"value": 1,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": "IRREGULAR",
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"deviceType": null,
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -2268,20 +2268,20 @@
|
||||
"id": "<id:4>",
|
||||
"type": "WEIGHT",
|
||||
"value": 74.2,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": null,
|
||||
"deviceType": null,
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -2291,20 +2291,20 @@
|
||||
"id": "<id:5>",
|
||||
"type": "IRREGULAR_RHYTHM_NOTIFICATION",
|
||||
"value": 1,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": "IRREGULAR",
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"deviceType": null,
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"deletedAt": null
|
||||
},
|
||||
{
|
||||
@@ -152,7 +152,7 @@
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"notes": null,
|
||||
"deletedAt": null
|
||||
}
|
||||
],
|
||||
@@ -1763,7 +1763,7 @@
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"deletedAt": null
|
||||
},
|
||||
{
|
||||
@@ -1773,7 +1773,7 @@
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"notes": null,
|
||||
"deletedAt": null
|
||||
}
|
||||
],
|
||||
|
||||
@@ -435,20 +435,20 @@
|
||||
"userId": "round-trip-owner",
|
||||
"type": "IRREGULAR_RHYTHM_NOTIFICATION",
|
||||
"value": 1,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"unit": "event",
|
||||
"source": "WITHINGS",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"notes": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": "IRREGULAR",
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"deviceType": null,
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -507,20 +507,20 @@
|
||||
"userId": "round-trip-owner",
|
||||
"type": "WEIGHT",
|
||||
"value": 74.2,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"unit": "kg",
|
||||
"source": "MANUAL",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": null,
|
||||
"deviceType": null,
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -2755,20 +2755,20 @@
|
||||
"id": "<id:4>",
|
||||
"type": "WEIGHT",
|
||||
"value": 74.2,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": null,
|
||||
"deviceType": null,
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -2778,20 +2778,20 @@
|
||||
"id": "<id:5>",
|
||||
"type": "IRREGULAR_RHYTHM_NOTIFICATION",
|
||||
"value": 1,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": "IRREGULAR",
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"deviceType": null,
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
|
||||
@@ -533,7 +533,7 @@
|
||||
"source": "WITHINGS",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"notes": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
@@ -581,7 +581,7 @@
|
||||
"source": "MANUAL",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
@@ -2519,7 +2519,7 @@
|
||||
"unit": "kg",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"source": "MANUAL",
|
||||
"notes": null,
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"deletedAt": null
|
||||
},
|
||||
{
|
||||
@@ -2529,7 +2529,7 @@
|
||||
"unit": "event",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"source": "WITHINGS",
|
||||
"notes": "rt-Measurement-notesEncrypted",
|
||||
"notes": null,
|
||||
"deletedAt": null
|
||||
}
|
||||
],
|
||||
|
||||
@@ -33,20 +33,20 @@
|
||||
"userId": "round-trip-owner",
|
||||
"type": "IRREGULAR_RHYTHM_NOTIFICATION",
|
||||
"value": 1,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"unit": "event",
|
||||
"source": "WITHINGS",
|
||||
"measuredAt": "2026-06-15T14:22:00.000Z",
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"externalId": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": "IRREGULAR",
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"deviceType": null,
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
@@ -105,20 +105,20 @@
|
||||
"userId": "round-trip-owner",
|
||||
"type": "WEIGHT",
|
||||
"value": 74.2,
|
||||
"valueMin": null,
|
||||
"valueMax": null,
|
||||
"valueMin": 2.5,
|
||||
"valueMax": 2.5,
|
||||
"unit": "kg",
|
||||
"source": "MANUAL",
|
||||
"measuredAt": "2026-07-01T07:00:00.000Z",
|
||||
"notes": null,
|
||||
"notesEncrypted": null,
|
||||
"notes": "rt-Measurement-notes",
|
||||
"notesEncrypted": "<sealed:rt-Measurement-notesEncrypted>",
|
||||
"externalId": null,
|
||||
"externalSourceVersion": null,
|
||||
"aggregationProvenance": null,
|
||||
"externalSourceVersion": "rt-Measurement-externalSourceVersion",
|
||||
"aggregationProvenance": "HEALTHKIT_STATISTICS",
|
||||
"glucoseContext": null,
|
||||
"sleepStage": null,
|
||||
"rhythmClassification": null,
|
||||
"deviceType": null,
|
||||
"deviceType": "rt-Measurement-deviceType",
|
||||
"syncVersion": 1,
|
||||
"deletedAt": null,
|
||||
"createdAt": "<now>",
|
||||
|
||||
@@ -1484,6 +1484,7 @@ export async function seedColumnShapes(prisma: PrismaClient): Promise<void> {
|
||||
export type Delegate = {
|
||||
findMany(args: {
|
||||
where: Record<string, unknown>;
|
||||
orderBy?: Record<string, "asc" | "desc">[];
|
||||
}): Promise<Record<string, unknown>[]>;
|
||||
update(args: {
|
||||
where: Record<string, unknown>;
|
||||
|
||||
@@ -397,8 +397,12 @@ async function fillDefaultedColumns(prisma: PrismaClient): Promise<string[]> {
|
||||
const enumValues = enumValuesFromSchema();
|
||||
const unfillable: string[] = [];
|
||||
for (const model of models) {
|
||||
// In key order, so the row that takes the fill is the same on every run:
|
||||
// a table read without an order comes back in whatever order its last
|
||||
// updates left on disk.
|
||||
const rows = await delegateOf(prisma, model).findMany({
|
||||
where: ownerWhere(byName, prisma, model.name, OWNER_ID),
|
||||
orderBy: model.primaryKey.map((key) => ({ [key]: "asc" as const })),
|
||||
});
|
||||
if (rows.length === 0) continue;
|
||||
for (const column of model.columns) {
|
||||
@@ -624,7 +628,6 @@ async function runRestore(
|
||||
effects.unitRefresh.length = 0;
|
||||
effects.foldRepair.length = 0;
|
||||
effects.annotations.length = 0;
|
||||
const auditFrom = new Date();
|
||||
const progress: Array<Record<string, unknown>> = [];
|
||||
const raw = await restoreBackup({
|
||||
backup,
|
||||
@@ -645,7 +648,12 @@ async function runRestore(
|
||||
},
|
||||
});
|
||||
const audit = await prisma.auditLog.findMany({
|
||||
where: { createdAt: { gte: auditFrom }, action: { startsWith: "admin." } },
|
||||
// By the copy's id rather than by time: the database clock and this
|
||||
// process's clock do not agree to the millisecond.
|
||||
where: {
|
||||
action: { startsWith: "admin." },
|
||||
details: { contains: backup.id },
|
||||
},
|
||||
orderBy: [{ createdAt: "asc" }, { id: "asc" }],
|
||||
select: { action: true, userId: true, details: true },
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user