Transport provider
Publish wakeups and connect a broker-native worker to Runlane.
A transport provider connects Runlane to a broker such as SQS. The broker carries wakeups. Storage still holds the task payload and current run state.
A complete transport provider has two sides:
Runlane outbox --> TransportDriver.publish() --> broker
broker --> ProviderDeliverySurface --> Runlane worker
|
v
handled / retry / rejectImport both contracts from @runlane/contracts.
Publish wakeups
TransportDriver.publish() receives a bounded array of messages. Each message already has canonical bytes, an outbox id, a logical queue, and an optional partition key.
The provider may group messages by destination or split them into native batches. It must return one outcome for each input, at the same array index.
| What happened | What the provider returns |
|---|---|
| The broker accepted one item | published at that item's index |
| One item failed and the result is certain | failed at that item's index |
| The whole request failed and item results are unknown | Reject the call |
Do not change the canonical message bytes. Return copies of mutable bytes and dates.
Deliver wakeups
ProviderDeliverySurface connects a native consumer to one Runlane DeliveryProcessor.
For each broker message:
- Read its Runlane bytes.
- Pass the bytes to the processor.
- Map the returned disposition to the broker action.
| Runlane disposition | Broker action |
|---|---|
handled | Acknowledge, delete, or commit the message |
retry | Leave it available for another delivery |
reject | Complete the configured terminal action |
If terminal handling fails, do not acknowledge the original rejected message. An unexpected processor error is retryable.
The provider owns receipt handles, offsets, visibility extensions, consumer groups, dead-letter configuration, and settlement. Those details do not enter core.
Choose the worker shapes
A provider can expose either or both:
createWorker()for a long-running receive loop;createHandler()for a platform-native serverless handler.
A long-running worker must support cooperative close() and observable waitUntilClosed(). Repeated closes should be safe. A background failure must reject waitUntilClosed().
Keep a serverless handler's native type in the lane generic. Do not add platform-specific event unions to Runlane core.
Report the real transport profile
Declare:
- maximum bytes in one message;
- maximum messages in one publish call;
- durability after the broker acknowledges a publish;
- whether ordering is absent or preserved within a partition for messages the broker accepts.
Broker ordering and Runlane queue concurrency are separate controls.
A failed per-message publish outcome has no broker position. If the caller retries it later, that retry is a later publish and may follow messages the broker already accepted from the original command. Do not claim original-command ordering across rejected entries unless the provider implements a durable sequencer or an equivalent guarantee.
Expect duplicate wakeups
A publish can succeed just before the publisher loses the response. Brokers can also redeliver messages.
Pass every valid wakeup to core. Do not treat the broker message as the job or invent provider-side run state. Core re-reads storage and decides whether the run can execute.
Prove the provider
Test batch results, partial failures, settlement, malformed messages, visibility or lock refresh, ordering, cancellation, and shutdown. Then run the same cases against the real broker.
Continue with test a provider. @runlane/transport-sqs is the shipped reference implementation, and the exact stable values are in delivery values.