|
This version is still in development and is not considered stable yet. |
Queue Channel Adapter
The queue adapter is the entrance of an internal flow: a named queue, inside the PipeliteContext, that one flow reads and that any other flow (or the application) can put an Exchange on. It is how flows are chained.
Usage
// Main flow
Pipelite.defineFlow("main-flow")
.fromSource("http://ingest")
.process("enrich", (exchange, contribution) -> { /* enrichment */ })
.toSink("queue://secondary") (1)
.build();
// Secondary flow
Pipelite.defineFlow("secondary-flow")
.fromSource("queue://secondary") (2)
.process("finalize", (exchange, contribution) -> { /* ... */ })
.toSink("slf4j://output")
.build();
| 1 | queue://secondary as a destination puts the Exchange on the queue named secondary. |
| 2 | queue://secondary as a source declares that this flow reads that queue. The same URL on both sides: what one flow writes to, the other reads from. |
URL format
queue://<queue-name>
| Parameter | Description |
|---|---|
|
The name of the queue. Not the flow’s own |
Every endpoint is a URL
A flow is always addressed by URL, and queue://<queue name> is the URL of an internal one. The same rule holds everywhere a destination is written - toSink(…), the destinations of toRoute(…) and toRecipientList(…), wireTap(…), toChannel(…) - and for PipeliteContext.supplyExchange(…). A source and a sink are URLs too: fromSource(…) and toSink(…) always take a protocol (and a flow that has nothing to deliver simply leaves toSink out). A bare name is neither a destination, nor a source, nor a sink, and it is rejected when the flow is defined - or, for a value that is only known at runtime, when the endpoint is created or the exchange is delivered.
.fromSource("orders")
// IllegalArgumentException: fromSource("orders"): 'orders' is not a URL - a source always has a protocol.
// Write 'queue://orders' for the queue in front of an internal flow, or the protocol of the channel adapter
// that feeds it (http://, kafka://, ...)
Characteristics
-
One queue, one flow, N consumers. A queue is read by exactly one flow. To process its Exchanges concurrently, declare
concurrencyon the source (?concurrency=N, orfromSource("queue://orders", (SourceConcurrencyConfigurer c) → c.concurrency(N))): the N consumers of the queue all run that flow. It is the only source that can declareconcurrency- see Flow Definition. -
The sender enqueues and moves on: the receiving flow runs on the consumer threads of its own queue, not on the sender’s thread. If the queue is full the sender waits (backpressure), so a slow flow slows its senders down instead of letting the queue grow without limit.
-
The queue holds the
Exchangeitself: the receiving flow gets the very instance the sender handed over, not a copy. With the durable inbox on (the default for every source excepttime://-durableInbox=falseopts one out, see Time Channel Adapter for whytime://inverts that default) a serialized copy is also written to disk before the Exchange is enqueued, so it survives a restart. -
The queue lives in memory, inside one
PipeliteContext: it is not a broker and does not reach another process. To leave the process, use a channel adapter such askafka://. -
Useful for splitting complex pipelines into modular, reusable flows.
Startup validation
PipeliteContext.start() checks that every queue:// target is a queue that a flow registered in the same context reads: the destinations of toSink(…), of the routes and the recipient list, of wireTap(…), and the target of toChannel(…), alone or as the exhaustion action of a retry. If one is not - a typo, a rename on one side only - start() throws a ContextValidationException that lists every problem, naming the flow and the DSL construct, before anything is started.
A destination that contains an expression (#{…}) is only known when an exchange is routed, so it is not checked at startup; if it names no flow then, the delivery fails with an IllegalArgumentException. Destinations with any other protocol are not checked either.
Because a queue is read by exactly one flow, start() also fails if two flows declare the same queue:// source. The error names the second flow and the one that read the queue first, and points at concurrency as the way to scale it. Only queues count: http://orders, queue://orders and two flows reading the same Kafka topic can coexist, since what belongs to a flow - its durable inbox, the resumption of its retries - is keyed by the flow’s name and not by the resource of its source.