mirror of
https://github.com/block/buzz.git
synced 2026-11-01 06:51:17 +00:00
Round-8 fixes for #3966: 1. allocateGeneration() primitive (pendingOverrideIntents.ts) Preflights BOTH the emitted gen AND _nextGen+1 before any mutation. If either is unsafe, throws without touching any queue/transaction map. Replaces both post-increment isSafeInteger guards in enqueue() and promoteDeferred(). promoteDeferred() now allocates FIRST, then mutates deferredEnqueues/promotedDeferredPayloads — so an allocation failure leaves the deferred payload untouched and abortTransaction can safely re-buffer it. 2. Hydration rebase boundary (readStateStorage.ts) Condition order swapped: rebase checked before clamp. New trigger: !isSafeInteger(requiredNextGen) || requiredNextGen >= MAX_SAFE_INTEGER This catches maxObservedGen = MAX_SAFE_INTEGER-1 (requiredNextGen = MAX_SAFE_INTEGER), which previously passed the isSafeInteger check and took the clamp path, leaving nextGen=MAX_SAFE_INTEGER and one tick from poisoning _nextGen. Added isSafeInteger guard to ng serialization. 3. Promotion allocation failure → total-closure exit (readStateDrain.ts) promoteDeferred() call in step-3 is now wrapped in try-catch. If allocateGeneration throws, the catch calls abortTransaction + scheduleAbortRetry and continues, same as other non-success exits. 4. drainPendingIntents finally (readStateManager.ts) Wrapped in try-finally so drainScheduled=false always clears, even on an escaped exception from the impl. Condensed JSDoc for scheduleDrain to stay within the 1000-line ratchet. 5. Two new witnesses (Tests 60, 61): - Test 60: pi.gen=MAX-1, ng=MAX-1 → hydrate → rebase fires → two enqueues get safe distinct gens, neither throws, persisted ng safe, both intents survive fresh-manager hydration. - Test 61: _nextGen forced to MAX_SAFE_INTEGER via restoreFromStorage with deferred gen2 mid-transaction → drain → allocation throws in promoteDeferred → catch routes to abortTransaction+scheduleAbortRetry → drainScheduled false, drainRetryTimer set, gen1 live, deferred payload preserved → hydrateFromLocalStorage normalizes _nextGen to 2 → retry drain completes gen1+gen2, frontier ≥ 999. Optional MINOR (explicit typed pass outcome): skipped. The change would require threading a return value through drainPendingIntentsImpl and its caller, adding several lines to files already near the ratchet. The current drainRetryTimer === null discrimination is sound for the synchronous impl. Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Buzz
Desktop chat shell with:
- Tauri + React + TypeScript + Vite
- Tailwind CSS
- shadcn/ui-ready shared components
- Biome (lint/format/check)
- Feature-driven frontend structure
Scripts
pnpm dev- run the web frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm format- Biome format (write)pnpm check- Biome check
Structure
src/shared- reusable app-wide code (ui,lib,styles)src/features- feature modules (vertical slices)src/app- top-level app composition