Skip to content

Decouple dead-worker task reclaim (xAutoClaim min-idle) from taskDebounce #71

Description

@bgeils

Problem

stream.js uses taskDebounce as the xAutoClaim min-idle when claiming tasks:

const reclaimedTasks = await this.redis.xAutoClaim(this.workerStreamName, this.workerGroupName, this.consumername, this.taskDebounce, '0', { COUNT: count })

taskDebounce is fundamentally a scheduling knob — how long a room's task waits after activity before compaction runs. Deployments tune it large to batch compaction work (we run 30 minutes in production to keep worker load sane on large docs).

But because the same value is the reclaim min-idle, it also becomes the failure-recovery latency: when a worker dies ungracefully (OOM, node crash, SIGKILL), its claimed task — lease renewals stopped — sits unclaimed for a full taskDebounce before any surviving worker may pick it up. With a 30-minute debounce, one worker crash means that document's persistence stalls for up to 30 minutes while its edits accumulate only in Redis. The blast radius of Redis loss during that window is exactly the unpersisted backlog this project's quarantine machinery exists to guard.

stopWorker()'s doc comment acknowledges the coupling ("they go stale and are reclaimed by another worker after redis.taskDebounce").

Proposal

Add a separate redis.taskTimeout (reclaim min-idle) defaulting to taskDebounce for compatibility:

  • claimTasks uses taskTimeout as the xAutoClaim min-idle.
  • _renewLeases renews at a cadence safely below taskTimeout (today it presumably tracks taskDebounce; the renewal interval and the reclaim idle need to be related to each other, not to the scheduling debounce).
  • Constraint check at config time: renewal interval < taskTimeout, so live tasks are never reclaimed out from under a healthy worker.

That lets a deployment run taskDebounce: 30min for scheduling while keeping dead-worker recovery at, say, 60–120s.

Context

@y/hub 0.7.0. Related operational context: we just added graceful SIGTERM draining on our side (stop claiming + wait for in-flight tasks) so routine rollouts don't strand tasks — this issue is about the remaining ungraceful-kill window that only an upstream knob can shrink.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions