lock Batch For Dispatch
Atomically selects up to batchSize messages eligible for dispatch and locks them with a write lock so that concurrent poller instances skip them (SELECT … FOR UPDATE SKIP LOCKED on PostgreSQL).
A message is eligible when:
it is OutboxStatus.PENDING (initial state or rescheduled retry) whose cooldown has elapsed (
lastRetryAtisnullor earlier than retriableBefore), ANDit has been attempted fewer than maxRetries times, OR
it is OutboxStatus.PROCESSING whose OutboxMessage.processedAt is older than stuckBefore (crash-recovery for messages whose publisher died after the row was marked PROCESSING but before the publishing completed).
Implementations MUST be called within an active transaction so the pessimistic lock survives until the caller updates each row.