Files
Michael Ramos c2950e709f fix: pre-release QA findings for 0.27.9 (#1405)
Fixes from the 0.27.9 pre-release review. Servers: an unreadable rendered-HTML root falls back to the startup snapshot on both runtimes with a once-per-process warning instead of hanging (Pi) or answering 500 (Bun); the version diff is recomputed against current bytes on reload and carried through the in-app Refresh instead of being dropped, with no history write on a GET. Client: a Refresh action on the compact touch shell; HtmlSurfaceControls renders Refresh independently of the eye; the dead HtmlSurfaceActions removed. Threading: one linear, cycle-safe reply resolution shared by the annotations panel, its sort, and the export (5,000-chain tests), PATCH ingest on both runtimes rejects self-references and cycles, nothing is ever dropped from feedback. WebMCP and viewer hygiene: bounded tombstone and request memories, per-instance minted ids, nudge id caps, waiter cleanup on unmount, a shared retry epoch for diagram blocks. Docs: HTML Refresh documented, the WebMCP design pointer fixed, marketing pages updated.

AI-assisted (Claude) under maintainer direction.
2026-08-27 15:23:28 -07:00

32 lines
1.0 KiB
TypeScript

/**
* A shared retry epoch for lazily loaded diagram runtimes.
*
* Mermaid and Graphviz memoize one runtime per module, so when a chunk
* import fails every block on the page fails together. Each block's Retry
* button used to bump only that block's own token, leaving its siblings on
* their error panels after the shared runtime had recovered. Bumping the
* epoch notifies every subscribed block, so one Retry re-attempts all of
* them (the memoized loader still issues a single import for the batch).
*/
export interface RuntimeRetryEpoch {
/** Ask every subscriber to re-attempt. */
bump(): void;
/** Subscribe; returns the unsubscribe. */
subscribe(listener: () => void): () => void;
}
export function createRuntimeRetryEpoch(): RuntimeRetryEpoch {
const listeners = new Set<() => void>();
return {
bump() {
for (const listener of [...listeners]) listener();
},
subscribe(listener) {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
},
};
}