Skip to content

Queue-type triggers with a durable local queue - #7

Merged
blakebauman merged 1 commit into
mainfrom
feat/queue-triggers
Jun 18, 2026
Merged

Queue-type triggers with a durable local queue#7
blakebauman merged 1 commit into
mainfrom
feat/queue-triggers

Conversation

@blakebauman

Copy link
Copy Markdown
Owner

Context

Highest-leverage net-new feature for the agent-runtime story after the reliability work. Triggers supported cron and webhook; this adds event-driven work: a type = "queue" trigger drains a message queue and delivers each message to the app, waking it first — so an agent processes a backlog at $0 idle cost between bursts.

Branched from a clean main.

What changed

  • config — new queue trigger type and queue field; validation requires a delivery path.
  • store — a durable SQLite-backed queue (queue_messages): publish, atomic claim (with a visibility timeout so a crashed delivery is redelivered), ack (delete), and requeue. This is the verified local provider.
  • controlRunQueueTriggers poller claims messages, wakes the app, and POSTs each body to the trigger path (X-Fold-Trigger / X-Fold-Message-Id headers). At-least-once: acked only on a 2xx; failures and stale claims are redelivered.
  • api / client / CLIPOST /v1/apps/{app}/triggers/{name}/publish and fold triggers publish <name> [--body | stdin].

Cloud sources (next step, intentionally not in this PR)

AWS SQS / GCP Pub/Sub slot in behind the same poller via the queue config field (already carries the queue URL/name). Left gated/unimplemented until run against the real target, per the repo's verified-core convention — so this PR ships only code that's actually exercised.

Tests

  • store: publish/claim/ack/requeue, claimed messages aren't double-claimed, and stale-claim redelivery
  • control: delivery acks on 2xx and requeues on 5xx (real httptest backend)
  • config: queue trigger requires a path; type/method parsed correctly

Verification

  • gofmt -l clean · go vet ./... clean · go test ./... all pass · go build -tags firecracker ./... compiles
  • Manual: deployed a scale-to-zero app with a queue trigger, fold triggers published two messages, and watched the poller wake the app and deliver each body — 200, then acked — confirmed in both the structured control log (queue message delivered) and the app activity stream (queue jobs delivered message to / -> 200 OK), no retries

🤖 Generated with Claude Code

Extends the trigger system beyond cron/webhook with event-driven work: a
`type = "queue"` trigger drains a message queue and delivers each message
to the app, waking it first — so an agent processes a backlog at $0 idle
cost between bursts.

- config: new `queue` trigger type + `queue` field; validation requires a
  delivery path.
- store: a durable SQLite-backed queue (queue_messages) with publish,
  atomic claim (with visibility timeout for crash recovery), ack, and
  requeue — the verified local provider.
- control: RunQueueTriggers poller claims messages, wakes the app, and
  POSTs each body to the trigger path. At-least-once: acked only on a 2xx;
  failures and stale claims are redelivered.
- api/client/CLI: POST /v1/apps/{app}/triggers/{name}/publish and
  `fold triggers publish <name> [--body | stdin]`.

Cloud sources (AWS SQS, GCP Pub/Sub) are the next step and slot in behind
the same poller via the `queue` config field — left gated/unimplemented
until run against the real target, per the verified-core convention.

Tests: store publish/claim/ack/requeue + stale-claim redelivery, control
delivery (acks on 2xx, requeues on 5xx), and config validation. Verified
end-to-end locally: published messages to a scaled-to-zero app and watched
the poller wake it and deliver each body (200, then acked).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@blakebauman
blakebauman merged commit 46a9f3e into main Jun 18, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant