Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion src/lib/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const KEY_PREFIX = "ocb:snap:v1:";
* new field don't try to deserialize old-shape values. The Zod schema
* below would also reject those, but the version prefix lets us
* invalidate without writing strict-mode parsers. */
const SCHEMA_VERSION = 1 as const;
const SCHEMA_VERSION = 2 as const;

// Minimal runtime payload. Editorial metadata isn't snapshotted because
// it lives in YAML and is rebuilt from the spec on every read.
Expand All @@ -57,13 +57,17 @@ const SnapshotSchema = z.object({
sampleSize: z.number(),
results: z.array(z.any()),
extras: z.any(),
bestPerChain: z.record(z.string(), z.any()).optional(),
worstPerChain: z.record(z.string(), z.any()).optional(),
});

export type SnapshotPayload = {
results: ProviderResult[];
extras: ResultExtras;
sampleSize: number;
lastRunAt: string;
bestPerChain?: Record<string, ProviderResult>;
worstPerChain?: Record<string, ProviderResult>;
};

function isConfigured(): boolean {
Expand Down Expand Up @@ -168,6 +172,12 @@ export async function readSnapshot(
extras: parsed.data.extras as ResultExtras,
sampleSize: parsed.data.sampleSize,
lastRunAt: parsed.data.lastRunAt,
bestPerChain: parsed.data.bestPerChain as
| Record<string, ProviderResult>
| undefined,
worstPerChain: parsed.data.worstPerChain as
| Record<string, ProviderResult>
| undefined,
};
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
Expand All @@ -190,5 +200,13 @@ export function snapshotFromBenchmark(b: Benchmark): SnapshotPayload {
extras: b.extras,
sampleSize: b.sampleSize,
lastRunAt: b.lastRunAt,
// Persist per-chain leader stash so the snapshot-recovery path
// (loadBenchmarkUnfilteredCached's KV fallback in spec.ts) can
// reconstruct a Benchmark that still resolves the
// `{{best_name:chain:X}}` / `{{best_p50:chain:X}}` family of
// placeholders. Without these, a cold-start fetched from the
// snapshot serves the raw placeholder string to the page.
bestPerChain: b.bestPerChain,
worstPerChain: b.worstPerChain,
};
}
5 changes: 4 additions & 1 deletion src/lib/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ const loadBenchmarkUnfilteredCached = unstable_cache(
},
// Version key bumped when Benchmark shape changes so stale cache entries
// from a previous deploy can't surface objects missing newer fields.
["bench-unfiltered-v2"],
// v3: added bestPerChain + worstPerChain stash; cached objects from
// v2 deploys lack those fields, which made `{{best_name:chain:X}}`
// placeholders fall through to the raw token on the rendered page.
["bench-unfiltered-v3"],
{ revalidate: 60, tags: ["benchmarks"] },
);

Expand Down
Loading