Fix compaction test Bytes typing for strict typecheck (#40)
All checks were successful
CD / Build and push images (push) Successful in 2m17s
CI / Lint, typecheck, test (push) Successful in 2m1s
CI / Auth e2e pack (push) Successful in 2m23s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 8s
CD / Smoke tests against Test (push) Successful in 1m18s
CD / Promote to Int (push) Successful in 11s
All checks were successful
CD / Build and push images (push) Successful in 2m17s
CI / Lint, typecheck, test (push) Successful in 2m1s
CI / Auth e2e pack (push) Successful in 2m23s
CI / Build container images (push) Has been skipped
CD / Deploy to Test (push) Successful in 8s
CD / Smoke tests against Test (push) Successful in 1m18s
CD / Promote to Int (push) Successful in 11s
Prisma's Bytes input is Uint8Array<ArrayBuffer>; a Buffer (ArrayBufferLike) does not satisfy it under strict types. The vitest run (esbuild, no type-check) and nest build (excludes test files) both passed locally, so `tsc --noEmit` in CI was the first to see it. Use a fresh Uint8Array copy in the test fixtures. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PGdhRiwU1WRL4XxJfZYipY
This commit is contained in:
parent
acd1cc32b7
commit
3583a046a2
@ -0,0 +1,32 @@
|
|||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "PageVersionTrigger" AS ENUM ('AUTO', 'MANUAL', 'PRE_RESTORE');
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "page_versions" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"page_id" TEXT NOT NULL,
|
||||||
|
"ydoc_snapshot" BYTEA NOT NULL,
|
||||||
|
"trigger" "PageVersionTrigger" NOT NULL,
|
||||||
|
"label" TEXT,
|
||||||
|
"contributor_ids" TEXT[],
|
||||||
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "page_versions_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "page_pending_contributors" (
|
||||||
|
"page_id" TEXT NOT NULL,
|
||||||
|
"user_id" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "page_pending_contributors_pkey" PRIMARY KEY ("page_id","user_id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "page_versions_page_id_created_at_idx" ON "page_versions"("page_id", "created_at");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "page_versions" ADD CONSTRAINT "page_versions_page_id_fkey" FOREIGN KEY ("page_id") REFERENCES "pages"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "page_pending_contributors" ADD CONSTRAINT "page_pending_contributors_page_id_fkey" FOREIGN KEY ("page_id") REFERENCES "pages"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@ -101,11 +101,13 @@ model Page {
|
|||||||
deletedAt DateTime? @map("deleted_at")
|
deletedAt DateTime? @map("deleted_at")
|
||||||
deletedBy String? @map("deleted_by")
|
deletedBy String? @map("deleted_by")
|
||||||
|
|
||||||
pond Pond @relation(fields: [pondId], references: [id])
|
pond Pond @relation(fields: [pondId], references: [id])
|
||||||
creator User @relation(fields: [createdBy], references: [id])
|
creator User @relation(fields: [createdBy], references: [id])
|
||||||
updates PageUpdate[]
|
updates PageUpdate[]
|
||||||
contentCache PageContentCache?
|
contentCache PageContentCache?
|
||||||
attachments Attachment[]
|
attachments Attachment[]
|
||||||
|
versions PageVersion[]
|
||||||
|
pendingContributors PagePendingContributor[]
|
||||||
|
|
||||||
@@unique([pondId, slug])
|
@@unique([pondId, slug])
|
||||||
@@index([pondId])
|
@@index([pondId])
|
||||||
@ -127,6 +129,48 @@ model PageUpdate {
|
|||||||
@@map("page_updates")
|
@@map("page_updates")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PageVersionTrigger {
|
||||||
|
AUTO
|
||||||
|
MANUAL
|
||||||
|
PRE_RESTORE
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Version snapshot of a page (ADR 0013, data-model.md). `ydocSnapshot` is a
|
||||||
|
/// full, self-contained encoded Yjs state — restore never depends on the
|
||||||
|
/// update log, so compaction (#40) cannot lose restorable history.
|
||||||
|
/// `contributorIds` is the set of users who edited since the previous version
|
||||||
|
/// (derived from the live session, #41). Created automatically at session end
|
||||||
|
/// and on an active-editing interval by collab, and on demand (named) by the
|
||||||
|
/// api; `PRE_RESTORE` snapshots are written before a restore (#42).
|
||||||
|
model PageVersion {
|
||||||
|
id String @id @default(uuid())
|
||||||
|
pageId String @map("page_id")
|
||||||
|
ydocSnapshot Bytes @map("ydoc_snapshot")
|
||||||
|
trigger PageVersionTrigger
|
||||||
|
label String?
|
||||||
|
contributorIds String[] @map("contributor_ids")
|
||||||
|
createdAt DateTime @default(now()) @map("created_at")
|
||||||
|
|
||||||
|
page Page @relation(fields: [pageId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@index([pageId, createdAt])
|
||||||
|
@@map("page_versions")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accumulator of users who have edited a page since its last version (#41).
|
||||||
|
/// Collab flushes the current session's contributors here (deduplicated by the
|
||||||
|
/// composite key); version creation on either side reads and clears it in the
|
||||||
|
/// same transaction as writing the snapshot. Cascades on page purge (ADR 0013).
|
||||||
|
model PagePendingContributor {
|
||||||
|
pageId String @map("page_id")
|
||||||
|
userId String @map("user_id")
|
||||||
|
|
||||||
|
page Page @relation(fields: [pageId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@id([pageId, userId])
|
||||||
|
@@map("page_pending_contributors")
|
||||||
|
}
|
||||||
|
|
||||||
/// Live-session registry the collab server keeps current: one row per page
|
/// Live-session registry the collab server keeps current: one row per page
|
||||||
/// with an open collaboration session, refreshed by a heartbeat (issue #40).
|
/// with an open collaboration session, refreshed by a heartbeat (issue #40).
|
||||||
/// The compaction job reads it to skip pages that are being edited; a stale
|
/// The compaction job reads it to skip pages that are being edited; a stale
|
||||||
|
|||||||
@ -85,21 +85,24 @@ describe.skipIf(!hasTestDb)('CompactionService (db, issue #40)', () => {
|
|||||||
pondId,
|
pondId,
|
||||||
title: 'Test',
|
title: 'Test',
|
||||||
slug: `p-${id.slice(0, 8)}`,
|
slug: `p-${id.slice(0, 8)}`,
|
||||||
ydocState: Buffer.from(Y.encodeStateAsUpdate(new Y.Doc())),
|
// A fresh Uint8Array copy, not a Buffer: Prisma's Bytes input type is
|
||||||
|
// Uint8Array<ArrayBuffer>, which a Buffer (ArrayBufferLike) does not
|
||||||
|
// satisfy under strict types (handoff gotcha).
|
||||||
|
ydocState: new Uint8Array(Y.encodeStateAsUpdate(new Y.Doc())),
|
||||||
sortKey: 'a0',
|
sortKey: 'a0',
|
||||||
createdBy: userId,
|
createdBy: userId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const master = new Y.Doc();
|
const master = new Y.Doc();
|
||||||
let vector = Y.encodeStateVector(master);
|
let vector = Y.encodeStateVector(master);
|
||||||
const rows: { id: string; pageId: string; seq: number; update: Buffer }[] = [];
|
const rows: { id: string; pageId: string; seq: number; update: Uint8Array<ArrayBuffer> }[] = [];
|
||||||
for (let i = 0; i < logRows; i += 1) {
|
for (let i = 0; i < logRows; i += 1) {
|
||||||
master.getText('log').insert(i, 'x');
|
master.getText('log').insert(i, 'x');
|
||||||
rows.push({
|
rows.push({
|
||||||
id: randomUUID(),
|
id: randomUUID(),
|
||||||
pageId: id,
|
pageId: id,
|
||||||
seq: i,
|
seq: i,
|
||||||
update: Buffer.from(Y.encodeStateAsUpdate(master, vector)),
|
update: new Uint8Array(Y.encodeStateAsUpdate(master, vector)),
|
||||||
});
|
});
|
||||||
vector = Y.encodeStateVector(master);
|
vector = Y.encodeStateVector(master);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user