ADR-004: Task Delivery and Leases
Status: PROPOSED.
Context
CURRENT: Scan messages are pushed to Redis with LPush and consumed with BRPop.
Source references:
- Queue key and queue interface:
backend/internal/scans/service.go:18 - Enqueue:
backend/internal/scans/service.go:171 - Dequeue:
backend/internal/scans/worker.go:97
This removes the task from Redis before execution completes. It does not provide durable acknowledgement, visibility timeout, or lease ownership.
Proposal
Use PostgreSQL-backed task state and lease ownership, with Redis notifications as an optional wake-up mechanism.
Core concepts:
- task;
- attempt;
- lease;
- lease token;
- attempt deadline;
- idempotency key;
- terminal state;
- retry policy.
Gateway replicas acquire tasks through transactional state changes. Workers must renew leases for long-running scans. Result submission and completion are authorized against the active lease.
Delivery guarantee
The realistic guarantee is at-least-once task delivery with idempotent ingestion boundaries.
The architecture must not claim exactly-once execution.
Required behaviors
- Lost Worker connection eventually expires the lease.
- Expired attempts cannot overwrite newer attempts.
- Duplicate result submission is rejected or idempotently ignored.
- Completion requires the active lease.
- Cancellation is durable and visible to Gateway and Worker.
- Terminal failure is explicit.
Alternatives
- Continue Redis list queue.
- Redis Streams consumer groups.
- Direct in-memory Gateway queue.
Consequences
- Requires database schema design before implementation.
- Redis can remain useful for notifications.
- Reliability semantics become explicit and testable.
Unresolved
- Exact task table schema.
- Retry limits.
- Dead-letter representation.
- Lease duration defaults.
- Long-running scan progress requirements.