Pause spring SqsListener to pull messages from queue

2k views Asked by At

Currently I have a SQS queue that move the messages to a DLQ after 5 retries, I'm using spring SqsListener to read the queue:

@SqsListener(
    value = ["\${messaging.queue.orders}"],
    deletionPolicy = SqsMessageDeletionPolicy.ON_SUCCESS
)
fun handleOrders(message: String) {
    // process order
}

Now I'm trying to use a feature toggle to pause the listener, but I could not find a way to do that, I tried to use the Acknowledgment manually, but the message is move to the DLQ if I don't send the success ack event:

@SqsListener(
    value = ["\${messaging.queue.orders}"],
    deletionPolicy = SqsMessageDeletionPolicy.NEVER
)
fun handleOrders(message: String, ack: Acknowledgment) {
    if(toggle.orders.enabled) {
        // process order
        ack.acknowledge()
    }
    // else don not process or ack the message
}

As I said, the problem with the solution above is that if I don't execute the ack.acknowledge() the message is moved to the DLQ after the fifth time, so I would need to pause/stop the SqsListener to pull messages from the Queue if the toggle is disabled, and start/resume if it's enabled again.

2

There are 2 answers

0
RobertG On

I'm having a similar issue.

Googling it, I found this issue on the archived predecessor of spring-cloud-aws-sqs.

It describes this workaround:

  1. Get the beans of the listener container that wraps the SQS listener (from the SpringBoot application context)
  2. Call the stop() method on them

Nowadays in spring-cloud-aws, @SqsListener is still there.

The listener container class you may want to autowire is io.awspring.cloud.sqs.listener.SqsMessageListenerContainer (to call its inherited io.awspring.cloud.sqs.listener.AbstractMessageListenerContainer#stop).

2
DragneelFPS On

You can toggle creation of SqsListener using @ConditionalOnExpression

Like:

@SqsListener(
    value = ["\${messaging.queue.orders}"],
    deletionPolicy = SqsMessageDeletionPolicy.NEVER
)
@ConditionalOnExpression("\${toggle.orders.enabled:false}")
fun handleOrders(message: String) {
    // process order
}

And adding following to application.yaml

toggle:
  orders:
    enabled: true

if you change the property, you will have to restart the server unless you are using spring cloud for configuration

You can also use @ConditionalOnProperty(prefix = "toggle", name = "orders.enabled")