Angular — 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.
Route-scoped pools
provideAtoll works in Route.providers — the pool spawns when the route injector is created and terminates when it is destroyed. Lazy features get lazy pools.
const routes: Routes = [{
path: 'reports',
providers: [
provideAtoll({ pools: [{ name: 'incidents', client: incidents }] }),
],
loadComponent: () => import('./reports.component'),
}];Async pool declarations
registerPoolAsync/forRootAsync resolve the spec from injected deps during APP_INITIALIZER — name stays static so the ATOLL_POOL:<name> token is injectable throughout.
AtollModule.registerPoolAsync({
name: 'incidents',
inject: [PoolConfig],
useFactory: (config: PoolConfig) => ({
worker: () => new Worker(
new URL('./incidents.worker.ts', import.meta.url)),
sharedMemory: incidentsMemory,
poolSize: config.poolSize,
}),
})Testing — stub the pool token
Each pool is a plain InjectionToken (ATOLL_POOL:<name>) — override it in TestBed with a stub; the component never touches a real worker.
await TestBed.configureTestingModule({
providers: [
{ provide: getAtollPoolToken('incidents'), useValue: stubIncidents },
],
}).compileComponents();Abort & timeout per call
with() attaches RunOptions to the same client surface. A queued call drops outright; an in-flight call is orphaned — the worker finishes it and the reply is discarded.
import { TaskAbortedError, TaskTimeoutError } from '@atolljs/core';
const ac = new AbortController();
const request = this.incidents
.with({ signal: ac.signal, timeout: 2_000 })
.queryIncidents(query);
ac.abort(); // rejects with TaskAbortedError