Kyrux
Back

Queue

Background task queue, with a worker pool, automatic retry, and draining on shutdown. Enabled via QUEUE_ENABLED=true.

Cache, EventBus, and Queue play different roles:

Component Role Guarantee
fw.Cache Key/value storage with TTL Fast reads; data can expire
fw.Events (EventBus) Fire-and-forget pub/sub ALL subscribers receive it; no retry
fw.Queue Background task queue Each task processed by ONE worker, with retry and draining on shutdown

Use the Queue for work that can't be lost during a spike: emails, webhooks, media processing.

Configuration

QUEUE_ENABLED=true
QUEUE_DRIVER=memory   # memory | redis
QUEUE_WORKERS=4

# Only with QUEUE_DRIVER=redis — a queue shared across replicas via
# LPUSH/BRPOP, instead of a process-local channel:
QUEUE_ADDR=127.0.0.1:6379
QUEUE_PASSWORD=            # Redis AUTH; empty = no password

With QUEUE_DRIVER=redis, every replica of the process needs to register the same handlers — any replica can process a task enqueued by another. If the connection fails at boot, bootstrap falls back to an in-memory queue (not shared across replicas) and logs a warning, instead of refusing to start.

Registering handlers and enqueueing

// App's Register — before any Enqueue call:
fw.Queue.Register("email.welcome", func(payload any) error {
    return sendEmail(payload.(string)) // error ≠ nil → retry (3× with backoff)
})

// In the view:
if err := fw.Queue.Enqueue("email.welcome", user.Email); err != nil {
    // ErrQueueFull = explicit backpressure: decide between 503, logging, or retry
    log.Printf("queue full: %v", err)
}

On server shutdown the queue is drained before the process exits — enqueued tasks aren't lost during a deploy (in redis mode, tasks still in the list stay there for the next boot to consume). A panic in a handler doesn't bring down the worker (it's logged with a stack trace).