Skip to content
File

Blob: test/packed-object-store.catalog.worker.test.ts

typescript102 lines
1import { describe, expect, it } from "vitest";
2import { env } from "cloudflare:workers";
3import { getDb, supersedePackCatalogRows } from "@/worker/do/repo/db";
4import {
5 buildPack,
6 callStubWithRetry,
7 readRepoCatalogState,
8 runDOWithRetry,
9 seedLegacyPackedRepo,
10 seedPackedRepo,
11 uniqueRepoId,
12} from "./util/test-helpers";
13import { encodeGitObject } from "@/worker/git/core";
14 
15describe("packed object store catalog", () => {
16 it("seeds active receive rows for packed repos", async () => {
17 const repoId = `o/${uniqueRepoId("pack-catalog")}`;
18 const id = env.REPO_DO.idFromName(repoId);
19 const getStub = () => env.REPO_DO.get(id);
20 const { getStub: seededStub } = await seedPackedRepo({ env, repoId, getStub });
21 
22 const catalog = await callStubWithRetry(seededStub, (stub) => stub.getActivePackCatalog());
23 expect(catalog.length).toBe(1);
24 expect(catalog[0]?.kind).toBe("receive");
25 expect(catalog[0]?.state).toBe("active");
26 expect(catalog[0]?.objectCount).toBe(4);
27 expect(catalog[0]?.packBytes).toBeGreaterThan(0);
28 expect(catalog[0]?.idxBytes).toBeGreaterThan(0);
29 });
30 
31 it("repeated catalog snapshots stay read-only after initial seed", async () => {
32 const repoId = `o/${uniqueRepoId("pack-catalog-snapshot")}`;
33 const id = env.REPO_DO.idFromName(repoId);
34 const getStub = () => env.REPO_DO.get(id);
35 const seeded = await seedPackedRepo({ env, repoId, getStub });
36 
37 const first = await callStubWithRetry(seeded.getStub, (stub) => stub.getActivePackCatalog());
38 expect(first).toHaveLength(1);
39 
40 const before = await readRepoCatalogState(seeded.getStub);
41 const second = await callStubWithRetry(seeded.getStub, (stub) => stub.getActivePackCatalog());
42 const after = await readRepoCatalogState(seeded.getStub);
43 
44 expect(second).toEqual(first);
45 expect(after.packsetVersion).toBe(before.packsetVersion);
46 expect(after.nextPackSeq).toBe(before.nextPackSeq);
47 expect(after.activeCatalog).toEqual(before.activeCatalog);
48 expect(after.catalog).toEqual(before.catalog);
49 });
50 
51 it("catalog snapshots do not reactivate superseded packs from legacy mirrors", async () => {
52 const repoId = `o/${uniqueRepoId("pack-superseded")}`;
53 const olderPayload = new TextEncoder().encode("older pack blob\n");
54 const newerPayload = new TextEncoder().encode("newer pack blob\n");
55 const olderBlob = await encodeGitObject("blob", olderPayload);
56 const newerBlob = await encodeGitObject("blob", newerPayload);
57 const id = env.REPO_DO.idFromName(repoId);
58 const getStub = () => env.REPO_DO.get(id);
59 
60 const { packKeys, getStub: seededStub } = await seedLegacyPackedRepo({
61 env,
62 repoId,
63 getStub,
64 packs: [
65 {
66 name: "pack-newer.pack",
67 packBytes: await buildPack([{ type: "blob", payload: newerPayload }]),
68 },
69 {
70 name: "pack-older.pack",
71 packBytes: await buildPack([{ type: "blob", payload: olderPayload }]),
72 },
73 ],
74 looseObjects: [olderBlob, newerBlob],
75 });
76 
77 const seeded = await callStubWithRetry(seededStub, (stub) => stub.getActivePackCatalog());
78 expect(seeded.map((row) => row.packKey)).toEqual(packKeys);
79 
80 await runDOWithRetry(seededStub, async (_instance, state: DurableObjectState) => {
81 const db = getDb(state.storage);
82 await supersedePackCatalogRows(db, [packKeys[1]], packKeys[0] || null);
83 });
84 
85 const beforeSnapshot = await readRepoCatalogState(seededStub);
86 expect(beforeSnapshot.activeCatalog.map((row) => row.packKey)).toEqual([packKeys[0]]);
87 expect(beforeSnapshot.catalog.find((row) => row.packKey === packKeys[1])?.state).toBe(
88 "superseded"
89 );
90 
91 const snapshot = await callStubWithRetry(seededStub, (stub) => stub.getActivePackCatalog());
92 const afterSnapshot = await readRepoCatalogState(seededStub);
93 
94 expect(snapshot.map((row) => row.packKey)).toEqual([packKeys[0]]);
95 expect(afterSnapshot.packsetVersion).toBe(beforeSnapshot.packsetVersion);
96 expect(afterSnapshot.nextPackSeq).toBe(beforeSnapshot.nextPackSeq);
97 expect(afterSnapshot.catalog.find((row) => row.packKey === packKeys[1])?.state).toBe(
98 "superseded"
99 );
100 });
101});