|
22 | 22 | import io.awspring.cloud.sqs.listener.QueueAttributes;
|
23 | 23 | import io.awspring.cloud.sqs.listener.QueueNotFoundStrategy;
|
24 | 24 | import io.awspring.cloud.sqs.listener.SqsHeaders;
|
| 25 | +import io.awspring.cloud.sqs.listener.SqsHeaders.MessageSystemAttributes; |
25 | 26 | import io.awspring.cloud.sqs.listener.acknowledgement.AcknowledgementCallback;
|
26 | 27 | import io.awspring.cloud.sqs.support.converter.MessageAttributeDataTypes;
|
27 | 28 | import io.awspring.cloud.sqs.support.converter.MessageConversionContext;
|
|
32 | 33 | import java.util.Collection;
|
33 | 34 | import java.util.Collections;
|
34 | 35 | import java.util.HashMap;
|
| 36 | +import java.util.HashSet; |
35 | 37 | import java.util.Map;
|
36 | 38 | import java.util.Optional;
|
| 39 | +import java.util.Set; |
37 | 40 | import java.util.UUID;
|
38 | 41 | import java.util.concurrent.CompletableFuture;
|
39 | 42 | import java.util.concurrent.ConcurrentHashMap;
|
@@ -244,23 +247,35 @@ private Map<String, Object> addAdditionalReceiveHeaders(SqsReceiveOptionsImpl op
|
244 | 247 | @Override
|
245 | 248 | protected <T> org.springframework.messaging.Message<T> preProcessMessageForSend(String endpointToUse,
|
246 | 249 | org.springframework.messaging.Message<T> message) {
|
247 |
| - return FifoUtils.isFifo(endpointToUse) ? addMissingFifoSendHeaders(message) : message; |
| 250 | + return FifoUtils.isFifo(endpointToUse) ? addMissingFifoSendHeaders(endpointToUse, message) : message; |
248 | 251 | }
|
249 | 252 |
|
250 | 253 | @Override
|
251 | 254 | protected <T> Collection<org.springframework.messaging.Message<T>> preProcessMessagesForSend(String endpointToUse,
|
252 | 255 | Collection<org.springframework.messaging.Message<T>> messages) {
|
253 | 256 | return FifoUtils.isFifo(endpointToUse)
|
254 |
| - ? messages.stream().map(this::addMissingFifoSendHeaders).collect(Collectors.toList()) |
| 257 | + ? messages.stream().map(message -> addMissingFifoSendHeaders(endpointToUse, message)).toList() |
255 | 258 | : messages;
|
256 | 259 | }
|
257 | 260 |
|
258 |
| - private <T> org.springframework.messaging.Message<T> addMissingFifoSendHeaders( |
| 261 | + private <T> org.springframework.messaging.Message<T> addMissingFifoSendHeaders(String endpointName, |
259 | 262 | org.springframework.messaging.Message<T> message) {
|
260 |
| - return MessageHeaderUtils.addHeadersIfAbsent(message, |
261 |
| - Map.of(SqsHeaders.MessageSystemAttributes.SQS_MESSAGE_GROUP_ID_HEADER, UUID.randomUUID().toString(), |
262 |
| - SqsHeaders.MessageSystemAttributes.SQS_MESSAGE_DEDUPLICATION_ID_HEADER, |
263 |
| - UUID.randomUUID().toString())); |
| 263 | + |
| 264 | + Set<QueueAttributeName> additionalAttributes = Set.of(QueueAttributeName.CONTENT_BASED_DEDUPLICATION); |
| 265 | + String contentBasedDedupQueueAttribute = getQueueAttributes(endpointName, additionalAttributes).join() |
| 266 | + .getQueueAttribute(QueueAttributeName.CONTENT_BASED_DEDUPLICATION); |
| 267 | + |
| 268 | + boolean isContentBasedDedup = Boolean.parseBoolean(contentBasedDedupQueueAttribute); |
| 269 | + Map<String, Object> defaultHeaders; |
| 270 | + if (isContentBasedDedup) { |
| 271 | + defaultHeaders = Map.of(MessageSystemAttributes.SQS_MESSAGE_GROUP_ID_HEADER, UUID.randomUUID().toString()); |
| 272 | + } |
| 273 | + else { |
| 274 | + defaultHeaders = Map.of(MessageSystemAttributes.SQS_MESSAGE_GROUP_ID_HEADER, UUID.randomUUID().toString(), |
| 275 | + MessageSystemAttributes.SQS_MESSAGE_DEDUPLICATION_ID_HEADER, UUID.randomUUID().toString()); |
| 276 | + } |
| 277 | + |
| 278 | + return MessageHeaderUtils.addHeadersIfAbsent(message, defaultHeaders); |
264 | 279 | }
|
265 | 280 |
|
266 | 281 | @Override
|
@@ -408,10 +423,21 @@ private boolean isSkipAttribute(MessageSystemAttributeName name) {
|
408 | 423 | }
|
409 | 424 |
|
410 | 425 | private CompletableFuture<QueueAttributes> getQueueAttributes(String endpointName) {
|
411 |
| - return this.queueAttributesCache.computeIfAbsent(endpointName, |
412 |
| - newName -> QueueAttributesResolver.builder().sqsAsyncClient(this.sqsAsyncClient).queueName(newName) |
413 |
| - .queueNotFoundStrategy(this.queueNotFoundStrategy).queueAttributeNames(this.queueAttributeNames) |
414 |
| - .build().resolveQueueAttributes()); |
| 426 | + return getQueueAttributes(endpointName, Collections.emptySet()); |
| 427 | + } |
| 428 | + |
| 429 | + private CompletableFuture<QueueAttributes> getQueueAttributes(String endpointName, |
| 430 | + Set<QueueAttributeName> additionalAttributes) { |
| 431 | + return this.queueAttributesCache.computeIfAbsent(endpointName, newName -> { |
| 432 | + // ensure we have the content based dedupe config to determine default fifo send headers |
| 433 | + Set<QueueAttributeName> namesToRequest = new HashSet<>(queueAttributeNames); |
| 434 | + if (additionalAttributes != null && !additionalAttributes.isEmpty()) { |
| 435 | + namesToRequest.addAll(additionalAttributes); |
| 436 | + } |
| 437 | + return QueueAttributesResolver.builder().sqsAsyncClient(this.sqsAsyncClient).queueName(newName) |
| 438 | + .queueNotFoundStrategy(this.queueNotFoundStrategy).queueAttributeNames(namesToRequest).build() |
| 439 | + .resolveQueueAttributes(); |
| 440 | + }); |
415 | 441 | }
|
416 | 442 |
|
417 | 443 | @Override
|
|
0 commit comments