Atomic Triggers
An HTTP route is one way to reach a function. A queue and a schedule are the other two, and neither needs a caller: the slice invokes the function on your behalf.
Queue-triggered functions
A function doesn't have to be called over HTTP. Swap the trigger in its directive and the slice polls a Backbone queue on your behalf:
# @atomic queue=orders auth=none
def handle_order(body, req):
# body is the message that was pushed onto the "orders" queue
drift.backbone.nosql.collection("orders").insert(body)
return 200, "OK", {"stored": True}A queue handler takes the body shape, (body, req), and the popped message is the body. It returns the same three (or four, in Go) values an HTTP handler does.
| Behaviour | Value |
|---|---|
| Poll interval | 500 ms |
| Retries | 3. A failed message is requeued with its retry count; once exhausted it moves to <queue>-dlq. |
| What counts as a failure | The invocation errored, or the handler returned a 5xx status. |
| Reachability | Registered under a synthetic queue method that no HTTP request can match, so a queue handler has no URL. |
| Function name | The queue name when the handler lives in an element (the common case); the folder basename when deployed on its own with drift atomic deploy ./folder. |
None of those defaults are visible from the annotation, and the annotation cannot change them. Since any HTTP function has a public URL, an http=post:… function is your webhook receiver. Point Stripe, GitHub or your provider straight at it.
Scheduled functions
A schedule is declared in the Driftfile, not in the directive. Give a function a cron: and it runs on that schedule in addition to staying callable over HTTP. Same code, two triggers:
atomic:
functions:
- { name: nightly-rollup, cron: "0 2 * * *" } # 02:00 daily
- { name: hourly-cleanup, cron: "0 * * * *" }Standard 5-field POSIX cron: minute hour day-of-month month day-of-week. Seconds and the 6-field quartz format are not supported. The schedule registers as part of the deploy, with no post-deploy step, and the deploy is refused if it would push the slice past its scheduled-job allowance.
Each fire delivers a small JSON body, so a scheduled handler takes the body shape:
{ "fired_at": "<RFC 3339 timestamp>", "schedule": "0 2 * * *" }Anything else the handler needs comes from secrets or Backbone.