Class OutboxPollerWorker
PENDING → SENT transition for
outbox rows the hot AFTER_COMMIT relay did not finish (broker outage,
process crash, circuit-breaker OPEN window, etc.).
Per ADR-0014 D-7, the poller is the source of truth for the SENT transition. Each tick:
- Acquires the
outbox-pollerShedLock — only one replica processes a tick at a time. - Fetches up to
im2be.outbox.poller.batch-sizePENDING rows increatedAt ASCorder. - For each row, performs a synchronous Kafka send. The cold path does NOT wrap the send in a circuit-breaker — the breaker exists to protect the hot path's commit-time critical section; the cold path is already off-cycle, so trying every row each tick is the correct semantic.
- Success →
markSent(clearslastError); failure →markFailureAttempt(bumpsretries+ persists truncated error message). Row stays PENDING on failure for the next tick.
OTel span im2be.outbox.poller.tick per invocation with
attributes batch.size, success.count, failure.count.
The worker is gated behind im2be.outbox.poller.enabled=true
(default) — disabling it is useful in dev-only contexts where the operator
inspects PENDING rows manually.
-
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionOutboxPollerWorker(OutboxBackend backend, org.springframework.kafka.core.KafkaTemplate<byte[], byte[]> kafkaTemplate, OutboxProperties properties, io.opentelemetry.api.OpenTelemetry openTelemetry, OutboxMetricsBinder metrics) Constructs the worker with all collaborators autowired byOutboxAutoConfiguration. -
Method Summary
-
Field Details
-
LOCK_NAME
ShedLock name; matches the value scoped inSchedulerLock.- See Also:
-
-
Constructor Details
-
OutboxPollerWorker
public OutboxPollerWorker(OutboxBackend backend, org.springframework.kafka.core.KafkaTemplate<byte[], byte[]> kafkaTemplate, OutboxProperties properties, io.opentelemetry.api.OpenTelemetry openTelemetry, OutboxMetricsBinder metrics) Constructs the worker with all collaborators autowired byOutboxAutoConfiguration.Wave A.2 Phase 0a — the former
repository+completioncollaborators are now collapsed behind theOutboxBackendstorage SPI (design doc refinement #11). For the defaultPgOutboxBackendthe FIFO batch fetch + transition semantics are identical to the pre-extraction code (zero behaviour change).- Parameters:
backend- storage SPI — supplies the FIFO PENDING-row batch and drives themarkSent/markFailureAttempttransitions (the default PG impl wraps the JPA repository + theREQUIRES_NEWcompletion helper)kafkaTemplate- Spring Kafka template (byte-key, byte-value)properties- type-safe configuration (poller batch size etc.)openTelemetry- OpenTelemetry instance for the span tracermetrics- metrics binder for latency/failure counters
-
-
Method Details
-
pollAndPublishPending
@Scheduled(fixedDelayString="${im2be.outbox.poller.interval-ms:5000}") public void pollAndPublishPending()Scheduled tick. Distributed-locked via ShedLock so only one replica sweeps PENDING rows at a time.Cadence governed by
im2be.outbox.poller.interval-ms(default 5000ms). Batch size byim2be.outbox.poller.batch-size(default 500).NOT wrapped in
@Transactional— each row's send is independent, and the status-transition writes occur in their own REQUIRES_NEW transactions insideOutboxPublishCompletion.
-