Queue-type triggers with a durable local queue - #7
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Highest-leverage net-new feature for the agent-runtime story after the reliability work. Triggers supported
cronandwebhook; this adds event-driven work: atype = "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
queuetrigger type andqueuefield; validation requires a deliverypath.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.RunQueueTriggerspoller claims messages, wakes the app, and POSTs each body to the trigger path (X-Fold-Trigger/X-Fold-Message-Idheaders). At-least-once: acked only on a 2xx; failures and stale claims are redelivered.POST /v1/apps/{app}/triggers/{name}/publishandfold 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
queueconfig 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
httptestbackend)Verification
gofmt -lclean ·go vet ./...clean ·go test ./...all pass ·go build -tags firecracker ./...compilesfold 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