Skip to content

JDBC dead-letter claimable sequence paging appears inconsistent with JPA implementation #4544

@doubleflygofight

Description

@doubleflygofight

Summary

The JDBC dead-letter queue implementation appears to page claimable sequence heads differently from the JPA implementation, in a way that may skip or distort candidate coverage beyond the first page.

JDBC behavior observed

JdbcSequencedDeadLetterQueue.process(predicate, processingTask) calls findClaimableSequences(10).

PagingJdbcIterable advances pages using page * pageSize, and DefaultDeadLetterStatementFactory.claimableSequencesStatement(...) uses that value as:

sequenceIndex >= ?

while also ordering by:

ORDER BY lastTouched ASC

The resulting SQL shape is effectively:

SELECT *
FROM DeadLetterEntry dl
WHERE dl.processingGroup = ?
  AND dl.sequenceIndex >= ?
  AND dl.sequenceIndex = (
      SELECT MIN(dl2.sequenceIndex)
      FROM DeadLetterEntry dl2
      WHERE dl2.processingGroup = dl.processingGroup
        AND dl2.sequenceIdentifier = dl.sequenceIdentifier
  )
  AND (
      dl.processingStarted IS NULL
      OR dl.processingStarted < ?
  )
ORDER BY dl.lastTouched ASC
LIMIT ?

Why this looks problematic

sequenceIndex is sequence-local, not globally monotonic across a processing group.

That means paging with sequenceIndex >= offset does not appear consistent with a result set ordered by lastTouched ASC.

For example:

  • page 1 uses sequenceIndex >= 0
  • page 2 uses sequenceIndex >= 10

But page 2 is then not "the next 10 oldest sequence heads by lastTouched".
Instead, it filters out any sequence head whose minimum sequenceIndex is below 10, even if that head was never part of page 1.

Comparison with JPA

The JPA implementation appears to page the ordered result set directly:

select dl
from DeadLetterEntry dl
where dl.processingGroup = :processingGroup
  and dl.sequenceIndex = (
      select min(dl2.sequenceIndex)
      from DeadLetterEntry dl2
      where dl2.processingGroup = dl.processingGroup
        and dl2.sequenceIdentifier = dl.sequenceIdentifier
  )
  and (dl.processingStarted is null or dl.processingStarted < :processingStartedLimit)
order by dl.lastTouched asc

This matches the expected semantics much more closely.

Potential risk

This may:

  • distort coverage beyond the first page,
  • skip valid sequence heads in later pages,
  • or make predicate-based processing fairness/throughput worse than expected.

This becomes especially visible when a custom predicate is used and the first page contains many non-processable sequence heads.

Question

Is this intentional in the JDBC implementation, or should JDBC paging be aligned with the JPA behavior for claimable sequence selection?

Metadata

Metadata

Labels

Priority 3: CouldLow priority. Issues that are nice to have but have a straightforward workaround.

Type

No fields configured for Bug.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions