AppView in a box as a Vite plugin thing hatk.dev
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: handle missing root block in diff CARs and add SIGTERM handler

- Fall back to full import when diff CAR is missing root block (PDS
returned 200 but compacted past our since rev)
- Handle SIGTERM for graceful shutdown on container platforms

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+23 -3
+17 -3
packages/hatk/src/backfill.ts
··· 192 192 } 193 193 194 194 resolvedSince = lastRev 195 - const { roots, blocks, byteLength } = await parseCarStream(res.body!) 195 + let { roots, blocks, byteLength } = await parseCarStream(res.body!) 196 196 carSizeBytes = byteLength 197 197 198 - // Decode commit to get MST root 199 - const rootData = blocks.get(roots[0]) 198 + // Decode commit to get MST root — if the diff CAR is missing the root block, 199 + // fall back to a full import (the PDS compacted past our `since` rev) 200 + let rootData = blocks.get(roots[0]) 201 + if (!rootData && lastRev) { 202 + lastRev = null 203 + resolvedSince = null 204 + res = await fetch(baseUrl, { signal: controller.signal }) 205 + if (!res.ok) { 206 + const httpErr = new Error(`getRepo failed for ${did}: ${res.status}`) as Error & { httpStatus: number } 207 + httpErr.httpStatus = res.status 208 + throw httpErr 209 + } 210 + ;({ roots, blocks, byteLength } = await parseCarStream(res.body!)) 211 + carSizeBytes = byteLength 212 + rootData = blocks.get(roots[0]) 213 + } 200 214 if (!rootData) throw new Error(`No root block for ${did}`) 201 215 const { value: commit } = cborDecode(rootData) 202 216
+6
packages/hatk/src/main.ts
··· 195 195 .catch((err) => { 196 196 console.error('[main] Backfill error:', err.message) 197 197 }) 198 + 199 + // Graceful shutdown 200 + process.on('SIGTERM', () => { 201 + log('[main] Received SIGTERM, shutting down...') 202 + process.exit(0) 203 + })