Invariants

Prev Next

Polling Manager Invariants

These invariants are runtime contracts. Breaking them changes system behavior and should be treated as a breaking internal change.

Invariant Map

Image

1. One key maps to one task/timer

Multiple subscribers for the same key must share one internal task and one interval schedule.

2. Ref-counted lifecycle is authoritative

  • First subscription initializes the task
  • Last unsubscribe tears task down completely
  • No timer may survive a zero-subscriber task

3. Immediate first poll is mandatory

subscribe(...) must execute a poll immediately for the first subscriber of a key and then continue on interval ticks.
Later same-key subscribers attach without triggering additional immediate polls.

4. No in-flight overlap for a key

If an interval tick fires while the previous poll is still pending, that tick is skipped.

5. Subscriber snapshot before callback iteration

Callback iteration must use a snapshot array to avoid mutation hazards:

const subscribers = [...task.subscribers.values()];

This protects iteration when callbacks unsubscribe during execution.

6. Callback updates are non-structural

subscription.update({ onResult, onError }) may replace callback references only.

It must not:

  • create new tasks
  • restart timers
  • alter ref counts
  • affect dedup semantics

7. Visibility behavior is opt-in by dependency

Visibility pause/resume works only when documentRef is injected.

No implicit global document fallback is allowed.
While hidden, visibility pause has precedence over global resume().

8. Errors do not auto-stop by default

pollFn errors are propagated to onError callbacks; task lifecycle continues unless terminal conditions are met through shouldStop on successful results.

9. Public API remains minimal

No public ID-based unsubscription path. Consumers own only the returned unsubscribe() function.

10. Same-key task definition is immutable

For an existing key, pollFn, intervalMs, shouldStop, and pauseWhenHidden must remain consistent.
Mismatched subscriptions fail fast and do not attach.