ReviewOS

also looking at this

pantry-pm/pantry

fix: hydrate durable registry snapshots before serving writes

#244
Merged chris wants to merge codex/wildloop-registry-rollout into main
11 files +202 -35

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

packages/registry/src/storage/build-status.tsmodified+15-2
Changes to packages/registry/src/storage/build-status.ts
@@ -179,6 +179,7 @@ export class BuildStatusStore {
179179 private unavailable = new Map<string, UnavailableVersion>()
180180 private snapshot: ObjectSnapshot
181181 private coverageSnapshot: ObjectSnapshot
182 private hydrated = false
182183
183184 // Derived coverage cache (domain -> version -> set of platforms) + freshness.
184185 private coverage = new Map<string, Map<string, Set<string>>>()
@@ -203,8 +204,18 @@ export class BuildStatusStore {
203204 private logs = new Map<string, BuildLogLine[]>()
204205
205206 constructor(private s3: S3Client, private bucket: string) {
206 this.snapshot = new ObjectSnapshot(s3, bucket, 'build-status/status.json', () => this.captureState())
207 this.coverageSnapshot = new ObjectSnapshot(s3, bucket, 'build-status/coverage.json', () => this.captureCoverage())
207 this.snapshot = new ObjectSnapshot(s3, bucket, 'build-status/status.json', () => {
208 this.assertHydrated()
209 return this.captureState()
210 })
211 this.coverageSnapshot = new ObjectSnapshot(s3, bucket, 'build-status/coverage.json', () => {
212 this.assertHydrated()
213 return this.captureCoverage()
214 })
215 }
216
217 private assertHydrated(): void {
218 if (!this.hydrated) throw new Error('Build status snapshots have not been applied')
208219 }
209220
210221 /**
@@ -312,6 +323,7 @@ export class BuildStatusStore {
312323 }
313324
314325 async load(): Promise<void> {
326 this.hydrated = false
315327 const [state, coverage] = await Promise.all([
316328 this.snapshot.load() as Promise<PersistedState | null>,
317329 this.coverageSnapshot.load() as Promise<PersistedCoverage | null>,
@@ -344,6 +356,7 @@ export class BuildStatusStore {
344356 if (event.state === 'built' && event.version)
345357 this.mergeCoverage(event.domain, event.version, event.platform, new Date(event.ts).toISOString())
346358 }
359 this.hydrated = true
347360 }
348361
349362 private key(e: { domain: string, version: string, platform: string }): string {