Interface SequencedDeadLetterQueue<M extends Message<?>>

Type Parameters:
M - An implementation of Message contained in the dead letters within this queue.
All Known Implementing Classes:
InMemorySequencedDeadLetterQueue, JdbcSequencedDeadLetterQueue, JpaSequencedDeadLetterQueue, JpaSequencedDeadLetterQueue

public interface SequencedDeadLetterQueue<M extends Message<?>>
Interface describing the required functionality for a dead letter queue. Contains several FIFO-ordered sequences of dead letters.

The contained sequences are uniquely identifiable through the "sequence identifier." Dead-letters are kept in the form of a DeadLetter. It is highly recommended to use the process operation (or any of its variants) to consume letters from the queue for retrying. This method ensure sequences cannot be concurrently accessed, thus protecting the user against handling messages out of order.

Since:
4.6.0
Author:
Steven van Beelen, Allard Buijze, Milan Savic, Mitchell Herrijgers
See Also:
  • Method Details

    • enqueue

      void enqueue(@Nonnull Object sequenceIdentifier, @Nonnull DeadLetter<? extends M> letter) throws DeadLetterQueueOverflowException
      Enqueues a dead letter containing an implementation of M to this queue.

      The dead letter will be appended to a sequence depending on the sequenceIdentifier. If there is no sequence yet, it will construct one.

      Parameters:
      sequenceIdentifier - The identifier of the sequence the letter belongs to.
      letter - The DeadLetter to enqueue.
      Throws:
      DeadLetterQueueOverflowException - Thrown when this queue is full.
    • enqueueIfPresent

      default boolean enqueueIfPresent(@Nonnull Object sequenceIdentifier, @Nonnull Supplier<DeadLetter<? extends M>> letterBuilder) throws DeadLetterQueueOverflowException
      Enqueue the result of the given letterBuilder only if there already are other dead letters with the same sequenceIdentifier present in this queue.
      Parameters:
      sequenceIdentifier - The identifier of the sequence to store the result of the letterBuilder in.
      letterBuilder - The DeadLetter builder constructing the letter to enqueue. Only invoked if the given sequenceIdentifier is contained.
      Returns:
      A true if there are dead letters for the given sequenceIdentifier and thus the letterBuilder's outcome is inserted. Otherwise false is returned.
      Throws:
      DeadLetterQueueOverflowException - Thrown when this queue is isFull(Object) for the given sequenceIdentifier.
    • evict

      void evict(DeadLetter<? extends M> letter)
      Evict the given letter from this queue. Nothing happens if the dead letter does not exist in this queue.
      Parameters:
      letter - The dead letter to evict from this queue.
    • requeue

      void requeue(@Nonnull DeadLetter<? extends M> letter, @Nonnull UnaryOperator<DeadLetter<? extends M>> letterUpdater) throws NoSuchDeadLetterException
      Reenters the given letter, updating the contents with the letterUpdater. This method should be invoked if processing decided to keep the letter in the queue.

      This operation adjusts the DeadLetter.lastTouched(). It may adjust the DeadLetter.cause() and DeadLetter.diagnostics(), depending on the given letterUpdater.

      Parameters:
      letter - The dead letter to reenter in this queue.
      letterUpdater - A lambda taking in the given letter and updating the entry for requeueing. This may adjust the DeadLetter.cause() and DeadLetter.diagnostics(), for example.
      Throws:
      NoSuchDeadLetterException - Thrown if the given letter does not exist in the queue.
    • contains

      boolean contains(@Nonnull Object sequenceIdentifier)
      Check whether there's a sequence of dead letters for the given sequenceIdentifier.
      Parameters:
      sequenceIdentifier - The identifier used to validate for contained dead letters instances.
      Returns:
      true if there are dead letters present for the given sequenceIdentifier, false otherwise.
    • deadLetterSequence

      Iterable<DeadLetter<? extends M>> deadLetterSequence(@Nonnull Object sequenceIdentifier)
      Return all the dead letters for the given sequenceIdentifier in insert order.
      Parameters:
      sequenceIdentifier - The identifier of the sequence of dead lettersto return.
      Returns:
      All the dead letters for the given sequenceIdentifier in insert order.
    • deadLetters

      Iterable<Iterable<DeadLetter<? extends M>>> deadLetters()
      Return all dead letter sequences held by this queue. The sequences are not necessarily returned in insert order.
      Returns:
      All dead letter sequences held by this queue.
    • isFull

      boolean isFull(@Nonnull Object sequenceIdentifier)
      Validates whether this queue is full for the given sequenceIdentifier.

      This method returns true either when the maximum amount of sequences or the maximum sequence size is reached.

      Parameters:
      sequenceIdentifier - The identifier of the sequence to validate for.
      Returns:
      true either when the limit of this queue is reached. Returns false otherwise.
    • size

      long size()
      Returns the number of dead letters contained in this queue.
      Returns:
      The number of dead letters contained in this queue.
    • sequenceSize

      long sequenceSize(@Nonnull Object sequenceIdentifier)
      Returns the number of dead letters for the sequence matching the given sequenceIdentifier contained in this queue.

      Note that there's a window of opportunity where the size might exceed the maximum sequence size to accompany concurrent usage.

      Parameters:
      sequenceIdentifier - The identifier of the sequence to retrieve the size from.
      Returns:
      The number of dead letters for the sequence matching the given sequenceIdentifier.
    • amountOfSequences

      long amountOfSequences()
      Returns the number of unique sequences contained in this queue.

      Note that there's a window of opportunity where the size might exceed the maximum amount of sequences to accompany concurrent usage of this dead letter queue.

      Returns:
      The number of unique sequences contained in this queue.
    • process

      boolean process(@Nonnull Predicate<DeadLetter<? extends M>> sequenceFilter, @Nonnull Function<DeadLetter<? extends M>,EnqueueDecision<M>> processingTask)
      Process a sequence of enqueued dead letters through the given processingTask matching the sequenceFilter. Will pick the oldest available sequence based on the DeadLetter.lastTouched() field from every sequence's first entry.

      Note that only a single matching sequence is processed! Furthermore, only the first dead letter is validated, because it is the blocker for the processing of the rest of the sequence.

      Uses the EnqueueDecision returned by the processingTask to decide whether to evict(DeadLetter) or requeue(DeadLetter, UnaryOperator) a dead letter from the selected sequence. The processingTask is invoked as long as letters are present in the selected sequence and the result of processing returns false for EnqueueDecision.shouldEnqueue() decision. The latter means the dead letter should be evicted.

      This operation protects against concurrent invocations of the processingTask on the filtered sequence. Doing so ensure enqueued messages are handled in order.

      Parameters:
      sequenceFilter - A lambda selecting the sequences within this queue to process with the processingTask.
      processingTask - A function processing a dead letter. Returns a EnqueueDecision used to deduce whether to evict(DeadLetter) or requeue(DeadLetter, UnaryOperator) the dead letter.
      Returns:
      true if an entire sequence of dead letters was processed successfully, false otherwise. This means the processingTask processed all dead letters of a sequence and the outcome was to evict each instance.
    • process

      default boolean process(@Nonnull Function<DeadLetter<? extends M>,EnqueueDecision<M>> processingTask)
      Process a sequence of enqueued dead letters with the given processingTask. Will pick the oldest available sequence based on the DeadLetter.lastTouched() field from every sequence's first entry.

      Note that only a single matching sequence is processed!

      Uses the EnqueueDecision returned by the processingTask to decide whether to evict(DeadLetter) or requeue(DeadLetter, UnaryOperator) the dead letter. The processingTask is invoked as long as letters are present in the selected sequence and the result of processing returns false for EnqueueDecision.shouldEnqueue() decision. The latter means the dead letter should be evicted.

      This operation protects against concurrent invocations of the processingTask on the filtered sequence. * Doing so ensure enqueued messages are handled in order.

      Parameters:
      processingTask - A function processing a dead letter. Returns a EnqueueDecision used to deduce whether to evict(DeadLetter) or requeue(DeadLetter, UnaryOperator) the dead letter.
      Returns:
      true if an entire sequence of dead letters was processed successfully, false otherwise. This means the processingTask processed all dead letters of a sequence and the outcome was to evict each instance.
    • clear

      void clear()
      Clears out all dead letters present in this queue.