3

The behavior of negative acknowledgment is to change the visibility timeout of a received message to 0. Where the value of NACK_TIMEOUT is not configurable while creating the SQS Factory for JMS.

https://github.com/awslabs/amazon-sqs-java-messaging-lib/blob/master/src/main/java/com/amazon/sqs/javamessaging/acknowledge/NegativeAcknowledger.java#L99

When a message is received, and the processing fails (Listener method throws an error), the message is immediately received again. In most of the cases, the message can be processed with a certain delay.

Is it possible to configure it to not change the visibility timeout, so it respects the Queue's default Receive Timeout configuration?

Justin Bertram
  • 29,372
  • 4
  • 21
  • 43
Ashwani Agarwal
  • 1,279
  • 9
  • 30

2 Answers2

4

Apparently there is a way, somewhat clunky, but I didn't find any better workaround, the idea is that when you create client you can attach your own request handler:

    return AmazonSQSAsyncClientBuilder.standard()
        .withRequestHandlers(new RequestHandler2() {
            @Override
            public AmazonWebServiceRequest beforeExecution(AmazonWebServiceRequest request) {
                if (request instanceof ChangeMessageVisibilityBatchRequest) {
                    ((ChangeMessageVisibilityBatchRequest) request).getEntries().forEach(changeMessageVisibilityBatchRequestEntry -> {
                        changeMessageVisibilityBatchRequestEntry.setVisibilityTimeout(15);
                    });
                    log.debug("Changed visibility timeout for request {}", request);
                }
                return request;
            }
        })
    ;
Cmyker
  • 2,318
  • 1
  • 26
  • 29
0

People who don't want to send ChangeMessageVisibility request at all (which reset current visibility timer) and want to rely only on the default queue visibility timeout may use following AmazonSQS wrapper written with the help of lombok:

public AmazonSQS amazonSqs(AWSCredentialsProvider credentialsProvider) {
    AmazonSQS amazonSQS = AmazonSQSClientBuilder.standard()
            .withRegion(region)
            (...)
            .build();

    return new IgnoringChangeVisibilityAmazonSqs(amazonSQS);
}

@Slf4j
@RequiredArgsConstructor
public class IgnoringChangeVisibilityAmazonSqs implements AmazonSQS {

    private interface ChangeVisibilityOperations {
        ChangeMessageVisibilityResult changeMessageVisibility(ChangeMessageVisibilityRequest changeMessageVisibilityRequest);
        ChangeMessageVisibilityResult changeMessageVisibility(String queueUrl, String receiptHandle, Integer visibilityTimeout);
        ChangeMessageVisibilityBatchResult changeMessageVisibilityBatch(ChangeMessageVisibilityBatchRequest request);
        ChangeMessageVisibilityBatchResult changeMessageVisibilityBatch(String queueUrl, List<ChangeMessageVisibilityBatchRequestEntry> entries);
    }

    @Delegate(excludes = ChangeVisibilityOperations.class)
    private final AmazonSQS amazonSqs;

    @Override
    public ChangeMessageVisibilityResult changeMessageVisibility(ChangeMessageVisibilityRequest changeMessageVisibilityRequest) {
        log.info("Ignoring ChangeMessageVisibilityRequest");
        return new ChangeMessageVisibilityResult();
    }

    @Override
    public ChangeMessageVisibilityResult changeMessageVisibility(String queueUrl, String receiptHandle, Integer visibilityTimeout) {
        log.info("Ignoring ChangeMessageVisibilityRequest");
        return new ChangeMessageVisibilityResult();
    }

    @Override
    public ChangeMessageVisibilityBatchResult changeMessageVisibilityBatch(ChangeMessageVisibilityBatchRequest request) {
        log.info("Ignoring ChangeMessageVisibilityBatchRequest");
        return changeMessageVisibilityBatch(request.getQueueUrl(), request.getEntries());
    }

    @Override
    public ChangeMessageVisibilityBatchResult changeMessageVisibilityBatch(String queueUrl, List<ChangeMessageVisibilityBatchRequestEntry> entries) {
        log.info("Ignoring ChangeMessageVisibilityBatchRequest");
        List<ChangeMessageVisibilityBatchResultEntry> results = entries.stream().map(request ->
                new ChangeMessageVisibilityBatchResultEntry().withId(request.getId()))
                .collect(Collectors.toList());
        return new ChangeMessageVisibilityBatchResult().withSuccessful(results);
    }
}

Michał Mielec
  • 1,582
  • 1
  • 14
  • 38