Skip to content

[Feature] Poison-pill quarantine after N failures on same message digest #222

Description

@pathosDev

Size / Priority

  • Size: S

Rationale

If the SAME message kills the actor N times in a row, it's a poison pill. Restarting forever is unhelpful — better to quarantine the message and keep the actor alive.

Design sketch

// src/internal/PoisonPillDetector.ts (new)

export interface PoisonPillOptions {
  /** N identical-message failures before quarantine.  Default: 3. */
  readonly maxFailuresPerMessage?: number;
  /** What to do with quarantined messages: log + drop, or send to DeadLetters.  Default: deadletters. */
  readonly quarantineAction?: 'log' | 'deadletters';
}

Implementation:

  • Per-actor map: Map<messageDigest, failureCount>.
  • On supervision failure: increment count for the offending message.
  • When count >= max: drop the message; emit PoisonPillQuarantined event.

Digest: hash of JSON.stringify(message) (caveats: large messages, non-stringifiable values; document).

Integration

  • Supervision: existing pathway.
  • Metrics: actor_poison_pills_total{actor.path}.
  • DeadLetters: optional sink.

Out of scope / non-goals

  • Cross-actor poison detection — out of scope.
  • Strict exactly-same-bytes detection — digest-based is sufficient.

Open design questions

  1. Digest method: SHA-256 (collision-safe, slow) vs FNV-1a (fast, collision-prone). Recommend FNV-1a (collisions extremely unlikely + speed matters).
  2. Cap on tracking map size: bounded LRU.

Test plan

  1. Send panic message 3× → restart 3× → 4th time quarantined; actor alive.
  2. Different messages don't accumulate together.
  3. Quarantined message in DeadLetters.
  4. Metric increments.
  5. Map size capped.

Acceptance criteria

  • PoisonPillOptions per actor.
  • Digest + counter per message.
  • Quarantine action.
  • Metrics + dead-letters integration.
  • Documentation.
  • Test suite (5 cases).
  • CHANGELOG entry.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: lowNice-to-have / niche / demand-driven

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions