ACTIAS

queue

Durable message queues and their handlers.

Declare

local mailroom = queue "mailroom"

on "queue:mailroom" (function(job)
    -- job is whatever was sent
end)

Top level only. The handler name must match the queue name exactly, and actias check refuses a queue with no handler or a handler with no queue.

Methods

MethodReturns
send(payload)true once the message is durable; a queue that cannot store it raises
stats()depth, in_flight, oldest_pending, dead_letters
FieldMeaning
depthevery message still queued
in_flightmessages due now, attempted or not
oldest_pendingwhen the oldest queued message was sent, platform clock in milliseconds
dead_lettersmessages on the dead-letter list

The payload must be JSON-representable, since a message can cross machines. A queue is one 64 MB file; a send past that raises.

Delivery

PromiseWhat your handler must do
at-least-oncetolerate running twice on one message
one message, one run, in order on one nodenothing; queues distribute, they do not broadcast
5 attempts, then dead-letteredthrow when the input can never work

The first retry waits 2 seconds and each further one doubles, capped at an hour. A dead letter stops retrying, does not block the queue, and waits in the console until you requeue or drop it.

Example

local catalog = database "catalog" { migrations = "migrations/catalog" }
local mailroom = queue "mailroom"

on "queue:mailroom" (function(job)
    if job.kind == "thumbnail" then
        local response = http.make_request({ uri = job.url, method = "GET" })
        catalog:exec("UPDATE listings SET preview = ? WHERE id = ?",
            { response.status_code == 200 and "ok" or "unavailable", job.id })
    end
end)

on "fetch" (function(request)
    mailroom:send({ kind = "thumbnail", id = "lot-1", url = "https://images.example.com/lot-1.jpg" })
    return { status_code = 202, body = "queued" }
end)

Gotchas

  • Throwing is how you dead-letter deliberately. A job whose input can never work should throw rather than silently succeed.
  • send returns before the handler runs, so a handler failure never surfaces at the call site. The console is where you see it.
  • A message delivered while its handler's script is unpublished counts as a failed attempt and dead-letters after five; it is not held.
  • Queues: when a queue is the wrong tool.
  • workflow: for jobs someone will ask about by name.