Endpoint-Created PollingConsumer for pollEnrich
Status: Accepted (2026-06-07)
Implemented in branch rc-3y0-eip-7 per plan
docs/superpowers/plans/2026-06-07-rc-3y0-eip-7-content-enricher.md. All
acceptance criteria from bd rc-3y0 met; quality gates green.
The pollEnrich DSL verb resolves its URI to an Endpoint, calls the
existing Endpoint::polling_consumer() -> Option<Box<dyn PollingConsumer>>
opt-in method, and invokes receive(timeout) on the result. We rejected the
producer-side alternatives (file:...?mode=read bridge, new resource:
component) because they invert the Tower Service<Exchange> producer invariant
(write/send only) and would constitute fake URI reuse across the data plane,
violating ADR-0001 and ADR-0014. The PollingConsumer trait already lives in
crates/components/camel-component-api/src/endpoint.rs; this ADR records the
decision to wire it up for the EIP-7 Content Enricher use case rather than
introduce a new mechanism.
Considered Options
- A. Endpoint-created PollingConsumer (chosen) — reuse the existing
PollingConsumertrait; endpoints opt in by overridingpolling_consumer(). File/SEDA/JMS can returnSome(...); HTTP server, Kafka returnNone. - B. Producer
file:...?mode=readbridge — REJECTED: violates ADR-0014 (fake URI reuse) and inverts the producer semantic. - C. New
ReadEndpointtrait — REJECTED: component-specific, doesn't reuse the existing consumer logic (filters, idempotency, path traversal). - D.
resource:standalone component — REJECTED: same flaws as B plus duplicates filesystem logic. - E. Consumer downcast — REJECTED: ugly, doesn't generalize, requires
every pollable component to share a concrete
Consumershape.
Consequences
- Adding
timeout: DurationtoPollingConsumer::receiveis a breaking change for any external implementor of the trait. Acceptable while the trait has zero implementors in-tree (all currentEndpoint::polling_consumeroverrides returnNone). Bumpcamel-component-apiminor version. FileEndpoint::polling_consumer()is the first non-Noneimplementation in the workspace; it must establish the eager-finalization lifecycle (delete/move/idempotency-mark happen insidereceive, before the Exchange is returned) that future implementors will follow.- WASM gains a sibling host function
camel_poll(uri, timeout_ms). Plugins remain backward compatible (additive WIT imports). No versioned worlds for v1 — carto-kit is the only consumer and is pre-production. - The DSL strategy trait is named
EnrichmentStrategy, notAggregationStrategy, to avoid collision with the existing EIP-22AggregateStrategyDeffamily.