Skip to content

v1.5.0 — @harperfast/prerender-browser

Choose a tag to compare

@harper-joseph harper-joseph released this 06 Jul 18:59
e69d90c

@harperfast/prerender-browser v1.5.0

Per-host claim/result resilience: the worker no longer busy-loops a drained queue, and it
backs off (circuit-breaks) a Harper host that is overloaded (503) or unreachable — while
picking up freshly-enqueued work promptly. Additive, backward-compatible config; no API
changes to startWorker.

What & why

Previously the claim loop re-hit /render_queue/claim back-to-back whenever local queue
state still said queued (e.g. the empty MQTT status hadn't propagated yet), and a
non-200 just logged and immediately retried — hammering an already-struggling host. The
idle path also slept an un-woken random up-to-60s, so an idle worker could take up to a
minute to pick up a new job.

This release introduces one per-host availability model (HostHealth) fed by three
signals:

  • Idle backoff. A zero-job claim (or an empty/paused queue_status message) parks
    that host for idleMs (default 15s, jittered) instead of re-polling immediately. The
    drained-queue busy-loop is gone.
  • Circuit breaker. A 503/429/502/504 or a network error on claim or
    job_result
    opens a per-host circuit with exponential, jittered backoff between minMs
    and maxMs, honoring a (positive, capped) Retry-After, with a half-open probe on
    recovery. Because claim and result share the per-host circuit, a result 503 also pauses
    claims to that host (no point claiming work you can't return).
  • Interruptible idle sleep. The wait wakes the instant a host becomes eligible — a
    queued status arrives, or a circuit clears after a successful result POST — so new work
    is picked up without waiting out a timer.

Plus: job_result POSTs now retry transient failures (bounded by resultRetries and
the job lease) so an expensive render isn't dropped on a blip, and the payload (incl. gzip)
is encoded once across retries.

New config (all optional, under startWorker({ backoff }))

option default meaning
idleMs 15000 delay before re-polling a host that reported empty/no work
minMs 1000 base circuit backoff on the first 503/unreachable
maxMs 30000 circuit backoff cap
pausedMs 30000 re-poll delay when a host reports paused
maxIdleMs 60000 cap on the idle sleep between poll re-evaluations
resultRetries 3 max job_result POST retries on 503/5xx/network before dropping

Notes

  • Consumer-side only — no plugin/response-shape change, so it interoperates with any
    running plugin. Queue status is reconciled from MQTT (timestamp-guarded against
    out-of-order/retained delivery) and from claim outcomes.
  • render() awaits sendResult() within a concurrency slot; result retries are capped at
    5s/attempt so a failing host can't pin slots (host-level backoff still applies via the
    shared circuit).
  • 42/42 tests pass; lint + format clean. dist/ is built at release time (gitignored).

Consuming

"@harperfast/prerender-browser": "https://github.com/HarperFast/prerender-plugin/releases/download/v1.5.0/harperfast-prerender-browser-1.5.0.tgz"