React — advanced usage

Escape hatches past the binding layer: connectWorker tuning, per-call abort/timeout, shared observables, and pool lifecycle — same APIs under every framework's idiom.

Tuning the pool

connectWorker folds the WorkerPool config into the client declaration — size, queueing, timeouts, crash respawn.

incidents.tsfrontend
export const incidents = connectWorker<IncidentsWorker>({
  sharedMemory: incidentsMemory,
  worker: () => new Worker(
    new URL('./incidents.worker.ts', import.meta.url),
    { type: 'module' },
  ),
  poolSize: 'auto',    // navigator.hardwareConcurrency
  concurrency: 1,      // in-flight tasks per worker; excess queue FIFO
  maxQueue: 1_000,     // a full queue rejects with PoolQueueFullError
  respawn: true,       // replace crashed workers (default)
  taskTimeout: 5_000,  // default per-call budget — with({timeout}) overrides
  // lazy: false,      // spawn immediately instead of on first call
});

Abort & timeout per call

with() returns the same client surface with RunOptions attached. A queued call drops outright; an in-flight call is orphaned — the worker finishes it and the reply is discarded.

frontend
import { TaskAbortedError, TaskTimeoutError } from '@atolljs/core';

const ac = new AbortController();
const request = incidents
  .with({ signal: ac.signal, timeout: 2_000 })
  .queryIncidents(query);

ac.abort();   // rejects with TaskAbortedError
try {
  await request;
} catch (e) {
  if (e instanceof TaskTimeoutError) { /* budget exceeded */ }
}

One observable, many components

Each useSharedValue call builds a fresh observe(). Hoist it to module scope and bind via useObservable — every subscriber shares one field watch, which stops when the last unsubscribes.

metrics.tsfrontend
import { observe, shallowEqual } from '@atolljs/core';
import { useObservable } from '@atolljs/react';
import { incidentsMemory } from '@atolljs/incidents';

export const pressure = observe(
  incidentsMemory,
  'state.metrics',
  (m) => ({ open: m.open, critical: m.critical }),
  { equals: shallowEqual },
);

// In any component: useObservable(pressure) — no new watch per mount.

Lifecycle & pool stats

terminate() kills the pool — the next method call re-spawns it lazily. pool.stats() exposes queue/dispatch aggregates for telemetry.

frontend
import { useEffect } from 'react';

// A feature panel that only keeps its pool while open:
useEffect(() => () => incidents.terminate(), []);

const stats = incidents.pool?.stats();
// { workers, idle, inFlight, queued, completed, failed, aborted,
//   waitMs: { count, mean, max }, runMs: { count, mean, max } }