API

Prev Next

Polling Manager API

The Polling Manager exposes a compact API focused on keyed polling lifecycle and subscription control.

Exports

import { PollingManager, pollingManager } from '@/lib/internal/PollingManager';
import type { SubscribeOptions, SubscribeResult, PollingManagerStatus } from '@/lib/internal/PollingManager';

Constructor

new PollingManager(deps?: PollingManagerDeps)

PollingManagerDeps

type PollingManagerDeps = {
  scheduler?: PollingScheduler;
  documentRef?: PollingDocument;
  now?: () => number;
};
  • scheduler overrides timer scheduling (tests/custom runtimes)
  • documentRef enables visibility-aware pause/resume behavior
  • now controls subscription ID timestamp source (test determinism)

If documentRef is not supplied, visibility handling is disabled.

subscribe<T>(options)

subscribe<T>(options: SubscribeOptions<T>): SubscribeResult<T>

SubscribeOptions<T>

type SubscribeOptions<T> = {
  key: string;
  intervalMs: number;
  pollFn: () => Promise<T>;
  onResult: (result: T) => void;
  onError?: (error: unknown) => void;
  shouldStop?: (result: T) => boolean;
  pauseWhenHidden?: boolean;
};

SubscribeResult<T>

type SubscribeResult<T> = {
  subscriptionId: string;
  unsubscribe: () => void;
  update: (updates: { onResult?: (result: T) => void; onError?: (error: unknown) => void }) => void;
};

Subscription semantics

  • First subscriber for a key triggers immediate poll (no deferred-first-tick mode)
  • Later same-key subscribers attach only (no extra immediate poll)
  • Same key dedups to one task/timer across subscribers
  • update only changes callbacks; task-defining fields are immutable
  • Public ID-based unsubscribe is intentionally not exposed
  • Same-key task-definition mismatch fails fast (pollFn, intervalMs, shouldStop, pauseWhenHidden)

pause and resume

pause(options?: { key?: string }): void
resume(options?: { key?: string }): void
  • No args: apply globally
  • With key: apply to one task
  • Visibility pause takes precedence while document is hidden; global resume() does not override hidden-state pause for pauseWhenHidden tasks

getStatus

getStatus(): PollingManagerStatus
type PollingManagerStatus = {
  status: 'idle' | 'running' | 'paused';
  taskCount: number;
  subscriptionCount: number;
  tasks: Array<{
    key: string;
    status: 'idle' | 'running' | 'paused';
    subscriptionCount: number;
    inFlight: boolean;
    pauseWhenHidden: boolean;
  }>;
};

stopAll

stopAll(): void

Stops all active tasks and clears subscriptions.

v1 Behavior Contract

  • Immediate first poll on every new subscription
  • In-flight overlap protection (skip interval tick while current poll is pending)
  • Terminal auto-stop via shouldStop(result) === true
  • Errors notify onError and keep task alive by default
  • Visibility behavior applies only when a document reference is injected

Key naming convention

Recommended format:

<domain>:<resource>:<id>[:variant]

Examples:

  • live:status:channel-123
  • encoding:progress:vod-889
  • jobs:chapter-sync:job-42

For complete integration patterns, see Examples.