Skip to content

feat: add production-grade Web Worker data layer#658

Draft
Copilot wants to merge 2 commits intopreviewfrom
copilot/add-web-worker-data-layer
Draft

feat: add production-grade Web Worker data layer#658
Copilot wants to merge 2 commits intopreviewfrom
copilot/add-web-worker-data-layer

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 19, 2026

Implements a singleton, promise-based Web Worker data layer with cross-tab synchronisation, typed command dispatch, and a clean React hook API — no third-party abstractions.

Architecture

3-tier storage in the worker:

  • Tier 1 — Map<string, unknown>: hot-path in-memory store, pre-warmed from IndexedDB on init
  • Tier 2 — Dexie (arolariu-worker-state): durable persistence; written on SET/DELETE when persist=true
  • Tier 3 — BroadcastChannel: fans out mutations to all other tabs; receivers update memory only (no re-persist, no re-broadcast → loop-safe)

New files

src/lib/workerTypes.ts

Shared discriminated-union contract. PayloadFor<T> and WorkerResultTypeMap give end-to-end generic inference — no any.

src/workers/coreWorker.ts

Stateful dedicated worker. Dispatch uses an async IIFE per message for full concurrency with per-request error isolation. Processor registry uses the Map constructor pattern (no eval, no dynamic code):

// Built-in operations
const processorRegistry = new Map<string, WorkerProcessor>([
  ["FILTER_BY_PREFIX", (data, state) => { /* … */ }],
  ["COUNT",            (_data, state) => state.size],
  ["KEYS",             (_data, state) => [...state.keys()]],
  ["CLEAR_ALL",        async () => { store.clear(); await db.state.clear(); /* broadcast */ }],
]);

src/workers/client.ts

Singleton WorkerClient (private constructor + getInstance()). In-flight requests are tracked in a Map<uuid, {resolve, reject}> — safe for arbitrary parallelism. Discriminates the READY signal on data.type === "READY" so TypeScript correctly narrows to WorkerResponse in the response path. onReady() uses queueMicrotask and returns an unsubscribe function.

src/hooks/useWorkerThread.ts

"use client" hook. All returned methods are useCallback-stabilised (empty deps) — safe in useEffect dependency arrays. Single reactive ready flag. WorkerClient.getInstance() is called inside useEffect only, ensuring no SSR execution.

function InvoiceCache() {
  const { ready, get, set, query, process } = useWorkerThread();

  useEffect(() => {
    if (!ready) return;
    void query("invoice:", 100).then(setData);
  }, [ready, query]);

  const count = async () => process("COUNT") as Promise<number>;
}

Copilot AI and others added 2 commits April 18, 2026 20:10
- src/lib/workerTypes.ts: shared discriminated-union types (WorkerRequest,
  WorkerResponse, WorkerSyncMessage, WorkerProcessor, PayloadFor<T>)
- src/workers/coreWorker.ts: stateful worker with 3-tier storage
  (Map → Dexie/IndexedDB → BroadcastChannel cross-tab sync) and typed
  processor registry (FILTER_BY_PREFIX, COUNT, KEYS, CLEAR_ALL)
- src/workers/client.ts: singleton WorkerClient with UUID-keyed pending
  Map, queueMicrotask-based onReady, and high-level get/set/delete/query/process API
- src/hooks/useWorkerThread.ts: 'use client' hook with stable useCallback
  references, reactive ready flag, and SSR guard"

Agent-Logs-Url: https://github.com/arolariu/arolariu.ro/sessions/1cf624ba-6c0a-4ddc-9aaa-127809d69b6b

Co-authored-by: arolariu <56928070+arolariu@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants