Skip to content

Delete the claim-check Redis key when the enqueue fails #217

Description

@HMarzban

Problem

The claim-check payload is written to Redis first, then the job is added (apps/hocuspocus.server/src/lib/queue.ts:156-157). If StoreDocumentQueue.add throws, the payload stays behind with no job that will ever read it. Nothing in enqueueStoreDocument catches that throw.

This is not a permanent leak. The write sets a TTL from const STATE_KEY_TTL_SECONDS = 3600 (apps/hocuspocus.server/src/lib/queue.ts:142). But a multi-megabyte document state then sits in Redis for up to an hour, doing nothing. refreshPendingStateKeyTtls cannot shorten that. It re-arms TTLs from job ids read off the wait and paused lists (apps/hocuspocus.server/src/lib/queue.ts:369-372). An orphan has no job on either list.

The orphans share one Redis keyspace with the rate limiter, as the comment at apps/hocuspocus.server/src/middleware/index.ts:52-55 records. Production runs that Redis with --maxmemory-policy volatile-lru (docker-compose.prod.yml:110). Eviction under that policy only picks keys that carry a TTL, and the claim-check states carry one. So during a queue outage the orphans raise eviction pressure on the live claim-check keys next to them.

What to do

Wrap the add call. On failure, delete stateKey before the error propagates to the caller. The same delete already exists for the success and DLQ paths (apps/hocuspocus.server/src/lib/queue.ts:518 and apps/hocuspocus.server/src/lib/queue.ts:605), so match that shape.

Acceptance

  • With the queue made to throw, no key with the store-doc-state: prefix (apps/hocuspocus.server/src/lib/queue.ts:137) survives the failed enqueue.
  • A successful enqueue still leaves its key for the worker to read.
  • The caller still sees the original add error, not a delete error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions