From bf414dd0f9cc4231018b9c508e0669788492ddd5 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Fri, 17 Mar 2023 04:27:05 -0300 Subject: [PATCH 01/20] feat: comunication interprocess using semaphore Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsConsumer.java | 165 ++++++++++++++++++ .../lib/core/AbstractAmazonSnsProducer.java | 157 ++--------------- .../lib/core/AbstractAmazonSnsTemplate.java | 34 ++-- .../messaging/lib/core/AmazonSnsConsumer.java | 140 +++++++++++++++ .../messaging/lib/core/AmazonSnsProducer.java | 113 +----------- .../messaging/lib/core/AmazonSnsTemplate.java | 16 +- .../core/core/AmazonSnsProducerAsyncTest.java | 16 +- .../core/core/AmazonSnsProducerSyncTest.java | 16 +- .../messaging/lib/core/AmazonSnsConsumer.java | 139 +++++++++++++++ .../messaging/lib/core/AmazonSnsProducer.java | 112 +----------- .../messaging/lib/core/AmazonSnsTemplate.java | 16 +- .../core/core/AmazonSnsProducerAsyncTest.java | 16 +- .../core/core/AmazonSnsProducerSyncTest.java | 8 +- 13 files changed, 546 insertions(+), 402 deletions(-) create mode 100644 amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java create mode 100644 amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java create mode 100644 amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java new file mode 100644 index 0000000..6813c09 --- /dev/null +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -0,0 +1,165 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.PublishRequestBuilder; +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.SneakyThrows; + +// @formatter:off +@RequiredArgsConstructor +abstract class AbstractAmazonSnsConsumer extends Thread implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsConsumer.class); + + protected final TopicProperty topicProperty; + + private final ObjectMapper objectMapper; + + protected final ConcurrentMap pendingRequests; + + private final BlockingQueue> topicRequests; + + protected final AmazonSnsThreadPoolExecutor executorService; + + private final Semaphore semaphoreProducer; + + private final Semaphore semaphoreConsumer; + + @Getter + @Setter(value = AccessLevel.PRIVATE) + private boolean running = true; + + protected abstract void publishBatch(final R publishBatchRequest); + + protected abstract void handleError(final R publishBatchRequest, final Exception ex); + + protected abstract void handleResponse(final O publishBatchResult); + + protected abstract BiFunction>, R> supplierPublishRequest(); + + @Override + @SneakyThrows + public void run() { + while (isRunning()) { + try { + semaphoreConsumer.acquire(); + + while (CollectionUtils.isNotEmpty(topicRequests)) { + final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); + final boolean maxBatchSizeReached = maxBatchSizeReached(topicRequests); + + if (maxWaitTimeElapsed || maxBatchSizeReached) { + createBatch(topicRequests).ifPresent(this::publishBatch); + } + } + } catch (final Exception ex) { + LOGGER.error(ex.getMessage(), ex); + } finally { + semaphoreProducer.release(); + } + } + } + + @SneakyThrows + public void shutdown() { + LOGGER.warn("Shutdown producer {}", getClass().getSimpleName()); + setRunning(false); + executorService.shutdown(); + if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { + LOGGER.warn("Executor did not terminate in the specified time."); + final List droppedTasks = executorService.shutdownNow(); + LOGGER.warn("Executor was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); + } + } + + private boolean requestsWaitedFor(final BlockingQueue> requests, final long batchingWindowInMs) { + return Optional.ofNullable(requests.peek()).map(oldestPendingRequest -> { + final long oldestEntryWaitTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - oldestPendingRequest.getCreateTime()); + return oldestEntryWaitTime > batchingWindowInMs; + }).orElse(false); + } + + private boolean maxBatchSizeReached(final BlockingQueue> requests) { + return requests.size() > topicProperty.getMaxBatchSize(); + } + + @SneakyThrows + private Optional createBatch(final BlockingQueue> requests) { + final List> requestEntries = new LinkedList<>(); + + while (requestEntries.size() < topicProperty.getMaxBatchSize() && Objects.nonNull(requests.peek())) { + final RequestEntry requestEntry = requests.take(); + requestEntries.add(requestEntry); + } + + if (requestEntries.isEmpty()) { + return Optional.empty(); + } + + return Optional.of(PublishRequestBuilder.>builder() + .supplier(supplierPublishRequest()) + .entries(requestEntries) + .topicArn(topicProperty.getTopicArn()) + .build()); + } + + public CompletableFuture await() { + while (MapUtils.isNotEmpty(pendingRequests) || CollectionUtils.isNotEmpty(topicRequests) || executorService.getActiveTaskCount() > 0) { + final List futures = pendingRequests.entrySet().stream() + .map(Entry::getValue) + .map(ListenableFutureRegistry::completable) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(futures)) { + CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); + } + } + return CompletableFuture.completedFuture(null); + } + + @SneakyThrows + protected String convertPayload(final E payload) { + return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index cdd38bc..52e5ce9 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -16,168 +16,49 @@ package com.amazon.sns.messaging.lib.core; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.BiFunction; -import java.util.stream.Collectors; +import java.util.concurrent.Semaphore; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.amazon.sns.messaging.lib.model.PublishRequestBuilder; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import lombok.AccessLevel; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.SneakyThrows; // @formatter:off @RequiredArgsConstructor -abstract class AbstractAmazonSnsProducer extends Thread implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsProducer.class); - - protected final TopicProperty topicProperty; +abstract class AbstractAmazonSnsProducer { - private final ObjectMapper objectMapper; - - protected final ConcurrentMap pendingRequests; + private final ConcurrentMap pendingRequests; private final BlockingQueue> topicRequests; - protected final AmazonSnsThreadPoolExecutor executorService; - - private final ReentrantLock reentrantLock = new ReentrantLock(); - - private final Condition empty = reentrantLock.newCondition(); - - @Getter - @Setter(value = AccessLevel.PRIVATE) - private boolean running = true; - - protected abstract void publishBatch(final R publishBatchRequest); - - protected abstract void handleError(final R publishBatchRequest, final Exception ex); - - protected abstract void handleResponse(final O publishBatchResult); + private final Semaphore semaphoreProducer; - protected abstract BiFunction>, R> supplierPublishRequest(); + private final Semaphore semaphoreConsumer; - @Override @SneakyThrows - public void run() { - while (isRunning()) { - try { - reentrantLock.lock(); - - while (CollectionUtils.isEmpty(topicRequests)) { - empty.await(); - } - - while (CollectionUtils.isNotEmpty(topicRequests)) { - final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); - final boolean maxBatchSizeReached = maxBatchSizeReached(topicRequests); - - if (maxWaitTimeElapsed || maxBatchSizeReached) { - createBatch(topicRequests).ifPresent(this::publishBatch); - } - } - } catch (final Exception ex) { - LOGGER.error(ex.getMessage(), ex); - Thread.currentThread().interrupt(); - } finally { - reentrantLock.unlock(); - } - } - } - - @SneakyThrows - public void shutdown() { - LOGGER.warn("Shutdown producer {}", getClass().getSimpleName()); - setRunning(false); - executorService.shutdown(); - if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { - LOGGER.warn("Executor did not terminate in the specified time."); - final List droppedTasks = executorService.shutdownNow(); - LOGGER.warn("Executor was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); - } - } - - private boolean requestsWaitedFor(final BlockingQueue> requests, final long batchingWindowInMs) { - return Optional.ofNullable(requests.peek()).map(oldestPendingRequest -> { - final long oldestEntryWaitTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - oldestPendingRequest.getCreateTime()); - return oldestEntryWaitTime > batchingWindowInMs; - }).orElse(false); - } - - private boolean maxBatchSizeReached(final BlockingQueue> requests) { - return requests.size() > topicProperty.getMaxBatchSize(); - } - - @SneakyThrows - private Optional createBatch(final BlockingQueue> requests) { - final List> requestEntries = new LinkedList<>(); - - while (requestEntries.size() < topicProperty.getMaxBatchSize() && Objects.nonNull(requests.peek())) { - final RequestEntry requestEntry = requests.take(); - requestEntries.add(requestEntry); - } - - if (requestEntries.isEmpty()) { - return Optional.empty(); - } - - return Optional.of(PublishRequestBuilder.>builder() - .supplier(supplierPublishRequest()) - .entries(requestEntries) - .topicArn(topicProperty.getTopicArn()) - .build()); - } - - public void wakeup() { + public ListenableFuture send(final RequestEntry requestEntry) { try { - reentrantLock.lock(); - - if (CollectionUtils.isNotEmpty(topicRequests)) { - empty.signal(); - } - + semaphoreProducer.acquire(); + return trackPendingRequest(enqueueRequest(requestEntry)); } finally { - reentrantLock.unlock(); + semaphoreConsumer.release(); } } - public CompletableFuture await() { - while (MapUtils.isNotEmpty(pendingRequests) || CollectionUtils.isNotEmpty(topicRequests) || executorService.getActiveTaskCount() > 0) { - final List futures = pendingRequests.entrySet().stream() - .map(Entry::getValue) - .map(ListenableFutureRegistry::completable) - .collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(futures)) { - CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); - } - } - return CompletableFuture.completedFuture(null); + @SneakyThrows + private String enqueueRequest(final RequestEntry requestEntry) { + topicRequests.put(requestEntry); + return requestEntry.getId(); } - @SneakyThrows - protected String convertPayload(final E payload) { - return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); + private ListenableFuture trackPendingRequest(final String correlationId) { + final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); + pendingRequests.put(correlationId, listenableFuture); + return listenableFuture; } } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 1ef30a8..17a26fe 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -20,13 +20,12 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.ResponseFailEntry; import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import lombok.SneakyThrows; - // @formatter:off abstract class AbstractAmazonSnsTemplate { @@ -34,35 +33,24 @@ abstract class AbstractAmazonSnsTemplate { protected BlockingQueue> topicRequests; - protected AbstractAmazonSnsProducer amazonSnsProducer; + protected Semaphore semaphoreProducer; + + protected Semaphore semaphoreConsumer; + + protected AbstractAmazonSnsProducer amazonSnsProducer; + + protected AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { - try { - final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); - enqueueRequest(requestEntry); - return trackPendingRequest; - } finally { - amazonSnsProducer.wakeup(); - } + return amazonSnsProducer.send(requestEntry); } public void shutdown() { - amazonSnsProducer.shutdown(); + amazonSnsConsumer.shutdown(); } public CompletableFuture await() { - return amazonSnsProducer.await(); - } - - @SneakyThrows - private void enqueueRequest(final RequestEntry requestEntry) { - topicRequests.put(requestEntry); - } - - private ListenableFuture trackPendingRequest(final String correlationId) { - final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); - pendingRequests.put(correlationId, listenableFuture); - return listenableFuture; + return amazonSnsConsumer.await(); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java new file mode 100644 index 0000000..022cbdd --- /dev/null +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -0,0 +1,140 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.services.sns.AmazonSNS; +import com.amazonaws.services.sns.model.PublishBatchRequest; +import com.amazonaws.services.sns.model.PublishBatchRequestEntry; +import com.amazonaws.services.sns.model.PublishBatchResult; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.SneakyThrows; + +// @formatter:off +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); + + private static final MessageAttributes messageAttributes = new MessageAttributes(); + + private final AmazonSNS amazonSNS; + + public AmazonSnsConsumer( + final AmazonSNS amazonSNS, + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final Semaphore semaphoreProducer, + final Semaphore semaphoreConsumer) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize()), semaphoreProducer, semaphoreConsumer); + this.amazonSNS = amazonSNS; + } + + private void publish(final PublishBatchRequest publishBatchRequest) { + try { + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + + @Override + protected void publishBatch(final PublishBatchRequest publishBatchRequest) { + if (topicProperty.isFifo()) { + publish(publishBatchRequest); + } else { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } + } + + @Override + protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { + return (topicArn, requestEntries) -> { + final List entries = requestEntries.stream() + .map(entry -> new PublishBatchRequestEntry() + .withId(entry.getId()) + .withSubject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) + .withMessageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) + .withMessageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) + .withMessageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) + .withMessage(convertPayload(entry.getValue()))) + .collect(Collectors.toList()); + return new PublishBatchRequest().withPublishBatchRequestEntries(entries).withTopicArn(topicArn); + }; + } + + @Override + protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { + final String code = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorCode() : "000"; + final String message = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorMessage() : ex.getMessage(); + + LOGGER.error(ex.getMessage(), ex); + + publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.getId()) + .withCode(code) + .withMessage(message) + .withSenderFault(true) + .build()); + }); + } + + @Override + @SneakyThrows + protected void handleResponse(final PublishBatchResult publishBatchResult) { + publishBatchResult.getSuccessful().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.success(ResponseSuccessEntry.builder() + .withId(entry.getId()) + .withMessageId(entry.getMessageId()) + .withSequenceNumber(entry.getSequenceNumber()) + .build()); + }); + + publishBatchResult.getFailed().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.getId()) + .withCode(entry.getCode()) + .withMessage(entry.getMessage()) + .withSenderFault(entry.getSenderFault()) + .build()); + }); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index 3cad178..ac757fd 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -16,116 +16,21 @@ package com.amazon.sns.messaging.lib.core; -import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.ResponseFailEntry; -import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.sns.AmazonSNS; -import com.amazonaws.services.sns.model.PublishBatchRequest; -import com.amazonaws.services.sns.model.PublishBatchRequestEntry; -import com.amazonaws.services.sns.model.PublishBatchResult; -import com.fasterxml.jackson.databind.ObjectMapper; - -import lombok.SneakyThrows; // @formatter:off -class AmazonSnsProducer extends AbstractAmazonSnsProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsProducer.class); - - private static final MessageAttributes messageAttributes = new MessageAttributes(); - - private final AmazonSNS amazonSNS; - - public AmazonSnsProducer(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } - - @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } - } - - @Override - protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { - return (topicArn, requestEntries) -> { - final List entries = requestEntries.stream() - .map(entry -> new PublishBatchRequestEntry() - .withId(entry.getId()) - .withSubject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) - .withMessageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) - .withMessageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) - .withMessageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) - .withMessage(convertPayload(entry.getValue()))) - .collect(Collectors.toList()); - return new PublishBatchRequest().withPublishBatchRequestEntries(entries).withTopicArn(topicArn); - }; - } - - @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorCode() : "000"; - final String message = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorMessage() : ex.getMessage(); - - LOGGER.error(ex.getMessage(), ex); - - publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.getId()) - .withCode(code) - .withMessage(message) - .withSenderFault(true) - .build()); - }); - } - - @Override - @SneakyThrows - protected void handleResponse(final PublishBatchResult publishBatchResult) { - publishBatchResult.getSuccessful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.success(ResponseSuccessEntry.builder() - .withId(entry.getId()) - .withMessageId(entry.getMessageId()) - .withSequenceNumber(entry.getSequenceNumber()) - .build()); - }); - - publishBatchResult.getFailed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.getId()) - .withCode(entry.getCode()) - .withMessage(entry.getMessage()) - .withSenderFault(entry.getSenderFault()) - .build()); - }); +class AmazonSnsProducer extends AbstractAmazonSnsProducer { + + public AmazonSnsProducer( + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final Semaphore semaphoreProducer, + final Semaphore semaphoreConsumer) { + super(pendingRequests, topicRequests, semaphoreProducer, semaphoreConsumer); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index eefc79d..d2b09d8 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.TopicProperty; @@ -26,12 +27,20 @@ import com.amazonaws.services.sns.model.PublishBatchResult; import com.fasterxml.jackson.databind.ObjectMapper; +// @formatter:off public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { - public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { + public AmazonSnsTemplate( + final AmazonSNS amazonSNS, + final TopicProperty topicProperty, + final BlockingQueue> topicRequests, + final ObjectMapper objectMapper) { + super.semaphoreProducer = new Semaphore(1); + super.semaphoreConsumer = new Semaphore(0); super.topicRequests = topicRequests; - super.amazonSnsProducer = new AmazonSnsProducer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer.start(); + super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests, super.semaphoreProducer, super.semaphoreConsumer); + super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests, super.semaphoreProducer, super.semaphoreConsumer); + super.amazonSnsConsumer.start(); } public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { @@ -47,3 +56,4 @@ public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicPro } } +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 501461a..910cd02 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -141,24 +141,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } @@ -181,24 +181,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 8b74acb..8ee4d65 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -140,24 +140,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } @@ -180,24 +180,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java new file mode 100644 index 0000000..22d92da --- /dev/null +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -0,0 +1,139 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.services.sns.SnsClient; +import software.amazon.awssdk.services.sns.model.PublishBatchRequest; +import software.amazon.awssdk.services.sns.model.PublishBatchRequestEntry; +import software.amazon.awssdk.services.sns.model.PublishBatchResponse; + +// @formatter:off +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); + + private static final MessageAttributes messageAttributes = new MessageAttributes(); + + private final SnsClient amazonSNS; + + public AmazonSnsConsumer( + final SnsClient amazonSNS, + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final Semaphore semaphoreProducer, + final Semaphore semaphoreConsumer) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize()), semaphoreProducer, semaphoreConsumer); + this.amazonSNS = amazonSNS; + } + + private void publish(final PublishBatchRequest publishBatchRequest) { + try { + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + + @Override + protected void publishBatch(final PublishBatchRequest publishBatchRequest) { + if (topicProperty.isFifo()) { + publish(publishBatchRequest); + } else { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } + } + + @Override + protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { + return (topicArn, requestEntries) -> { + final List entries = requestEntries.stream() + .map(entry -> PublishBatchRequestEntry.builder() + .id(entry.getId()) + .subject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) + .messageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) + .messageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) + .messageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) + .message(convertPayload(entry.getValue())) + .build()) + .collect(Collectors.toList()); + return PublishBatchRequest.builder().publishBatchRequestEntries(entries).topicArn(topicArn).build(); + }; + } + + @Override + protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { + final String code = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorCode() : "000"; + final String message = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorMessage() : ex.getMessage(); + + LOGGER.error(ex.getMessage(), ex); + + publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.id()) + .withCode(code) + .withMessage(message) + .withSenderFault(true) + .build()); + }); + } + + @Override + protected void handleResponse(final PublishBatchResponse publishBatchResult) { + publishBatchResult.successful().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.success(ResponseSuccessEntry.builder() + .withId(entry.id()) + .withMessageId(entry.messageId()) + .withSequenceNumber(entry.sequenceNumber()) + .build()); + }); + + publishBatchResult.failed().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.id()) + .withCode(entry.code()) + .withMessage(entry.message()) + .withSenderFault(entry.senderFault()) + .build()); + }); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index cd8d6f6..ac757fd 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -16,115 +16,21 @@ package com.amazon.sns.messaging.lib.core; -import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.ResponseFailEntry; -import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.fasterxml.jackson.databind.ObjectMapper; - -import software.amazon.awssdk.awscore.exception.AwsServiceException; -import software.amazon.awssdk.services.sns.SnsClient; -import software.amazon.awssdk.services.sns.model.PublishBatchRequest; -import software.amazon.awssdk.services.sns.model.PublishBatchRequestEntry; -import software.amazon.awssdk.services.sns.model.PublishBatchResponse; // @formatter:off -class AmazonSnsProducer extends AbstractAmazonSnsProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsProducer.class); - - private static final MessageAttributes messageAttributes = new MessageAttributes(); - - private final SnsClient amazonSNS; - - public AmazonSnsProducer(final SnsClient amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } - - @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } - } - - @Override - protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { - return (topicArn, requestEntries) -> { - final List entries = requestEntries.stream() - .map(entry -> PublishBatchRequestEntry.builder() - .id(entry.getId()) - .subject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) - .messageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) - .messageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) - .messageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) - .message(convertPayload(entry.getValue())) - .build()) - .collect(Collectors.toList()); - return PublishBatchRequest.builder().publishBatchRequestEntries(entries).topicArn(topicArn).build(); - }; - } - - @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorCode() : "000"; - final String message = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorMessage() : ex.getMessage(); - - LOGGER.error(ex.getMessage(), ex); - - publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.id()) - .withCode(code) - .withMessage(message) - .withSenderFault(true) - .build()); - }); - } - - @Override - protected void handleResponse(final PublishBatchResponse publishBatchResult) { - publishBatchResult.successful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.success(ResponseSuccessEntry.builder() - .withId(entry.id()) - .withMessageId(entry.messageId()) - .withSequenceNumber(entry.sequenceNumber()) - .build()); - }); - - publishBatchResult.failed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.id()) - .withCode(entry.code()) - .withMessage(entry.message()) - .withSenderFault(entry.senderFault()) - .build()); - }); +class AmazonSnsProducer extends AbstractAmazonSnsProducer { + + public AmazonSnsProducer( + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final Semaphore semaphoreProducer, + final Semaphore semaphoreConsumer) { + super(pendingRequests, topicRequests, semaphoreProducer, semaphoreConsumer); } } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index a6f0976..a368e99 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.TopicProperty; @@ -27,12 +28,20 @@ import software.amazon.awssdk.services.sns.model.PublishBatchRequest; import software.amazon.awssdk.services.sns.model.PublishBatchResponse; +// @formatter:off public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { - public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { + public AmazonSnsTemplate( + final SnsClient amazonSNS, + final TopicProperty topicProperty, + final BlockingQueue> topicRequests, + final ObjectMapper objectMapper) { + super.semaphoreProducer = new Semaphore(1); + super.semaphoreConsumer = new Semaphore(0); super.topicRequests = topicRequests; - super.amazonSnsProducer = new AmazonSnsProducer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer.start(); + super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests, super.semaphoreProducer, super.semaphoreConsumer); + super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests, super.semaphoreProducer, super.semaphoreConsumer); + super.amazonSnsConsumer.start(); } public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { @@ -48,3 +57,4 @@ public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicPro } } +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 8c99331..2651812 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -143,24 +143,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } @@ -183,24 +183,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index c29d934..fe51ccf 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -142,24 +142,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } From 43758e64ace27d903bbc3770951201e45b2a040c Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Fri, 17 Mar 2023 04:27:05 -0300 Subject: [PATCH 02/20] feat: improvement CPU usage Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsConsumer.java | 174 ++++++++++++++++++ .../lib/core/AbstractAmazonSnsProducer.java | 157 ++-------------- .../lib/core/AbstractAmazonSnsTemplate.java | 34 ++-- .../messaging/lib/core/AmazonSnsConsumer.java | 137 ++++++++++++++ .../messaging/lib/core/AmazonSnsProducer.java | 108 +---------- .../messaging/lib/core/AmazonSnsTemplate.java | 13 +- .../core/core/AmazonSnsProducerAsyncTest.java | 20 +- .../core/core/AmazonSnsProducerSyncTest.java | 18 +- .../src/test/resources/logback.xml | 2 +- .../messaging/lib/core/AmazonSnsConsumer.java | 136 ++++++++++++++ .../messaging/lib/core/AmazonSnsProducer.java | 107 +---------- .../messaging/lib/core/AmazonSnsTemplate.java | 16 +- .../core/core/AmazonSnsProducerAsyncTest.java | 16 +- .../core/core/AmazonSnsProducerSyncTest.java | 8 +- .../src/test/resources/logback.xml | 2 +- 15 files changed, 539 insertions(+), 409 deletions(-) create mode 100644 amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java create mode 100644 amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java create mode 100644 amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java new file mode 100644 index 0000000..92af5d2 --- /dev/null +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -0,0 +1,174 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.PublishRequestBuilder; +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; + +// @formatter:off +abstract class AbstractAmazonSnsConsumer extends Thread implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsConsumer.class); + + protected final TopicProperty topicProperty; + + private final ObjectMapper objectMapper; + + protected final ConcurrentMap pendingRequests; + + private final BlockingQueue> topicRequests; + + protected final AmazonSnsThreadPoolExecutor executorService; + + protected AbstractAmazonSnsConsumer( + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final AmazonSnsThreadPoolExecutor executorService) { + super(String.format("amazon-sns-consumer-%s", topicProperty.getTopicArn())); + this.topicProperty = topicProperty; + this.objectMapper = objectMapper; + this.pendingRequests = pendingRequests; + this.topicRequests = topicRequests; + this.executorService = executorService; + } + + @Getter + @Setter(value = AccessLevel.PRIVATE) + private boolean running = true; + + protected abstract void publishBatch(final R publishBatchRequest); + + protected abstract void handleError(final R publishBatchRequest, final Exception ex); + + protected abstract void handleResponse(final O publishBatchResult); + + protected abstract BiFunction>, R> supplierPublishRequest(); + + @Override + @SneakyThrows + public void run() { + while (isRunning()) { + try { + + if (topicRequests.isEmpty()) { + Thread.sleep(10); + } + + final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); + final boolean maxBatchSizeReached = maxBatchSizeReached(topicRequests); + + if (maxWaitTimeElapsed || maxBatchSizeReached) { + createBatch(topicRequests).ifPresent(this::publishBatch); + } + + } catch (final Exception ex) { + LOGGER.error(ex.getMessage(), ex); + } + } + } + + @SneakyThrows + public void shutdown() { + LOGGER.warn("Shutdown producer {}", getClass().getSimpleName()); + setRunning(false); + executorService.shutdown(); + if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { + LOGGER.warn("Executor did not terminate in the specified time."); + final List droppedTasks = executorService.shutdownNow(); + LOGGER.warn("Executor was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); + } + } + + private boolean requestsWaitedFor(final BlockingQueue> requests, final long batchingWindowInMs) { + return Optional.ofNullable(requests.peek()).map(oldestPendingRequest -> { + final long oldestEntryWaitTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - oldestPendingRequest.getCreateTime()); + return oldestEntryWaitTime > batchingWindowInMs; + }).orElse(false); + } + + private boolean maxBatchSizeReached(final BlockingQueue> requests) { + return requests.size() > topicProperty.getMaxBatchSize(); + } + + @SneakyThrows + private Optional createBatch(final BlockingQueue> requests) { + final List> requestEntries = new LinkedList<>(); + + while (requestEntries.size() < topicProperty.getMaxBatchSize() && Objects.nonNull(requests.peek())) { + final RequestEntry requestEntry = requests.take(); + requestEntries.add(requestEntry); + } + + if (requestEntries.isEmpty()) { + return Optional.empty(); + } + + LOGGER.debug("{}", requestEntries); + + return Optional.of(PublishRequestBuilder.>builder() + .supplier(supplierPublishRequest()) + .entries(requestEntries) + .topicArn(topicProperty.getTopicArn()) + .build()); + } + + public CompletableFuture await() { + while (MapUtils.isNotEmpty(pendingRequests) || CollectionUtils.isNotEmpty(topicRequests) || executorService.getActiveTaskCount() > 0) { + final List futures = pendingRequests.entrySet().stream() + .map(Entry::getValue) + .map(ListenableFutureRegistry::completable) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(futures)) { + CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); + } + } + return CompletableFuture.completedFuture(null); + } + + @SneakyThrows + protected String convertPayload(final E payload) { + return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index cdd38bc..4dae800 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -16,168 +16,41 @@ package com.amazon.sns.messaging.lib.core; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Optional; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.BiFunction; -import java.util.stream.Collectors; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.amazon.sns.messaging.lib.model.PublishRequestBuilder; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import lombok.AccessLevel; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.SneakyThrows; // @formatter:off @RequiredArgsConstructor -abstract class AbstractAmazonSnsProducer extends Thread implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsProducer.class); - - protected final TopicProperty topicProperty; - - private final ObjectMapper objectMapper; +abstract class AbstractAmazonSnsProducer { - protected final ConcurrentMap pendingRequests; + private final ConcurrentMap pendingRequests; private final BlockingQueue> topicRequests; - protected final AmazonSnsThreadPoolExecutor executorService; - - private final ReentrantLock reentrantLock = new ReentrantLock(); - - private final Condition empty = reentrantLock.newCondition(); - - @Getter - @Setter(value = AccessLevel.PRIVATE) - private boolean running = true; - - protected abstract void publishBatch(final R publishBatchRequest); - - protected abstract void handleError(final R publishBatchRequest, final Exception ex); - - protected abstract void handleResponse(final O publishBatchResult); - - protected abstract BiFunction>, R> supplierPublishRequest(); - - @Override - @SneakyThrows - public void run() { - while (isRunning()) { - try { - reentrantLock.lock(); - - while (CollectionUtils.isEmpty(topicRequests)) { - empty.await(); - } - - while (CollectionUtils.isNotEmpty(topicRequests)) { - final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); - final boolean maxBatchSizeReached = maxBatchSizeReached(topicRequests); - - if (maxWaitTimeElapsed || maxBatchSizeReached) { - createBatch(topicRequests).ifPresent(this::publishBatch); - } - } - } catch (final Exception ex) { - LOGGER.error(ex.getMessage(), ex); - Thread.currentThread().interrupt(); - } finally { - reentrantLock.unlock(); - } - } - } - @SneakyThrows - public void shutdown() { - LOGGER.warn("Shutdown producer {}", getClass().getSimpleName()); - setRunning(false); - executorService.shutdown(); - if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { - LOGGER.warn("Executor did not terminate in the specified time."); - final List droppedTasks = executorService.shutdownNow(); - LOGGER.warn("Executor was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); - } - } - - private boolean requestsWaitedFor(final BlockingQueue> requests, final long batchingWindowInMs) { - return Optional.ofNullable(requests.peek()).map(oldestPendingRequest -> { - final long oldestEntryWaitTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - oldestPendingRequest.getCreateTime()); - return oldestEntryWaitTime > batchingWindowInMs; - }).orElse(false); - } - - private boolean maxBatchSizeReached(final BlockingQueue> requests) { - return requests.size() > topicProperty.getMaxBatchSize(); + public ListenableFuture send(final RequestEntry requestEntry) { + final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); + enqueueRequest(requestEntry); + return trackPendingRequest; } @SneakyThrows - private Optional createBatch(final BlockingQueue> requests) { - final List> requestEntries = new LinkedList<>(); - - while (requestEntries.size() < topicProperty.getMaxBatchSize() && Objects.nonNull(requests.peek())) { - final RequestEntry requestEntry = requests.take(); - requestEntries.add(requestEntry); - } - - if (requestEntries.isEmpty()) { - return Optional.empty(); - } - - return Optional.of(PublishRequestBuilder.>builder() - .supplier(supplierPublishRequest()) - .entries(requestEntries) - .topicArn(topicProperty.getTopicArn()) - .build()); - } - - public void wakeup() { - try { - reentrantLock.lock(); - - if (CollectionUtils.isNotEmpty(topicRequests)) { - empty.signal(); - } - - } finally { - reentrantLock.unlock(); - } - } - - public CompletableFuture await() { - while (MapUtils.isNotEmpty(pendingRequests) || CollectionUtils.isNotEmpty(topicRequests) || executorService.getActiveTaskCount() > 0) { - final List futures = pendingRequests.entrySet().stream() - .map(Entry::getValue) - .map(ListenableFutureRegistry::completable) - .collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(futures)) { - CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); - } - } - return CompletableFuture.completedFuture(null); + private String enqueueRequest(final RequestEntry requestEntry) { + topicRequests.put(requestEntry); + return requestEntry.getId(); } - @SneakyThrows - protected String convertPayload(final E payload) { - return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); + private ListenableFuture trackPendingRequest(final String correlationId) { + final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); + pendingRequests.put(correlationId, listenableFuture); + return listenableFuture; } } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 1ef30a8..17a26fe 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -20,13 +20,12 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.ResponseFailEntry; import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import lombok.SneakyThrows; - // @formatter:off abstract class AbstractAmazonSnsTemplate { @@ -34,35 +33,24 @@ abstract class AbstractAmazonSnsTemplate { protected BlockingQueue> topicRequests; - protected AbstractAmazonSnsProducer amazonSnsProducer; + protected Semaphore semaphoreProducer; + + protected Semaphore semaphoreConsumer; + + protected AbstractAmazonSnsProducer amazonSnsProducer; + + protected AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { - try { - final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); - enqueueRequest(requestEntry); - return trackPendingRequest; - } finally { - amazonSnsProducer.wakeup(); - } + return amazonSnsProducer.send(requestEntry); } public void shutdown() { - amazonSnsProducer.shutdown(); + amazonSnsConsumer.shutdown(); } public CompletableFuture await() { - return amazonSnsProducer.await(); - } - - @SneakyThrows - private void enqueueRequest(final RequestEntry requestEntry) { - topicRequests.put(requestEntry); - } - - private ListenableFuture trackPendingRequest(final String correlationId) { - final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); - pendingRequests.put(correlationId, listenableFuture); - return listenableFuture; + return amazonSnsConsumer.await(); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java new file mode 100644 index 0000000..28b90fd --- /dev/null +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -0,0 +1,137 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.services.sns.AmazonSNS; +import com.amazonaws.services.sns.model.PublishBatchRequest; +import com.amazonaws.services.sns.model.PublishBatchRequestEntry; +import com.amazonaws.services.sns.model.PublishBatchResult; +import com.fasterxml.jackson.databind.ObjectMapper; + +import lombok.SneakyThrows; + +// @formatter:off +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); + + private static final MessageAttributes messageAttributes = new MessageAttributes(); + + private final AmazonSNS amazonSNS; + + public AmazonSnsConsumer( + final AmazonSNS amazonSNS, + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); + this.amazonSNS = amazonSNS; + } + + private void publish(final PublishBatchRequest publishBatchRequest) { + try { + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + + @Override + protected void publishBatch(final PublishBatchRequest publishBatchRequest) { + if (topicProperty.isFifo()) { + publish(publishBatchRequest); + } else { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } + } + + @Override + protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { + return (topicArn, requestEntries) -> { + final List entries = requestEntries.stream() + .map(entry -> new PublishBatchRequestEntry() + .withId(entry.getId()) + .withSubject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) + .withMessageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) + .withMessageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) + .withMessageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) + .withMessage(convertPayload(entry.getValue()))) + .collect(Collectors.toList()); + return new PublishBatchRequest().withPublishBatchRequestEntries(entries).withTopicArn(topicArn); + }; + } + + @Override + protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { + final String code = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorCode() : "000"; + final String message = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorMessage() : ex.getMessage(); + + LOGGER.error(ex.getMessage(), ex); + + publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.getId()) + .withCode(code) + .withMessage(message) + .withSenderFault(true) + .build()); + }); + } + + @Override + @SneakyThrows + protected void handleResponse(final PublishBatchResult publishBatchResult) { + publishBatchResult.getSuccessful().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.success(ResponseSuccessEntry.builder() + .withId(entry.getId()) + .withMessageId(entry.getMessageId()) + .withSequenceNumber(entry.getSequenceNumber()) + .build()); + }); + + publishBatchResult.getFailed().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.getId()) + .withCode(entry.getCode()) + .withMessage(entry.getMessage()) + .withSenderFault(entry.getSenderFault()) + .build()); + }); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index 3cad178..ccd9fb2 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -16,116 +16,18 @@ package com.amazon.sns.messaging.lib.core; -import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.ResponseFailEntry; -import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.sns.AmazonSNS; -import com.amazonaws.services.sns.model.PublishBatchRequest; -import com.amazonaws.services.sns.model.PublishBatchRequestEntry; -import com.amazonaws.services.sns.model.PublishBatchResult; -import com.fasterxml.jackson.databind.ObjectMapper; - -import lombok.SneakyThrows; // @formatter:off -class AmazonSnsProducer extends AbstractAmazonSnsProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsProducer.class); - - private static final MessageAttributes messageAttributes = new MessageAttributes(); - - private final AmazonSNS amazonSNS; - - public AmazonSnsProducer(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } - - @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } - } - - @Override - protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { - return (topicArn, requestEntries) -> { - final List entries = requestEntries.stream() - .map(entry -> new PublishBatchRequestEntry() - .withId(entry.getId()) - .withSubject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) - .withMessageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) - .withMessageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) - .withMessageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) - .withMessage(convertPayload(entry.getValue()))) - .collect(Collectors.toList()); - return new PublishBatchRequest().withPublishBatchRequestEntries(entries).withTopicArn(topicArn); - }; - } - - @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorCode() : "000"; - final String message = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorMessage() : ex.getMessage(); - - LOGGER.error(ex.getMessage(), ex); - - publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.getId()) - .withCode(code) - .withMessage(message) - .withSenderFault(true) - .build()); - }); - } - - @Override - @SneakyThrows - protected void handleResponse(final PublishBatchResult publishBatchResult) { - publishBatchResult.getSuccessful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.success(ResponseSuccessEntry.builder() - .withId(entry.getId()) - .withMessageId(entry.getMessageId()) - .withSequenceNumber(entry.getSequenceNumber()) - .build()); - }); +class AmazonSnsProducer extends AbstractAmazonSnsProducer { - publishBatchResult.getFailed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.getId()) - .withCode(entry.getCode()) - .withMessage(entry.getMessage()) - .withSenderFault(entry.getSenderFault()) - .build()); - }); + public AmazonSnsProducer( + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests) { + super(pendingRequests, topicRequests); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index eefc79d..bc7eb8e 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -26,12 +26,18 @@ import com.amazonaws.services.sns.model.PublishBatchResult; import com.fasterxml.jackson.databind.ObjectMapper; +// @formatter:off public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { - public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { + public AmazonSnsTemplate( + final AmazonSNS amazonSNS, + final TopicProperty topicProperty, + final BlockingQueue> topicRequests, + final ObjectMapper objectMapper) { super.topicRequests = topicRequests; - super.amazonSnsProducer = new AmazonSnsProducer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer.start(); + super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); + super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests); + super.amazonSnsConsumer.start(); } public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { @@ -47,3 +53,4 @@ public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicPro } } +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 501461a..7f7eefb 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -71,8 +71,8 @@ public class AmazonSnsProducerAsyncTest { public void before() throws Exception { when(topicProperty.isFifo()).thenReturn(false); when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(100); - when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaximumPoolSize()).thenReturn(10); + when(topicProperty.getLinger()).thenReturn(1000L); when(topicProperty.getMaxBatchSize()).thenReturn(10); snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); } @@ -141,24 +141,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } @@ -181,24 +181,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 8b74acb..4e8d53e 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -70,7 +70,7 @@ public void before() throws Exception { when(topicProperty.isFifo()).thenReturn(true); when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getLinger()).thenReturn(1000L); when(topicProperty.getMaxBatchSize()).thenReturn(10); snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); } @@ -140,24 +140,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } @@ -180,24 +180,24 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any()); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml b/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml index bf06d81..b35b3bc 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml +++ b/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml @@ -6,7 +6,7 @@ - + diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java new file mode 100644 index 0000000..c622582 --- /dev/null +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -0,0 +1,136 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.amazon.sns.messaging.lib.core; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentMap; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazon.sns.messaging.lib.model.RequestEntry; +import com.amazon.sns.messaging.lib.model.ResponseFailEntry; +import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.services.sns.SnsClient; +import software.amazon.awssdk.services.sns.model.PublishBatchRequest; +import software.amazon.awssdk.services.sns.model.PublishBatchRequestEntry; +import software.amazon.awssdk.services.sns.model.PublishBatchResponse; + +// @formatter:off +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); + + private static final MessageAttributes messageAttributes = new MessageAttributes(); + + private final SnsClient amazonSNS; + + public AmazonSnsConsumer( + final SnsClient amazonSNS, + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); + this.amazonSNS = amazonSNS; + } + + private void publish(final PublishBatchRequest publishBatchRequest) { + try { + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + + @Override + protected void publishBatch(final PublishBatchRequest publishBatchRequest) { + if (topicProperty.isFifo()) { + publish(publishBatchRequest); + } else { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } + } + + @Override + protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { + return (topicArn, requestEntries) -> { + final List entries = requestEntries.stream() + .map(entry -> PublishBatchRequestEntry.builder() + .id(entry.getId()) + .subject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) + .messageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) + .messageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) + .messageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) + .message(convertPayload(entry.getValue())) + .build()) + .collect(Collectors.toList()); + return PublishBatchRequest.builder().publishBatchRequestEntries(entries).topicArn(topicArn).build(); + }; + } + + @Override + protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { + final String code = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorCode() : "000"; + final String message = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorMessage() : ex.getMessage(); + + LOGGER.error(ex.getMessage(), ex); + + publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.id()) + .withCode(code) + .withMessage(message) + .withSenderFault(true) + .build()); + }); + } + + @Override + protected void handleResponse(final PublishBatchResponse publishBatchResult) { + publishBatchResult.successful().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.success(ResponseSuccessEntry.builder() + .withId(entry.id()) + .withMessageId(entry.messageId()) + .withSequenceNumber(entry.sequenceNumber()) + .build()); + }); + + publishBatchResult.failed().forEach(entry -> { + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + listenableFuture.fail(ResponseFailEntry.builder() + .withId(entry.id()) + .withCode(entry.code()) + .withMessage(entry.message()) + .withSenderFault(entry.senderFault()) + .build()); + }); + } + +} +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index cd8d6f6..ccd9fb2 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -16,115 +16,18 @@ package com.amazon.sns.messaging.lib.core; -import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.amazon.sns.messaging.lib.model.RequestEntry; -import com.amazon.sns.messaging.lib.model.ResponseFailEntry; -import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; -import com.amazon.sns.messaging.lib.model.TopicProperty; -import com.fasterxml.jackson.databind.ObjectMapper; - -import software.amazon.awssdk.awscore.exception.AwsServiceException; -import software.amazon.awssdk.services.sns.SnsClient; -import software.amazon.awssdk.services.sns.model.PublishBatchRequest; -import software.amazon.awssdk.services.sns.model.PublishBatchRequestEntry; -import software.amazon.awssdk.services.sns.model.PublishBatchResponse; // @formatter:off -class AmazonSnsProducer extends AbstractAmazonSnsProducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsProducer.class); - - private static final MessageAttributes messageAttributes = new MessageAttributes(); - - private final SnsClient amazonSNS; - - public AmazonSnsProducer(final SnsClient amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } - - @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } - } - - @Override - protected BiFunction>, PublishBatchRequest> supplierPublishRequest() { - return (topicArn, requestEntries) -> { - final List entries = requestEntries.stream() - .map(entry -> PublishBatchRequestEntry.builder() - .id(entry.getId()) - .subject(StringUtils.isNotBlank(entry.getSubject()) ? entry.getSubject() : null) - .messageGroupId(StringUtils.isNotBlank(entry.getGroupId()) ? entry.getGroupId() : null) - .messageDeduplicationId(StringUtils.isNotBlank(entry.getDeduplicationId()) ? entry.getDeduplicationId() : null) - .messageAttributes(messageAttributes.messageAttributes(entry.getMessageHeaders())) - .message(convertPayload(entry.getValue())) - .build()) - .collect(Collectors.toList()); - return PublishBatchRequest.builder().publishBatchRequestEntries(entries).topicArn(topicArn).build(); - }; - } - - @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorCode() : "000"; - final String message = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorMessage() : ex.getMessage(); - - LOGGER.error(ex.getMessage(), ex); - - publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.id()) - .withCode(code) - .withMessage(message) - .withSenderFault(true) - .build()); - }); - } - - @Override - protected void handleResponse(final PublishBatchResponse publishBatchResult) { - publishBatchResult.successful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.success(ResponseSuccessEntry.builder() - .withId(entry.id()) - .withMessageId(entry.messageId()) - .withSequenceNumber(entry.sequenceNumber()) - .build()); - }); +class AmazonSnsProducer extends AbstractAmazonSnsProducer { - publishBatchResult.failed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); - listenableFuture.fail(ResponseFailEntry.builder() - .withId(entry.id()) - .withCode(entry.code()) - .withMessage(entry.message()) - .withSenderFault(entry.senderFault()) - .build()); - }); + public AmazonSnsProducer( + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests) { + super(pendingRequests, topicRequests); } } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index a6f0976..73ef62d 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.TopicProperty; @@ -27,12 +28,20 @@ import software.amazon.awssdk.services.sns.model.PublishBatchRequest; import software.amazon.awssdk.services.sns.model.PublishBatchResponse; +// @formatter:off public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { - public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { + public AmazonSnsTemplate( + final SnsClient amazonSNS, + final TopicProperty topicProperty, + final BlockingQueue> topicRequests, + final ObjectMapper objectMapper) { + super.semaphoreProducer = new Semaphore(1); + super.semaphoreConsumer = new Semaphore(0); super.topicRequests = topicRequests; - super.amazonSnsProducer = new AmazonSnsProducer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer.start(); + super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); + super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests); + super.amazonSnsConsumer.start(); } public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { @@ -48,3 +57,4 @@ public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicPro } } +// @formatter:on diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 8c99331..2651812 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -143,24 +143,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } @@ -183,24 +183,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index c29d934..fe51ccf 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -142,24 +142,24 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(100000).forEach(entry -> { snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(3000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml b/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml index bf06d81..b35b3bc 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml +++ b/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml @@ -6,7 +6,7 @@ - + From 39597bffa28572e82a4f0323f5ab02a24d713167 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 17:18:02 -0300 Subject: [PATCH 03/20] feat: improve await() Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsConsumer.java | 41 +++---- .../lib/core/AbstractAmazonSnsProducer.java | 3 +- .../core/core/AmazonSnsProducerAsyncTest.java | 115 ++++++++---------- .../core/core/AmazonSnsProducerSyncTest.java | 113 ++++++++--------- .../core/core/AmazonSnsProducerAsyncTest.java | 113 ++++++++--------- .../core/core/AmazonSnsProducerSyncTest.java | 113 ++++++++--------- 6 files changed, 230 insertions(+), 268 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index 62003cf..ee145e0 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -1,24 +1,18 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; import java.util.LinkedList; import java.util.List; -import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.concurrent.BlockingQueue; @@ -26,7 +20,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; -import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; @@ -91,7 +84,7 @@ public void run() { try { if (topicRequests.isEmpty()) { - Thread.sleep(topicProperty.getLinger()); + sleep(1); } final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); @@ -127,7 +120,7 @@ private boolean requestsWaitedFor(final BlockingQueue> requests, } private boolean maxBatchSizeReached(final BlockingQueue> requests) { - return requests.size() > topicProperty.getMaxBatchSize(); + return requests.size() > this.topicProperty.getMaxBatchSize(); } @SneakyThrows @@ -152,17 +145,16 @@ private Optional createBatch(final BlockingQueue> requests) { .build()); } + @SneakyThrows public CompletableFuture await() { - while (MapUtils.isNotEmpty(pendingRequests) || CollectionUtils.isNotEmpty(topicRequests) || executorService.getActiveTaskCount() > 0) { - final List futures = pendingRequests.entrySet().stream() - .map(Entry::getValue) - .map(ListenableFutureRegistry::completable) - .collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(futures)) { - CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join(); + return CompletableFuture.runAsync(() -> { + while ( + MapUtils.isNotEmpty(this.pendingRequests) || + CollectionUtils.isNotEmpty(this.topicRequests) || + this.executorService.getActiveTaskCount() > 0) { + sleep(1); } - } - return CompletableFuture.completedFuture(null); + }); } @SneakyThrows @@ -170,5 +162,10 @@ protected String convertPayload(final E payload) { return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); } + @SneakyThrows + private static void sleep(final int millis) { + Thread.sleep(millis); + } + } // @formatter:on diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 4dae800..8478dbe 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -42,9 +42,8 @@ public ListenableFuture send(final Requ } @SneakyThrows - private String enqueueRequest(final RequestEntry requestEntry) { + private void enqueueRequest(final RequestEntry requestEntry) { topicRequests.put(requestEntry); - return requestEntry.getId(); } private ListenableFuture trackPendingRequest(final String correlationId) { diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 7f7eefb..563eec1 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -38,9 +33,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -69,12 +62,12 @@ public class AmazonSnsProducerAsyncTest { @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(1000L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); - snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); + when(this.topicProperty.isFifo()).thenReturn(false); + when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); + when(this.topicProperty.getLinger()).thenReturn(1000L); + when(this.topicProperty.getMaxBatchSize()).thenReturn(10); + this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty, new LinkedBlockingQueue<>(1024)); } @Test @@ -87,16 +80,18 @@ public void testSuccess() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getSuccessful().add(publishBatchResultEntry); - when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> snsTemplate.shutdown()).join(); + this.snsTemplate.await().thenAccept(result -> { + this.snsTemplate.shutdown(); + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); + }).join(); - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); } @Test @@ -109,15 +104,15 @@ public void testFailure() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getFailed().add(batchResultErrorEntry); - when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -125,15 +120,12 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(amazonSNS.publishBatch(any())).thenAnswer(new Answer() { - @Override - public PublishBatchResult answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.getPublishBatchRequestEntries().stream() - .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) - .collect(Collectors.toList()); - return new PublishBatchResult().withSuccessful(resultEntries); - } + when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.getPublishBatchRequestEntries().stream() + .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) + .collect(Collectors.toList()); + return new PublishBatchResult().withSuccessful(resultEntries); }); final ConsumerHelper successCallback = spy(new ConsumerHelper<>(result -> { @@ -142,38 +134,37 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + }).join(); } @Test public void testFailureMultipleEntry() { - when(amazonSNS.publishBatch(any())).thenAnswer(new Answer() { - @Override - public PublishBatchResult answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.getPublishBatchRequestEntries().stream() - .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) - .collect(Collectors.toList()); - return new PublishBatchResult().withFailed(resultEntries); - } + when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.getPublishBatchRequestEntries().stream() + .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) + .collect(Collectors.toList()); + return new PublishBatchResult().withFailed(resultEntries); }); final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { @@ -182,39 +173,41 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + }).join(); } @Test public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -223,15 +216,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 4e8d53e..96b79bf 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -36,9 +31,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -67,12 +60,12 @@ public class AmazonSnsProducerSyncTest { @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(true); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(1000L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); - snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); + when(this.topicProperty.isFifo()).thenReturn(true); + when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); + when(this.topicProperty.getLinger()).thenReturn(1000L); + when(this.topicProperty.getMaxBatchSize()).thenReturn(10); + this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty); } @Test @@ -85,15 +78,15 @@ public void testSuccess() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getSuccessful().add(publishBatchResultEntry); - when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -108,15 +101,15 @@ public void testFailure() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getFailed().add(batchResultErrorEntry); - when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -124,15 +117,12 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(amazonSNS.publishBatch(any())).thenAnswer(new Answer() { - @Override - public PublishBatchResult answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.getPublishBatchRequestEntries().stream() - .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) - .collect(Collectors.toList()); - return new PublishBatchResult().withSuccessful(resultEntries); - } + when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.getPublishBatchRequestEntries().stream() + .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) + .collect(Collectors.toList()); + return new PublishBatchResult().withSuccessful(resultEntries); }); final ConsumerHelper successCallback = spy(new ConsumerHelper<>(result -> { @@ -141,38 +131,37 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + }).join(); } @Test public void testFailureMultipleEntry() { - when(amazonSNS.publishBatch(any())).thenAnswer(new Answer() { - @Override - public PublishBatchResult answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.getPublishBatchRequestEntries().stream() - .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) - .collect(Collectors.toList()); - return new PublishBatchResult().withFailed(resultEntries); - } + when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.getPublishBatchRequestEntries().stream() + .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) + .collect(Collectors.toList()); + return new PublishBatchResult().withFailed(resultEntries); }); final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { @@ -181,39 +170,41 @@ public PublishBatchResult answer(final InvocationOnMock invocation) throws Throw CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any()); + this.snsTemplate.await().thenAccept(result -> { + verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + }).join(); } @Test public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -222,15 +213,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 2651812..b66f795 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -37,9 +32,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -70,12 +63,12 @@ public class AmazonSnsProducerAsyncTest { @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(true); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); - snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); + when(this.topicProperty.isFifo()).thenReturn(true); + when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); + when(this.topicProperty.getLinger()).thenReturn(50L); + when(this.topicProperty.getMaxBatchSize()).thenReturn(10); + this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty, new LinkedBlockingQueue<>(1024)); } @Test @@ -88,15 +81,15 @@ public void testSuccess() { .successful(publishBatchResultEntry) .build(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -111,15 +104,15 @@ public void testFailure() { .failed(batchResultErrorEntry) .build(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -127,15 +120,12 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(new Answer() { - @Override - public PublishBatchResponse answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.publishBatchRequestEntries().stream() - .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) - .collect(Collectors.toList()); - return PublishBatchResponse.builder().successful(resultEntries).build(); - } + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.publishBatchRequestEntries().stream() + .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) + .collect(Collectors.toList()); + return PublishBatchResponse.builder().successful(resultEntries).build(); }); final ConsumerHelper successCallback = spy(new ConsumerHelper<>(result -> { @@ -144,38 +134,37 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + }).join(); } @Test public void testFailureMultipleEntry() { - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(new Answer() { - @Override - public PublishBatchResponse answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.publishBatchRequestEntries().stream() - .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) - .collect(Collectors.toList()); - return PublishBatchResponse.builder().failed(resultEntries).build(); - } + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.publishBatchRequestEntries().stream() + .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) + .collect(Collectors.toList()); + return PublishBatchResponse.builder().failed(resultEntries).build(); }); final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { @@ -184,39 +173,41 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + }).join(); } @Test public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -225,15 +216,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index fe51ccf..1e70aa8 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -36,9 +31,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -69,12 +62,12 @@ public class AmazonSnsProducerSyncTest { @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); - snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); + when(this.topicProperty.isFifo()).thenReturn(false); + when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); + when(this.topicProperty.getLinger()).thenReturn(50L); + when(this.topicProperty.getMaxBatchSize()).thenReturn(10); + this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty); } @Test @@ -87,15 +80,15 @@ public void testSuccess() { .successful(publishBatchResultEntry) .build(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -110,15 +103,15 @@ public void testFailure() { .failed(batchResultErrorEntry) .build(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -126,15 +119,12 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(new Answer() { - @Override - public PublishBatchResponse answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.publishBatchRequestEntries().stream() - .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) - .collect(Collectors.toList()); - return PublishBatchResponse.builder().successful(resultEntries).build(); - } + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.publishBatchRequestEntries().stream() + .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) + .collect(Collectors.toList()); + return PublishBatchResponse.builder().successful(resultEntries).build(); }); final ConsumerHelper successCallback = spy(new ConsumerHelper<>(result -> { @@ -143,38 +133,37 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(100000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); + this.snsTemplate.send(entry).addCallback(successCallback); }); }); - verify(successCallback, timeout(300000).times(300000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + }).join(); } @Test public void testFailureMultipleEntry() { - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(new Answer() { - @Override - public PublishBatchResponse answer(final InvocationOnMock invocation) throws Throwable { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); - final List resultEntries = request.publishBatchRequestEntries().stream() - .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) - .collect(Collectors.toList()); - return PublishBatchResponse.builder().failed(resultEntries).build(); - } + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final List resultEntries = request.publishBatchRequestEntries().stream() + .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) + .collect(Collectors.toList()); + return PublishBatchResponse.builder().failed(resultEntries).build(); }); final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { @@ -183,39 +172,41 @@ public PublishBatchResponse answer(final InvocationOnMock invocation) throws Thr CompletableFuture.runAsync(() -> { entries(1000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(1000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(1000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); + this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - verify(failureCallback, timeout(300000).times(3000)).accept(any()); - verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + }).join(); } @Test public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -224,15 +215,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); + when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); - snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - snsTemplate.await().thenAccept(result -> { - verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + this.snsTemplate.await().thenAccept(result -> { + verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } From 59fe0a77c7743df9646247c20cf49c95d85f43d9 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 17:39:16 -0300 Subject: [PATCH 04/20] chore: set log level in test to INFO Signed-off-by: Marcos Tischer Vallim --- amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml | 2 +- amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml b/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml index b35b3bc..bf06d81 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml +++ b/amazon-sns-java-messaging-lib-v1/src/test/resources/logback.xml @@ -6,7 +6,7 @@ - + diff --git a/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml b/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml index b35b3bc..bf06d81 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml +++ b/amazon-sns-java-messaging-lib-v2/src/test/resources/logback.xml @@ -6,7 +6,7 @@ - + From b2575397b6ee975904a2552fa282b0acaca8cfdb Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 17:54:31 -0300 Subject: [PATCH 05/20] chore: improve tests Signed-off-by: Marcos Tischer Vallim --- .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++++++++-------- .../lib/core/core/AmazonSnsProducerSyncTest.java | 16 ++++++++-------- .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++++++++-------- .../lib/core/core/AmazonSnsProducerSyncTest.java | 16 ++++++++-------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 563eec1..7379ce2 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 96b79bf..278e361 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -130,25 +130,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -169,25 +169,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index b66f795..83cbe69 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 1e70aa8..ebc9397 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -132,25 +132,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -171,25 +171,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(1000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(3000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } From 9e941394f24b8c7592895ef9631ae1cdb8d907e7 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 20:04:31 -0300 Subject: [PATCH 06/20] chore: update documentation Signed-off-by: Marcos Tischer Vallim --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a431f22..7ec07e6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ You can pull it from the central Maven repositories: com.github.mvallim amazon-sns-java-messaging-lib-v1 - 1.0.3 + 1.0.4 ``` @@ -47,7 +47,7 @@ You can pull it from the central Maven repositories: com.github.mvallim amazon-sns-java-messaging-lib-v2 - 1.0.3 + 1.0.4 ``` @@ -68,12 +68,12 @@ If you want to try a snapshot version, add the following repository: ### For AWS SDK v1 ```groovy -implementation 'com.github.mvallim:amazon-sns-java-messaging-lib-v1:1.0.3' +implementation 'com.github.mvallim:amazon-sns-java-messaging-lib-v1:1.0.4' ``` ### For AWS SDK v2 ```groovy -implementation 'com.github.mvallim:amazon-sns-java-messaging-lib-v2:1.0.3' +implementation 'com.github.mvallim:amazon-sns-java-messaging-lib-v2:1.0.4' ``` If you want to try a snapshot version, add the following repository: From e28f3c74b03c55279ff4ee6119fe41f10844e924 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 20:30:37 -0300 Subject: [PATCH 07/20] fix: OutOfMemory Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsProducer.java | 17 ++++++----------- .../lib/core/AbstractAmazonSnsTemplate.java | 19 +++++++------------ .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++++++++-------- .../core/core/AmazonSnsProducerSyncTest.java | 16 ++++++++-------- .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++++++++-------- .../core/core/AmazonSnsProducerSyncTest.java | 16 ++++++++-------- 6 files changed, 45 insertions(+), 55 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 8478dbe..20b7b75 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -35,7 +30,7 @@ abstract class AbstractAmazonSnsProducer { private final BlockingQueue> topicRequests; @SneakyThrows - public ListenableFuture send(final RequestEntry requestEntry) { + public synchronized ListenableFuture send(final RequestEntry requestEntry) { final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); enqueueRequest(requestEntry); return trackPendingRequest; @@ -48,7 +43,7 @@ private void enqueueRequest(final RequestEntry requestEntry) { private ListenableFuture trackPendingRequest(final String correlationId) { final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); - pendingRequests.put(correlationId, listenableFuture); + this.pendingRequests.put(correlationId, listenableFuture); return listenableFuture; } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 17a26fe..ea3557e 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -42,15 +37,15 @@ abstract class AbstractAmazonSnsTemplate { protected AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { - return amazonSnsProducer.send(requestEntry); + return this.amazonSnsProducer.send(requestEntry); } public void shutdown() { - amazonSnsConsumer.shutdown(); + this.amazonSnsConsumer.shutdown(); } public CompletableFuture await() { - return amazonSnsConsumer.await(); + return this.amazonSnsConsumer.await(); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 7379ce2..563eec1 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(30000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(30000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 278e361..96b79bf 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -130,25 +130,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(30000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -169,25 +169,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(30000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 83cbe69..b66f795 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(30000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(30000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index ebc9397..c45b395 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -132,25 +132,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(30000)).accept(any()); + verify(successCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -171,25 +171,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { + entries(100000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(30000)).accept(any()); + verify(failureCallback, timeout(300000).times(300000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } From 5b9c3347e99d1a20f1f7661b973431bcd5733eef Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 21:41:24 -0300 Subject: [PATCH 08/20] chore: set java heap memory for junit in maven-surefire-plugin Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsProducer.java | 10 +++++++- .../lib/core/AbstractAmazonSnsTemplate.java | 5 ---- .../messaging/lib/core/AmazonSnsConsumer.java | 21 ++++++---------- .../messaging/lib/core/AmazonSnsProducer.java | 13 +++------- .../messaging/lib/core/AmazonSnsTemplate.java | 15 ++++------- .../core/core/AmazonSnsProducerAsyncTest.java | 2 +- .../core/core/AmazonSnsProducerSyncTest.java | 2 +- .../messaging/lib/core/AmazonSnsConsumer.java | 25 ++++++++----------- .../messaging/lib/core/AmazonSnsProducer.java | 13 +++------- .../messaging/lib/core/AmazonSnsTemplate.java | 18 ++++--------- pom.xml | 2 +- 11 files changed, 48 insertions(+), 78 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 20b7b75..6fbe70e 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -29,10 +29,18 @@ abstract class AbstractAmazonSnsProducer { private final BlockingQueue> topicRequests; + private Integer maxTopicRequests = 0; + + private Integer maxPendingRequests = 0; + @SneakyThrows - public synchronized ListenableFuture send(final RequestEntry requestEntry) { + public ListenableFuture send(final RequestEntry requestEntry) { final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); enqueueRequest(requestEntry); + maxTopicRequests = Math.max(maxTopicRequests, topicRequests.size()); + maxPendingRequests = Math.max(maxPendingRequests, pendingRequests.size()); + System.out.println("topicRequests : " + maxTopicRequests); + System.out.println("pendingRequests : " + maxPendingRequests); return trackPendingRequest; } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index ea3557e..3c26c54 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -15,7 +15,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.ResponseFailEntry; @@ -28,10 +27,6 @@ abstract class AbstractAmazonSnsTemplate { protected BlockingQueue> topicRequests; - protected Semaphore semaphoreProducer; - - protected Semaphore semaphoreConsumer; - protected AbstractAmazonSnsProducer amazonSnsProducer; protected AbstractAmazonSnsConsumer amazonSnsConsumer; diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 230195c..e1aa595 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -61,7 +56,7 @@ public AmazonSnsConsumer( private void publish(final PublishBatchRequest publishBatchRequest) { try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + handleResponse(this.amazonSNS.publishBatch(publishBatchRequest)); } catch (final Exception ex) { handleError(publishBatchRequest, ex); } @@ -69,10 +64,10 @@ private void publish(final PublishBatchRequest publishBatchRequest) { @Override protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { + if (this.topicProperty.isFifo()) { publish(publishBatchRequest); } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + CompletableFuture.runAsync(() -> publish(publishBatchRequest), this.executorService); } } @@ -100,7 +95,7 @@ protected void handleError(final PublishBatchRequest publishBatchRequest, final LOGGER.error(ex.getMessage(), ex); publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); + final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.getId()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.getId()) .withCode(code) diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index ccd9fb2..df97eae 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index bc7eb8e..697245f 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -36,7 +31,7 @@ public AmazonSnsTemplate( final ObjectMapper objectMapper) { super.topicRequests = topicRequests; super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests); + super.amazonSnsProducer = new AmazonSnsProducer<>(super.pendingRequests, super.topicRequests); super.amazonSnsConsumer.start(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 563eec1..7ee211b 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -65,7 +65,7 @@ public void before() throws Exception { when(this.topicProperty.isFifo()).thenReturn(false); when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(1000L); + when(this.topicProperty.getLinger()).thenReturn(50L); when(this.topicProperty.getMaxBatchSize()).thenReturn(10); this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty, new LinkedBlockingQueue<>(1024)); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 96b79bf..c86b27e 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -63,7 +63,7 @@ public void before() throws Exception { when(this.topicProperty.isFifo()).thenReturn(true); when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(1000L); + when(this.topicProperty.getLinger()).thenReturn(50L); when(this.topicProperty.getMaxBatchSize()).thenReturn(10); this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty); } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index de8af56..636d3d6 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -60,7 +55,7 @@ public AmazonSnsConsumer( private void publish(final PublishBatchRequest publishBatchRequest) { try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); + handleResponse(this.amazonSNS.publishBatch(publishBatchRequest)); } catch (final Exception ex) { handleError(publishBatchRequest, ex); } @@ -68,10 +63,10 @@ private void publish(final PublishBatchRequest publishBatchRequest) { @Override protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { + if (this.topicProperty.isFifo()) { publish(publishBatchRequest); } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + CompletableFuture.runAsync(() -> publish(publishBatchRequest), this.executorService); } } @@ -100,7 +95,7 @@ protected void handleError(final PublishBatchRequest publishBatchRequest, final LOGGER.error(ex.getMessage(), ex); publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.id()) .withCode(code) @@ -113,7 +108,7 @@ protected void handleError(final PublishBatchRequest publishBatchRequest, final @Override protected void handleResponse(final PublishBatchResponse publishBatchResult) { publishBatchResult.successful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); listenableFuture.success(ResponseSuccessEntry.builder() .withId(entry.id()) .withMessageId(entry.messageId()) @@ -122,7 +117,7 @@ protected void handleResponse(final PublishBatchResponse publishBatchResult) { }); publishBatchResult.failed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.id()) .withCode(entry.code()) diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index ccd9fb2..df97eae 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 73ef62d..72cafe0 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -1,24 +1,18 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.Semaphore; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.TopicProperty; @@ -36,11 +30,9 @@ public AmazonSnsTemplate( final TopicProperty topicProperty, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { - super.semaphoreProducer = new Semaphore(1); - super.semaphoreConsumer = new Semaphore(0); super.topicRequests = topicRequests; super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer = new AmazonSnsProducer<>(pendingRequests, topicRequests); + super.amazonSnsProducer = new AmazonSnsProducer<>(super.pendingRequests, super.topicRequests); super.amazonSnsConsumer.start(); } diff --git a/pom.xml b/pom.xml index 4d9bb50..3725248 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 2.22.2 false - ${jacoco.argLine} -Dfile.encoding=${project.build.sourceEncoding} + ${jacoco.argLine} -Dfile.encoding=${project.build.sourceEncoding} -Xms1024m -Xmx1024m From dd2e1ce8f35f476963371a47be6e3c26ceaa7289 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 21:45:40 -0300 Subject: [PATCH 09/20] chore: remove debug Signed-off-by: Marcos Tischer Vallim --- .../sns/messaging/lib/core/AbstractAmazonSnsProducer.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 6fbe70e..2c0b0c5 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -29,18 +29,10 @@ abstract class AbstractAmazonSnsProducer { private final BlockingQueue> topicRequests; - private Integer maxTopicRequests = 0; - - private Integer maxPendingRequests = 0; - @SneakyThrows public ListenableFuture send(final RequestEntry requestEntry) { final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); enqueueRequest(requestEntry); - maxTopicRequests = Math.max(maxTopicRequests, topicRequests.size()); - maxPendingRequests = Math.max(maxPendingRequests, pendingRequests.size()); - System.out.println("topicRequests : " + maxTopicRequests); - System.out.println("pendingRequests : " + maxPendingRequests); return trackPendingRequest; } From e1b24ba4930877d4c14279838b8edea24d4c6593 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Sun, 19 Mar 2023 23:28:15 -0300 Subject: [PATCH 10/20] feat: configuration thread pool Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsConsumer.java | 14 +++- .../lib/core/AmazonSnsThreadPoolExecutor.java | 64 +++++++------------ .../core/AmazonSnsThreadPoolExecutorTest.java | 20 +++++- .../messaging/lib/core/AmazonSnsConsumer.java | 2 +- .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++--- .../core/core/AmazonSnsProducerSyncTest.java | 16 ++--- .../messaging/lib/core/AmazonSnsConsumer.java | 2 +- .../core/core/AmazonSnsProducerAsyncTest.java | 16 ++--- .../core/core/AmazonSnsProducerSyncTest.java | 16 ++--- 9 files changed, 86 insertions(+), 80 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index ee145e0..1ae5151 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; @@ -49,7 +50,7 @@ abstract class AbstractAmazonSnsConsumer extends Thread implements Runn private final BlockingQueue> topicRequests; - protected final AmazonSnsThreadPoolExecutor executorService; + protected final ExecutorService executorService; protected AbstractAmazonSnsConsumer( final TopicProperty topicProperty, @@ -150,8 +151,7 @@ public CompletableFuture await() { return CompletableFuture.runAsync(() -> { while ( MapUtils.isNotEmpty(this.pendingRequests) || - CollectionUtils.isNotEmpty(this.topicRequests) || - this.executorService.getActiveTaskCount() > 0) { + CollectionUtils.isNotEmpty(this.topicRequests)) { sleep(1); } }); @@ -162,6 +162,14 @@ protected String convertPayload(final E payload) { return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); } + protected static AmazonSnsThreadPoolExecutor getAmazonSnsThreadPoolExecutor(final TopicProperty topicProperty) { + if (topicProperty.isFifo()) { + return new AmazonSnsThreadPoolExecutor(1); + } else { + return new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize()); + } + } + @SneakyThrows private static void sleep(final int millis) { Thread.sleep(millis); diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java index d9d1e31..e838ab3 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java @@ -1,17 +1,12 @@ /* * Copyright 2022 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -20,63 +15,52 @@ import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; public class AmazonSnsThreadPoolExecutor extends ThreadPoolExecutor { - private final Object lockObject = new Object(); + private final AtomicInteger activeTaskCount = new AtomicInteger(); - private int activeTaskCount = 0; + private final AtomicInteger failedTaskCount = new AtomicInteger(); - private int failedTaskCount = 0; - - private int succeededTaskCount = 0; + private final AtomicInteger succeededTaskCount = new AtomicInteger(); public AmazonSnsThreadPoolExecutor(final int maximumPoolSize) { - super(2, maximumPoolSize, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), new BlockingSubmissionPolicy(30000)); + super(0, maximumPoolSize, 60, TimeUnit.SECONDS, new SynchronousQueue<>(), new BlockingSubmissionPolicy(30000)); } public int getActiveTaskCount() { - synchronized (lockObject) { - return activeTaskCount; - } + return this.activeTaskCount.get(); } public int getFailedTaskCount() { - synchronized (lockObject) { - return failedTaskCount; - } + return this.failedTaskCount.get(); } public int getSucceededTaskCount() { - synchronized (lockObject) { - return succeededTaskCount; - } + return this.succeededTaskCount.get(); } @Override protected void beforeExecute(final Thread thread, final Runnable runnable) { - synchronized (lockObject) { - try { - super.beforeExecute(thread, runnable); - } finally { - activeTaskCount++; - } + try { + super.beforeExecute(thread, runnable); + } finally { + this.activeTaskCount.incrementAndGet(); } } @Override protected void afterExecute(final Runnable runnable, final Throwable throwable) { - synchronized (lockObject) { - try { - super.afterExecute(runnable, throwable); - } finally { - if (Objects.nonNull(throwable)) { - failedTaskCount++; - } else { - succeededTaskCount++; - } - activeTaskCount--; + try { + super.afterExecute(runnable, throwable); + } finally { + if (Objects.nonNull(throwable)) { + this.failedTaskCount.incrementAndGet(); + } else { + this.succeededTaskCount.incrementAndGet(); } + this.activeTaskCount.decrementAndGet(); } } diff --git a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java index ee435e1..c158cc9 100644 --- a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java +++ b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java @@ -19,7 +19,7 @@ public void testSuccessCounters() { assertThat(amazonSnsThreadPoolExecutor.getActiveTaskCount(), is(0)); assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); assertThat(amazonSnsThreadPoolExecutor.getFailedTaskCount(), is(0)); - assertThat(amazonSnsThreadPoolExecutor.getCorePoolSize(), is(2)); + assertThat(amazonSnsThreadPoolExecutor.getCorePoolSize(), is(0)); } @Test @@ -29,7 +29,13 @@ public void testSuccessSucceededTaskCount() throws InterruptedException { assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); for(int i = 0; i < 300; i++) { - amazonSnsThreadPoolExecutor.execute(() -> { }); + amazonSnsThreadPoolExecutor.execute(() -> { + try { + Thread.sleep(1); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + }); } amazonSnsThreadPoolExecutor.shutdown(); @@ -71,7 +77,15 @@ public void testSuccessActiveTaskCount() throws InterruptedException { assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); for(int i = 0; i < 10; i++) { - amazonSnsThreadPoolExecutor.execute(() -> { while(true); }); + amazonSnsThreadPoolExecutor.execute(() -> { + while(true) { + try { + Thread.sleep(1); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + }); } amazonSnsThreadPoolExecutor.shutdown(); diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index e1aa595..938b96e 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -50,7 +50,7 @@ public AmazonSnsConsumer( final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); + super(topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)); this.amazonSNS = amazonSNS; } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 7ee211b..4605b21 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index c86b27e..3d0a1b2 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -130,25 +130,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -169,25 +169,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 636d3d6..3ba8815 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -49,7 +49,7 @@ public AmazonSnsConsumer( final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize())); + super(topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)); this.amazonSNS = amazonSNS; } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index b66f795..83cbe69 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -133,25 +133,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -172,25 +172,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index c45b395..ebc9397 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -132,25 +132,25 @@ public void testSuccessMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(successCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(successCallback, timeout(300000).times(300000)).accept(any()); + verify(successCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -171,25 +171,25 @@ public void testFailureMultipleEntry() { })); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { - entries(100000).forEach(entry -> { + entries(10000).forEach(entry -> { this.snsTemplate.send(entry).addCallback(null, failureCallback); }); }); this.snsTemplate.await().thenAccept(result -> { - verify(failureCallback, timeout(300000).times(300000)).accept(any()); + verify(failureCallback, timeout(300000).times(30000)).accept(any()); verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } From 8a2d06f1be80dad9967c4c2d459d17498e8992e6 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Mon, 20 Mar 2023 11:24:01 -0300 Subject: [PATCH 11/20] feat: improve rejection policy tasks Signed-off-by: Marcos Tischer Vallim --- .../lib/core/AbstractAmazonSnsConsumer.java | 19 +-- .../lib/core/AbstractAmazonSnsProducer.java | 17 ++- .../lib/core/AbstractAmazonSnsTemplate.java | 21 ++-- .../lib/core/AbstractMessageAttributes.java | 2 +- .../lib/core/AmazonSnsThreadPoolExecutor.java | 29 +++-- .../lib/core/BlockingSubmissionPolicy.java | 13 +- .../messaging/lib/core/ListenableFuture.java | 2 +- .../lib/core/ListenableFutureRegistry.java | 2 +- .../core/AmazonSnsThreadPoolExecutorTest.java | 35 ++++++ .../messaging/lib/core/AmazonSnsConsumer.java | 35 ++++-- .../messaging/lib/core/AmazonSnsProducer.java | 15 ++- .../messaging/lib/core/AmazonSnsTemplate.java | 15 ++- .../messaging/lib/core/MessageAttributes.java | 2 +- .../core/core/AmazonSnsProducerAsyncTest.java | 113 +++++++++++------- .../core/core/AmazonSnsProducerSyncTest.java | 83 +++++++------ .../lib/core/core/MessageAttributesTest.java | 2 +- .../lib/core/helper/ConsumerHelper.java | 2 +- .../messaging/lib/core/AmazonSnsConsumer.java | 39 +++--- .../messaging/lib/core/AmazonSnsProducer.java | 15 ++- .../messaging/lib/core/AmazonSnsTemplate.java | 15 ++- .../messaging/lib/core/MessageAttributes.java | 2 +- .../core/core/AmazonSnsProducerAsyncTest.java | 111 +++++++++++------ .../core/core/AmazonSnsProducerSyncTest.java | 83 +++++++------ .../lib/core/core/MessageAttributesTest.java | 2 +- .../lib/core/helper/ConsumerHelper.java | 2 +- 25 files changed, 422 insertions(+), 254 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index 1ae5151..b0d0a77 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -72,7 +77,7 @@ protected AbstractAmazonSnsConsumer( protected abstract void publishBatch(final R publishBatchRequest); - protected abstract void handleError(final R publishBatchRequest, final Exception ex); + protected abstract void handleError(final R publishBatchRequest, final Throwable throwable); protected abstract void handleResponse(final O publishBatchResult); @@ -121,7 +126,7 @@ private boolean requestsWaitedFor(final BlockingQueue> requests, } private boolean maxBatchSizeReached(final BlockingQueue> requests) { - return requests.size() > this.topicProperty.getMaxBatchSize(); + return requests.size() > topicProperty.getMaxBatchSize(); } @SneakyThrows diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 2c0b0c5..8250164 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -43,7 +48,7 @@ private void enqueueRequest(final RequestEntry requestEntry) { private ListenableFuture trackPendingRequest(final String correlationId) { final ListenableFutureRegistry listenableFuture = new ListenableFutureRegistry(); - this.pendingRequests.put(correlationId, listenableFuture); + pendingRequests.put(correlationId, listenableFuture); return listenableFuture; } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 3c26c54..35e3d57 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -32,15 +37,15 @@ abstract class AbstractAmazonSnsTemplate { protected AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { - return this.amazonSnsProducer.send(requestEntry); + return amazonSnsProducer.send(requestEntry); } public void shutdown() { - this.amazonSnsConsumer.shutdown(); + amazonSnsConsumer.shutdown(); } public CompletableFuture await() { - return this.amazonSnsConsumer.await(); + return amazonSnsConsumer.await(); } } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractMessageAttributes.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractMessageAttributes.java index bf932a0..dd7b5a2 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractMessageAttributes.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractMessageAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java index e838ab3..f3e728f 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsThreadPoolExecutor.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -30,15 +35,15 @@ public AmazonSnsThreadPoolExecutor(final int maximumPoolSize) { } public int getActiveTaskCount() { - return this.activeTaskCount.get(); + return activeTaskCount.get(); } public int getFailedTaskCount() { - return this.failedTaskCount.get(); + return failedTaskCount.get(); } public int getSucceededTaskCount() { - return this.succeededTaskCount.get(); + return succeededTaskCount.get(); } @Override @@ -46,7 +51,7 @@ protected void beforeExecute(final Thread thread, final Runnable runnable) { try { super.beforeExecute(thread, runnable); } finally { - this.activeTaskCount.incrementAndGet(); + activeTaskCount.incrementAndGet(); } } @@ -56,11 +61,11 @@ protected void afterExecute(final Runnable runnable, final Throwable throwable) super.afterExecute(runnable, throwable); } finally { if (Objects.nonNull(throwable)) { - this.failedTaskCount.incrementAndGet(); + failedTaskCount.incrementAndGet(); } else { - this.succeededTaskCount.incrementAndGet(); + succeededTaskCount.incrementAndGet(); } - this.activeTaskCount.decrementAndGet(); + activeTaskCount.decrementAndGet(); } } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/BlockingSubmissionPolicy.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/BlockingSubmissionPolicy.java index 61698fb..8eda3bf 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/BlockingSubmissionPolicy.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/BlockingSubmissionPolicy.java @@ -22,6 +22,8 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import lombok.SneakyThrows; + class BlockingSubmissionPolicy implements RejectedExecutionHandler { private final long timeout; @@ -31,14 +33,11 @@ public BlockingSubmissionPolicy(final long timeout) { } @Override + @SneakyThrows public void rejectedExecution(final Runnable runnable, final ThreadPoolExecutor executor) { - try { - final BlockingQueue queue = executor.getQueue(); - if (!queue.offer(runnable, timeout, TimeUnit.MILLISECONDS)) { - throw new RejectedExecutionException("Timeout"); - } - } catch (final InterruptedException e) { - Thread.currentThread().interrupt(); + final BlockingQueue queue = executor.getQueue(); + if (!queue.offer(runnable, timeout, TimeUnit.MILLISECONDS)) { + throw new RejectedExecutionException("Timeout"); } } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFuture.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFuture.java index bdc1029..52082ee 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFuture.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFuture.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFutureRegistry.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFutureRegistry.java index 7827e62..f39a1d5 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFutureRegistry.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/ListenableFutureRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java index c158cc9..88dc77b 100644 --- a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java +++ b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java @@ -1,8 +1,26 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.amazon.sns.messaging.core; +import static org.assertj.core.api.Assertions.catchThrowableOfType; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import org.junit.Test; @@ -99,5 +117,22 @@ public void testSuccessActiveTaskCount() throws InterruptedException { assertThat(amazonSnsThreadPoolExecutor.getFailedTaskCount(), is(0)); } + @Test + public void testSuccessBlockingSubmissionPolicy() throws InterruptedException { + final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(1); + + amazonSnsThreadPoolExecutor.execute(() -> { + while(true) { + try { + Thread.sleep(1); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + }); + + catchThrowableOfType(() -> amazonSnsThreadPoolExecutor.execute(() -> { }), RejectedExecutionException.class); + } + } // @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 938b96e..a812faa 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -56,7 +61,7 @@ public AmazonSnsConsumer( private void publish(final PublishBatchRequest publishBatchRequest) { try { - handleResponse(this.amazonSNS.publishBatch(publishBatchRequest)); + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); } catch (final Exception ex) { handleError(publishBatchRequest, ex); } @@ -64,10 +69,14 @@ private void publish(final PublishBatchRequest publishBatchRequest) { @Override protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (this.topicProperty.isFifo()) { + if (topicProperty.isFifo()) { publish(publishBatchRequest); } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), this.executorService); + try { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } } } @@ -88,14 +97,14 @@ protected BiFunction>, PublishBatchRequest> supplie } @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorCode() : "000"; - final String message = ex instanceof AmazonServiceException ? AmazonServiceException.class.cast(ex).getErrorMessage() : ex.getMessage(); + protected void handleError(final PublishBatchRequest publishBatchRequest, final Throwable throwable) { + final String code = throwable instanceof AmazonServiceException ? AmazonServiceException.class.cast(throwable).getErrorCode() : "000"; + final String message = throwable instanceof AmazonServiceException ? AmazonServiceException.class.cast(throwable).getErrorMessage() : throwable.getMessage(); - LOGGER.error(ex.getMessage(), ex); + LOGGER.error(throwable.getMessage(), throwable); publishBatchRequest.getPublishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.getId()); + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.getId()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.getId()) .withCode(code) diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index df97eae..308d334 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 697245f..54ec40e 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java index ad74e35..05d6241 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 4605b21..0a33919 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -62,12 +67,12 @@ public class AmazonSnsProducerAsyncTest { @Before public void before() throws Exception { - when(this.topicProperty.isFifo()).thenReturn(false); - when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(50L); - when(this.topicProperty.getMaxBatchSize()).thenReturn(10); - this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty, new LinkedBlockingQueue<>(1024)); + when(topicProperty.isFifo()).thenReturn(false); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(10); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(10); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); } @Test @@ -80,16 +85,16 @@ public void testSuccess() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getSuccessful().add(publishBatchResultEntry); - when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - this.snsTemplate.shutdown(); - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); + snsTemplate.await().thenAccept(result -> { + snsTemplate.shutdown(); + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -104,15 +109,15 @@ public void testFailure() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getFailed().add(batchResultErrorEntry); - when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -120,7 +125,7 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) @@ -134,32 +139,32 @@ public void testSuccessMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(successCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @Test public void testFailureMultipleEntry() { - when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) @@ -173,25 +178,25 @@ public void testFailureMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(failureCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -199,15 +204,15 @@ public void testFailureMultipleEntry() { public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -216,19 +221,47 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } + @Test + public void testSuccessBlockingSubmissionPolicy() { + when(topicProperty.isFifo()).thenReturn(false); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(1); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(1); + + final AmazonSnsTemplate snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); + + when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + while (true) { + Thread.sleep(1); + } + }); + + final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { + assertThat(result, notNullValue()); + })); + + entries(2).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback);; + }); + + verify(failureCallback, timeout(40000).times(1)).accept(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any()); + } + private List> entries(final int amount) { final LinkedList> entries = new LinkedList<>(); diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 3d0a1b2..6b7cc95 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -60,12 +65,12 @@ public class AmazonSnsProducerSyncTest { @Before public void before() throws Exception { - when(this.topicProperty.isFifo()).thenReturn(true); - when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(50L); - when(this.topicProperty.getMaxBatchSize()).thenReturn(10); - this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty); + when(topicProperty.isFifo()).thenReturn(true); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(10); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(10); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); } @Test @@ -78,15 +83,15 @@ public void testSuccess() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getSuccessful().add(publishBatchResultEntry); - when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -101,15 +106,15 @@ public void testFailure() { final PublishBatchResult publishBatchResult = new PublishBatchResult(); publishBatchResult.getFailed().add(batchResultErrorEntry); - when(this.amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any())).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any()); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any()); }).join(); } @@ -117,7 +122,7 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) @@ -131,32 +136,32 @@ public void testSuccessMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(successCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @Test public void testFailureMultipleEntry() { - when(this.amazonSNS.publishBatch(any())).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) @@ -170,25 +175,25 @@ public void testFailureMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(failureCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any()); }).join(); } @@ -196,15 +201,15 @@ public void testFailureMultipleEntry() { public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -213,15 +218,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java index 77e5037..0212239 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java index e36d340..cbd68ea 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 3ba8815..3195a83 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; @@ -55,7 +60,7 @@ public AmazonSnsConsumer( private void publish(final PublishBatchRequest publishBatchRequest) { try { - handleResponse(this.amazonSNS.publishBatch(publishBatchRequest)); + handleResponse(amazonSNS.publishBatch(publishBatchRequest)); } catch (final Exception ex) { handleError(publishBatchRequest, ex); } @@ -63,10 +68,14 @@ private void publish(final PublishBatchRequest publishBatchRequest) { @Override protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (this.topicProperty.isFifo()) { + if (topicProperty.isFifo()) { publish(publishBatchRequest); } else { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), this.executorService); + try { + CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } } } @@ -88,14 +97,14 @@ protected BiFunction>, PublishBatchRequest> supplie } @Override - protected void handleError(final PublishBatchRequest publishBatchRequest, final Exception ex) { - final String code = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorCode() : "000"; - final String message = ex instanceof AwsServiceException ? AwsServiceException.class.cast(ex).awsErrorDetails().errorMessage() : ex.getMessage(); + protected void handleError(final PublishBatchRequest publishBatchRequest, final Throwable throwable) { + final String code = throwable instanceof AwsServiceException ? AwsServiceException.class.cast(throwable).awsErrorDetails().errorCode() : "000"; + final String message = throwable instanceof AwsServiceException ? AwsServiceException.class.cast(throwable).awsErrorDetails().errorMessage() : throwable.getMessage(); - LOGGER.error(ex.getMessage(), ex); + LOGGER.error(throwable.getMessage(), throwable); publishBatchRequest.publishBatchRequestEntries().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.id()) .withCode(code) @@ -108,7 +117,7 @@ protected void handleError(final PublishBatchRequest publishBatchRequest, final @Override protected void handleResponse(final PublishBatchResponse publishBatchResult) { publishBatchResult.successful().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); listenableFuture.success(ResponseSuccessEntry.builder() .withId(entry.id()) .withMessageId(entry.messageId()) @@ -117,7 +126,7 @@ protected void handleResponse(final PublishBatchResponse publishBatchResult) { }); publishBatchResult.failed().forEach(entry -> { - final ListenableFutureRegistry listenableFuture = this.pendingRequests.remove(entry.id()); + final ListenableFutureRegistry listenableFuture = pendingRequests.remove(entry.id()); listenableFuture.fail(ResponseFailEntry.builder() .withId(entry.id()) .withCode(entry.code()) diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index df97eae..308d334 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 72cafe0..b196f6a 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core; diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java index bd0c775..b0fa0ab 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/MessageAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 83cbe69..709f10f 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -63,12 +68,12 @@ public class AmazonSnsProducerAsyncTest { @Before public void before() throws Exception { - when(this.topicProperty.isFifo()).thenReturn(true); - when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(50L); - when(this.topicProperty.getMaxBatchSize()).thenReturn(10); - this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty, new LinkedBlockingQueue<>(1024)); + when(topicProperty.isFifo()).thenReturn(true); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(10); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(10); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); } @Test @@ -81,15 +86,15 @@ public void testSuccess() { .successful(publishBatchResultEntry) .build(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -104,15 +109,15 @@ public void testFailure() { .failed(batchResultErrorEntry) .build(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -120,7 +125,7 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) @@ -134,32 +139,32 @@ public void testSuccessMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(successCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @Test public void testFailureMultipleEntry() { - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) @@ -173,25 +178,25 @@ public void testFailureMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(failureCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -199,15 +204,15 @@ public void testFailureMultipleEntry() { public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -216,19 +221,47 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } + @Test + public void testSuccessBlockingSubmissionPolicy() { + when(topicProperty.isFifo()).thenReturn(false); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(1); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(1); + + final AmazonSnsTemplate snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); + + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + while (true) { + Thread.sleep(1); + } + }); + + final ConsumerHelper failureCallback = spy(new ConsumerHelper<>(result -> { + assertThat(result, notNullValue()); + })); + + entries(2).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback);; + }); + + verify(failureCallback, timeout(40000).times(1)).accept(any()); + verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + } + private List> entries(final int amount) { final LinkedList> entries = new LinkedList<>(); diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index ebc9397..b1a7196 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -1,12 +1,17 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package com.amazon.sns.messaging.lib.core.core; @@ -62,12 +67,12 @@ public class AmazonSnsProducerSyncTest { @Before public void before() throws Exception { - when(this.topicProperty.isFifo()).thenReturn(false); - when(this.topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(this.topicProperty.getMaximumPoolSize()).thenReturn(10); - when(this.topicProperty.getLinger()).thenReturn(50L); - when(this.topicProperty.getMaxBatchSize()).thenReturn(10); - this.snsTemplate = new AmazonSnsTemplate<>(this.amazonSNS, this.topicProperty); + when(topicProperty.isFifo()).thenReturn(false); + when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); + when(topicProperty.getMaximumPoolSize()).thenReturn(10); + when(topicProperty.getLinger()).thenReturn(50L); + when(topicProperty.getMaxBatchSize()).thenReturn(10); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); } @Test @@ -80,15 +85,15 @@ public void testSuccess() { .successful(publishBatchResultEntry) .build(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -103,15 +108,15 @@ public void testFailure() { .failed(batchResultErrorEntry) .build(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenReturn(publishBatchResult); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(null, result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -119,7 +124,7 @@ public void testFailure() { @Test public void testSuccessMultipleEntry() { - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) @@ -133,32 +138,32 @@ public void testSuccessMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(successCallback); + snsTemplate.send(entry).addCallback(successCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(successCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @Test public void testFailureMultipleEntry() { - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) @@ -172,25 +177,25 @@ public void testFailureMultipleEntry() { CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); CompletableFuture.runAsync(() -> { entries(10000).forEach(entry -> { - this.snsTemplate.send(entry).addCallback(null, failureCallback); + snsTemplate.send(entry).addCallback(null, failureCallback); }); }); - this.snsTemplate.await().thenAccept(result -> { + snsTemplate.await().thenAccept(result -> { verify(failureCallback, timeout(300000).times(30000)).accept(any()); - verify(this.amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); + verify(amazonSNS, atLeastOnce()).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -198,15 +203,15 @@ public void testFailureMultipleEntry() { public void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } @@ -215,15 +220,15 @@ public void testFailRiseRuntimeException() { public void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); - when(this.amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); + when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); - this.snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { + snsTemplate.send(RequestEntry.builder().withId(id).build()).addCallback(result -> { assertThat(result, notNullValue()); assertThat(result.getId(), is(id)); }); - this.snsTemplate.await().thenAccept(result -> { - verify(this.amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); + snsTemplate.await().thenAccept(result -> { + verify(amazonSNS, timeout(10000).times(1)).publishBatch(any(PublishBatchRequest.class)); }).join(); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java index ecfab39..fb4d167 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java index e36d340..cbd68ea 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/helper/ConsumerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 the original author or authors. + * Copyright 2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From f5d09cdbcfdba6462110267e866ca621baa1ee6e Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Mon, 19 Feb 2024 01:49:01 -0300 Subject: [PATCH 12/20] feat: improve CPU consume --- .../lib/core/AbstractAmazonSnsConsumer.java | 72 ++++++++----------- .../lib/core/AbstractAmazonSnsProducer.java | 3 +- .../core/core/AmazonSnsProducerAsyncTest.java | 37 ++-------- .../core/core/AmazonSnsProducerSyncTest.java | 37 ++-------- .../core/core/AmazonSnsProducerAsyncTest.java | 37 ++-------- .../core/core/AmazonSnsProducerSyncTest.java | 37 ++-------- 6 files changed, 47 insertions(+), 176 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index b0d0a77..3d0bfca 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -24,6 +24,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; @@ -38,15 +40,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AccessLevel; -import lombok.Getter; -import lombok.Setter; +import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; // @formatter:off -abstract class AbstractAmazonSnsConsumer extends Thread implements Runnable { +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +abstract class AbstractAmazonSnsConsumer implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsConsumer.class); + private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + protected final TopicProperty topicProperty; private final ObjectMapper objectMapper; @@ -57,24 +61,6 @@ abstract class AbstractAmazonSnsConsumer extends Thread implements Runn protected final ExecutorService executorService; - protected AbstractAmazonSnsConsumer( - final TopicProperty topicProperty, - final ObjectMapper objectMapper, - final ConcurrentMap pendingRequests, - final BlockingQueue> topicRequests, - final AmazonSnsThreadPoolExecutor executorService) { - super(String.format("amazon-sns-consumer-%s", topicProperty.getTopicArn())); - this.topicProperty = topicProperty; - this.objectMapper = objectMapper; - this.pendingRequests = pendingRequests; - this.topicRequests = topicRequests; - this.executorService = executorService; - } - - @Getter - @Setter(value = AccessLevel.PRIVATE) - private boolean running = true; - protected abstract void publishBatch(final R publishBatchRequest); protected abstract void handleError(final R publishBatchRequest, final Throwable throwable); @@ -83,38 +69,38 @@ protected AbstractAmazonSnsConsumer( protected abstract BiFunction>, R> supplierPublishRequest(); + protected void start() { + scheduledExecutorService.scheduleAtFixedRate(this, 0, topicProperty.getLinger(), TimeUnit.MILLISECONDS); + } + @Override @SneakyThrows public void run() { - while (isRunning()) { - try { - - if (topicRequests.isEmpty()) { - sleep(1); - } - - final boolean maxWaitTimeElapsed = requestsWaitedFor(topicRequests, topicProperty.getLinger()); - final boolean maxBatchSizeReached = maxBatchSizeReached(topicRequests); - - if (maxWaitTimeElapsed || maxBatchSizeReached) { - createBatch(topicRequests).ifPresent(this::publishBatch); - } - - } catch (final Exception ex) { - LOGGER.error(ex.getMessage(), ex); + try { + while (requestsWaitedFor(topicRequests, topicProperty.getLinger()) || maxBatchSizeReached(topicRequests)) { + createBatch(topicRequests).ifPresent(this::publishBatch); } + } catch (final Exception ex) { + LOGGER.error(ex.getMessage(), ex); } } @SneakyThrows public void shutdown() { - LOGGER.warn("Shutdown producer {}", getClass().getSimpleName()); - setRunning(false); + LOGGER.warn("Shutdown consumer {}", getClass().getSimpleName()); + + scheduledExecutorService.shutdown(); + if (!scheduledExecutorService.awaitTermination(60, TimeUnit.SECONDS)) { + LOGGER.warn("Scheduled executor service did not terminate in the specified time."); + final List droppedTasks = executorService.shutdownNow(); + LOGGER.warn("Scheduled executor service was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); + } + executorService.shutdown(); if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { - LOGGER.warn("Executor did not terminate in the specified time."); + LOGGER.warn("Executor service did not terminate in the specified time."); final List droppedTasks = executorService.shutdownNow(); - LOGGER.warn("Executor was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); + LOGGER.warn("Executor service was abruptly shut down. {} tasks will not be executed.", droppedTasks.size()); } } @@ -157,7 +143,7 @@ public CompletableFuture await() { while ( MapUtils.isNotEmpty(this.pendingRequests) || CollectionUtils.isNotEmpty(this.topicRequests)) { - sleep(1); + sleep(topicProperty.getLinger()); } }); } @@ -176,7 +162,7 @@ protected static AmazonSnsThreadPoolExecutor getAmazonSnsThreadPoolExecutor(fina } @SneakyThrows - private static void sleep(final int millis) { + private static void sleep(final long millis) { Thread.sleep(millis); } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 8250164..5935425 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -23,11 +23,12 @@ import com.amazon.sns.messaging.lib.model.ResponseFailEntry; import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; // @formatter:off -@RequiredArgsConstructor +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) abstract class AbstractAmazonSnsProducer { private final ConcurrentMap pendingRequests; diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 0a33919..19bf02b 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; @@ -137,22 +136,8 @@ public void testSuccessMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(successCallback); }); snsTemplate.await().thenAccept(result -> { @@ -176,22 +161,8 @@ public void testFailureMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback); }); snsTemplate.await().thenAccept(result -> { diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 6b7cc95..b94c74b 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import org.junit.Before; @@ -134,22 +133,8 @@ public void testSuccessMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(successCallback); }); snsTemplate.await().thenAccept(result -> { @@ -173,22 +158,8 @@ public void testFailureMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback); }); snsTemplate.await().thenAccept(result -> { diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 709f10f..f9c85d4 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; @@ -137,22 +136,8 @@ public void testSuccessMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(successCallback); }); snsTemplate.await().thenAccept(result -> { @@ -176,22 +161,8 @@ public void testFailureMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback); }); snsTemplate.await().thenAccept(result -> { diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index b1a7196..11f7c1f 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import org.junit.Before; @@ -136,22 +135,8 @@ public void testSuccessMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(successCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(successCallback); }); snsTemplate.await().thenAccept(result -> { @@ -175,22 +160,8 @@ public void testFailureMultipleEntry() { assertThat(result, notNullValue()); })); - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); - }); - - CompletableFuture.runAsync(() -> { - entries(10000).forEach(entry -> { - snsTemplate.send(entry).addCallback(null, failureCallback); - }); + entries(30000).forEach(entry -> { + snsTemplate.send(entry).addCallback(null, failureCallback); }); snsTemplate.await().thenAccept(result -> { From a2c4d37a30f2f580c91c6098ac817067c15d86c6 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Mon, 19 Feb 2024 02:06:19 -0300 Subject: [PATCH 13/20] Update maven.yml --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9850e29..7635766 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -68,10 +68,10 @@ jobs: needs: [build, test] steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: 11 + java-version: 17 distribution: "corretto" cache: "maven" - name: Cache SonarQube packages From c9affbb22404d9cef1a6b879a84d9927c646e23c Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Mon, 19 Feb 2024 02:16:24 -0300 Subject: [PATCH 14/20] chore(test): fixing multi-threaded mockito --- .../core/core/AmazonSnsProducerAsyncTest.java | 27 ++++++++++--------- .../core/core/AmazonSnsProducerSyncTest.java | 16 +++++------ .../core/core/AmazonSnsProducerAsyncTest.java | 27 ++++++++++--------- .../core/core/AmazonSnsProducerSyncTest.java | 16 +++++------ 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 19bf02b..20898f4 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -61,16 +61,15 @@ public class AmazonSnsProducerAsyncTest { @Mock private AmazonSNS amazonSNS; - @Mock - private TopicProperty topicProperty; - @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(false) + .linger(50L) + .maxBatchSize(10) + .maximumPoolSize(10) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); } @@ -207,11 +206,13 @@ public void testFailRiseAwsServiceException() { @Test public void testSuccessBlockingSubmissionPolicy() { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(1); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(1); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(false) + .linger(50L) + .maxBatchSize(1) + .maximumPoolSize(1) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); final AmazonSnsTemplate snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index b94c74b..c7a8ca1 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -59,16 +59,16 @@ public class AmazonSnsProducerSyncTest { @Mock private AmazonSNS amazonSNS; - @Mock - private TopicProperty topicProperty; - @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(true); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(true) + .linger(50L) + .maxBatchSize(10) + .maximumPoolSize(10) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); } diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index f9c85d4..e3f7208 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -62,16 +62,17 @@ public class AmazonSnsProducerAsyncTest { @Mock private SnsClient amazonSNS; - @Mock - private TopicProperty topicProperty; @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(true); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(false) + .linger(50L) + .maxBatchSize(10) + .maximumPoolSize(10) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty, new LinkedBlockingQueue<>(1024)); } @@ -207,11 +208,13 @@ public void testFailRiseAwsServiceException() { @Test public void testSuccessBlockingSubmissionPolicy() { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(1); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(1); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(false) + .linger(50L) + .maxBatchSize(1) + .maximumPoolSize(1) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); final AmazonSnsTemplate snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index 11f7c1f..bc4d169 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -61,16 +61,16 @@ public class AmazonSnsProducerSyncTest { @Mock private SnsClient amazonSNS; - @Mock - private TopicProperty topicProperty; - @Before public void before() throws Exception { - when(topicProperty.isFifo()).thenReturn(false); - when(topicProperty.getTopicArn()).thenReturn("arn:aws:sns:us-east-2:000000000000:topic"); - when(topicProperty.getMaximumPoolSize()).thenReturn(10); - when(topicProperty.getLinger()).thenReturn(50L); - when(topicProperty.getMaxBatchSize()).thenReturn(10); + final TopicProperty topicProperty = TopicProperty.builder() + .fifo(true) + .linger(50L) + .maxBatchSize(10) + .maximumPoolSize(10) + .topicArn("arn:aws:sns:us-east-2:000000000000:topic") + .build(); + snsTemplate = new AmazonSnsTemplate<>(amazonSNS, topicProperty); } From 60aa50c4a47ef9470a96b96c3dc501bafcf9ae9c Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Mon, 19 Feb 2024 21:41:38 -0300 Subject: [PATCH 15/20] feat: improve performance --- .../lib/core/AbstractAmazonSnsConsumer.java | 26 ++++++++++--------- .../lib/core/AbstractAmazonSnsProducer.java | 6 ++++- .../lib/core/AbstractAmazonSnsTemplate.java | 24 ++++++++++------- .../messaging/lib/core/AmazonSnsConsumer.java | 6 +++-- .../messaging/lib/core/AmazonSnsProducer.java | 6 +++-- .../messaging/lib/core/AmazonSnsTemplate.java | 15 ++++++----- .../messaging/lib/core/AmazonSnsConsumer.java | 6 +++-- .../messaging/lib/core/AmazonSnsProducer.java | 6 +++-- .../messaging/lib/core/AmazonSnsTemplate.java | 15 ++++++----- 9 files changed, 68 insertions(+), 42 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index 3d0bfca..262f92f 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -39,12 +39,10 @@ import com.amazon.sns.messaging.lib.model.TopicProperty; import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; // @formatter:off -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +//@RequiredArgsConstructor(access = AccessLevel.PROTECTED) abstract class AbstractAmazonSnsConsumer implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsConsumer.class); @@ -69,7 +67,19 @@ abstract class AbstractAmazonSnsConsumer implements Runnable { protected abstract BiFunction>, R> supplierPublishRequest(); - protected void start() { + protected AbstractAmazonSnsConsumer( + final TopicProperty topicProperty, + final ObjectMapper objectMapper, + final ConcurrentMap pendingRequests, + final BlockingQueue> topicRequests, + final ExecutorService executorService) { + + this.topicProperty = topicProperty; + this.objectMapper = objectMapper; + this.pendingRequests = pendingRequests; + this.topicRequests = topicRequests; + this.executorService = executorService; + scheduledExecutorService.scheduleAtFixedRate(this, 0, topicProperty.getLinger(), TimeUnit.MILLISECONDS); } @@ -153,14 +163,6 @@ protected String convertPayload(final E payload) { return payload instanceof String ? payload.toString() : objectMapper.writeValueAsString(payload); } - protected static AmazonSnsThreadPoolExecutor getAmazonSnsThreadPoolExecutor(final TopicProperty topicProperty) { - if (topicProperty.isFifo()) { - return new AmazonSnsThreadPoolExecutor(1); - } else { - return new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize()); - } - } - @SneakyThrows private static void sleep(final long millis) { Thread.sleep(millis); diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java index 5935425..0ee7162 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsProducer.java @@ -17,7 +17,9 @@ package com.amazon.sns.messaging.lib.core; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.ResponseFailEntry; @@ -35,10 +37,12 @@ abstract class AbstractAmazonSnsProducer { private final BlockingQueue> topicRequests; + private final ExecutorService executorService; + @SneakyThrows public ListenableFuture send(final RequestEntry requestEntry) { final ListenableFuture trackPendingRequest = trackPendingRequest(requestEntry.getId()); - enqueueRequest(requestEntry); + CompletableFuture.runAsync(() -> enqueueRequest(requestEntry), executorService); return trackPendingRequest; } diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 35e3d57..1951ab9 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -16,25 +16,23 @@ package com.amazon.sns.messaging.lib.core; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import com.amazon.sns.messaging.lib.model.RequestEntry; import com.amazon.sns.messaging.lib.model.ResponseFailEntry; import com.amazon.sns.messaging.lib.model.ResponseSuccessEntry; +import com.amazon.sns.messaging.lib.model.TopicProperty; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; // @formatter:off +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) abstract class AbstractAmazonSnsTemplate { - protected final ConcurrentMap pendingRequests = new ConcurrentHashMap<>(); - - protected BlockingQueue> topicRequests; - - protected AbstractAmazonSnsProducer amazonSnsProducer; + private final AbstractAmazonSnsProducer amazonSnsProducer; - protected AbstractAmazonSnsConsumer amazonSnsConsumer; + private final AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { return amazonSnsProducer.send(requestEntry); @@ -48,5 +46,13 @@ public CompletableFuture await() { return amazonSnsConsumer.await(); } + protected static AmazonSnsThreadPoolExecutor getAmazonSnsThreadPoolExecutor(final TopicProperty topicProperty) { + if (topicProperty.isFifo()) { + return new AmazonSnsThreadPoolExecutor(1); + } else { + return new AmazonSnsThreadPoolExecutor(topicProperty.getMaximumPoolSize()); + } + } + } // @formatter:on diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index a812faa..bb0c497 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -20,6 +20,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import java.util.function.BiFunction; import java.util.stream.Collectors; @@ -54,8 +55,9 @@ public AmazonSnsConsumer( final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, - final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)); + final BlockingQueue> topicRequests, + final ExecutorService executorService) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, executorService); this.amazonSNS = amazonSNS; } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index 308d334..241bd53 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -26,8 +27,9 @@ class AmazonSnsProducer extends AbstractAmazonSnsProducer { public AmazonSnsProducer( final ConcurrentMap pendingRequests, - final BlockingQueue> topicRequests) { - super(pendingRequests, topicRequests); + final BlockingQueue> topicRequests, + final ExecutorService executorService) { + super(pendingRequests, topicRequests, executorService); } } diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 54ec40e..e22f218 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -17,6 +17,8 @@ package com.amazon.sns.messaging.lib.core; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingQueue; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -32,20 +34,21 @@ public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate pendingRequests, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { - super.topicRequests = topicRequests; - super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer = new AmazonSnsProducer<>(super.pendingRequests, super.topicRequests); - super.amazonSnsConsumer.start(); + super( + new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), + new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) + ); } public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { - this(amazonSNS, topicProperty, topicRequests, new ObjectMapper()); + this(amazonSNS, topicProperty, new ConcurrentHashMap<>(), topicRequests, new ObjectMapper()); } public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper) { - this(amazonSNS, topicProperty, new LinkedBlockingQueue<>(topicProperty.getMaximumPoolSize() * topicProperty.getMaxBatchSize()), objectMapper); + this(amazonSNS, topicProperty, new ConcurrentHashMap<>(), new LinkedBlockingQueue<>(topicProperty.getMaximumPoolSize() * topicProperty.getMaxBatchSize()), objectMapper); } public AmazonSnsTemplate(final AmazonSNS amazonSNS, final TopicProperty topicProperty) { diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 3195a83..3fb08fa 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -20,6 +20,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import java.util.function.BiFunction; import java.util.stream.Collectors; @@ -53,8 +54,9 @@ public AmazonSnsConsumer( final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, - final BlockingQueue> topicRequests) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)); + final BlockingQueue> topicRequests, + final ExecutorService executorService) { + super(topicProperty, objectMapper, pendingRequests, topicRequests, executorService); this.amazonSNS = amazonSNS; } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java index 308d334..241bd53 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsProducer.java @@ -18,6 +18,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutorService; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -26,8 +27,9 @@ class AmazonSnsProducer extends AbstractAmazonSnsProducer { public AmazonSnsProducer( final ConcurrentMap pendingRequests, - final BlockingQueue> topicRequests) { - super(pendingRequests, topicRequests); + final BlockingQueue> topicRequests, + final ExecutorService executorService) { + super(pendingRequests, topicRequests, executorService); } } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index b196f6a..8a4727b 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -17,6 +17,8 @@ package com.amazon.sns.messaging.lib.core; import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingQueue; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -33,20 +35,21 @@ public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate pendingRequests, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { - super.topicRequests = topicRequests; - super.amazonSnsConsumer = new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, super.pendingRequests, super.topicRequests); - super.amazonSnsProducer = new AmazonSnsProducer<>(super.pendingRequests, super.topicRequests); - super.amazonSnsConsumer.start(); + super( + new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), + new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) + ); } public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final BlockingQueue> topicRequests) { - this(amazonSNS, topicProperty, topicRequests, new ObjectMapper()); + this(amazonSNS, topicProperty, new ConcurrentHashMap<>(), topicRequests, new ObjectMapper()); } public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty, final ObjectMapper objectMapper) { - this(amazonSNS, topicProperty, new LinkedBlockingQueue<>(topicProperty.getMaximumPoolSize() * topicProperty.getMaxBatchSize()), objectMapper); + this(amazonSNS, topicProperty, new ConcurrentHashMap<>(), new LinkedBlockingQueue<>(topicProperty.getMaximumPoolSize() * topicProperty.getMaxBatchSize()), objectMapper); } public AmazonSnsTemplate(final SnsClient amazonSNS, final TopicProperty topicProperty) { From 604e2ea7fda5c5851bae0185a1f700fa5eb6507c Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Tue, 20 Feb 2024 19:46:33 -0300 Subject: [PATCH 16/20] chore(dep): update dependencies version Merge branch 'feature/interprocess-semaphore' of git@github.com:mvallim/amazon-sns-java-messaging-lib.git into feature/interprocess-semaphore --- .../core/AmazonSnsThreadPoolExecutorTest.java | 14 +- .../sns/messaging/model/RequestEntryTest.java | 6 +- .../core/core/AmazonSnsProducerAsyncTest.java | 34 +- .../core/core/AmazonSnsProducerSyncTest.java | 32 +- .../lib/core/core/MessageAttributesTest.java | 16 +- .../core/core/AmazonSnsProducerAsyncTest.java | 35 +- .../core/core/AmazonSnsProducerSyncTest.java | 32 +- .../lib/core/core/MessageAttributesTest.java | 16 +- pom.xml | 405 +++++++++++------- 9 files changed, 331 insertions(+), 259 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java index 88dc77b..a68b45b 100644 --- a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java +++ b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/core/AmazonSnsThreadPoolExecutorTest.java @@ -23,15 +23,15 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.amazon.sns.messaging.lib.core.AmazonSnsThreadPoolExecutor; // @formatter:off -public class AmazonSnsThreadPoolExecutorTest { +class AmazonSnsThreadPoolExecutorTest { @Test - public void testSuccessCounters() { + void testSuccessCounters() { final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(10); assertThat(amazonSnsThreadPoolExecutor.getActiveTaskCount(), is(0)); @@ -41,7 +41,7 @@ public void testSuccessCounters() { } @Test - public void testSuccessSucceededTaskCount() throws InterruptedException { + void testSuccessSucceededTaskCount() throws InterruptedException { final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(10); assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); @@ -68,7 +68,7 @@ public void testSuccessSucceededTaskCount() throws InterruptedException { } @Test - public void testSuccessFailedTaskCount() throws InterruptedException { + void testSuccessFailedTaskCount() throws InterruptedException { final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(10); assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); @@ -89,7 +89,7 @@ public void testSuccessFailedTaskCount() throws InterruptedException { } @Test - public void testSuccessActiveTaskCount() throws InterruptedException { + void testSuccessActiveTaskCount() throws InterruptedException { final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(10); assertThat(amazonSnsThreadPoolExecutor.getSucceededTaskCount(), is(0)); @@ -118,7 +118,7 @@ public void testSuccessActiveTaskCount() throws InterruptedException { } @Test - public void testSuccessBlockingSubmissionPolicy() throws InterruptedException { + void testSuccessBlockingSubmissionPolicy() throws InterruptedException { final AmazonSnsThreadPoolExecutor amazonSnsThreadPoolExecutor = new AmazonSnsThreadPoolExecutor(1); amazonSnsThreadPoolExecutor.execute(() -> { diff --git a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/model/RequestEntryTest.java b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/model/RequestEntryTest.java index eb7f4e3..a26e99b 100644 --- a/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/model/RequestEntryTest.java +++ b/amazon-sns-java-messaging-lib-template/src/test/java/com/amazon/sns/messaging/model/RequestEntryTest.java @@ -22,15 +22,15 @@ import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.amazon.sns.messaging.lib.model.RequestEntry; // @formatter:off -public class RequestEntryTest { +class RequestEntryTest { @Test - public void testSuccess() { + void testSuccess() { final Map messageHeaders = new HashMap<>(); final RequestEntry requestEntry = RequestEntry.builder() diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index 20898f4..f7b2fe8 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; @@ -33,11 +33,11 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.RandomStringUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -53,15 +53,15 @@ import com.amazonaws.services.sns.model.PublishBatchResultEntry; // @formatter:off -@RunWith(MockitoJUnitRunner.class) -public class AmazonSnsProducerAsyncTest { +@ExtendWith(MockitoExtension.class) +class AmazonSnsProducerAsyncTest { private AmazonSnsTemplate snsTemplate; @Mock private AmazonSNS amazonSNS; - @Before + @BeforeEach public void before() throws Exception { final TopicProperty topicProperty = TopicProperty.builder() .fifo(false) @@ -74,7 +74,7 @@ public void before() throws Exception { } @Test - public void testSuccess() { + void testSuccess() { final String id = UUID.randomUUID().toString(); final PublishBatchResultEntry publishBatchResultEntry = new PublishBatchResultEntry(); @@ -98,7 +98,7 @@ public void testSuccess() { } @Test - public void testFailure() { + void testFailure() { final String id = UUID.randomUUID().toString(); final BatchResultErrorEntry batchResultErrorEntry = new BatchResultErrorEntry(); @@ -121,10 +121,10 @@ public void testFailure() { } @Test - public void testSuccessMultipleEntry() { + void testSuccessMultipleEntry() { when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) .collect(Collectors.toList()); @@ -146,10 +146,10 @@ public void testSuccessMultipleEntry() { } @Test - public void testFailureMultipleEntry() { + void testFailureMultipleEntry() { when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) .collect(Collectors.toList()); @@ -171,7 +171,7 @@ public void testFailureMultipleEntry() { } @Test - public void testFailRiseRuntimeException() { + void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); @@ -188,7 +188,7 @@ public void testFailRiseRuntimeException() { } @Test - public void testFailRiseAwsServiceException() { + void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); @@ -205,7 +205,7 @@ public void testFailRiseAwsServiceException() { } @Test - public void testSuccessBlockingSubmissionPolicy() { + void testSuccessBlockingSubmissionPolicy() { final TopicProperty topicProperty = TopicProperty.builder() .fifo(false) .linger(50L) diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index c7a8ca1..e5d0275 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; @@ -31,11 +31,11 @@ import java.util.UUID; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -51,15 +51,15 @@ import com.amazonaws.services.sns.model.PublishBatchResultEntry; // @formatter:off -@RunWith(MockitoJUnitRunner.class) -public class AmazonSnsProducerSyncTest { +@ExtendWith(MockitoExtension.class) +class AmazonSnsProducerSyncTest { private AmazonSnsTemplate snsTemplate; @Mock private AmazonSNS amazonSNS; - @Before + @BeforeEach public void before() throws Exception { final TopicProperty topicProperty = TopicProperty.builder() .fifo(true) @@ -73,7 +73,7 @@ public void before() throws Exception { } @Test - public void testSuccess() { + void testSuccess() { final String id = UUID.randomUUID().toString(); final PublishBatchResultEntry publishBatchResultEntry = new PublishBatchResultEntry(); @@ -96,7 +96,7 @@ public void testSuccess() { } @Test - public void testFailure() { + void testFailure() { final String id = UUID.randomUUID().toString(); final BatchResultErrorEntry batchResultErrorEntry = new BatchResultErrorEntry(); @@ -119,10 +119,10 @@ public void testFailure() { } @Test - public void testSuccessMultipleEntry() { + void testSuccessMultipleEntry() { when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new PublishBatchResultEntry().withId(entry.getId())) .collect(Collectors.toList()); @@ -144,10 +144,10 @@ public void testSuccessMultipleEntry() { } @Test - public void testFailureMultipleEntry() { + void testFailureMultipleEntry() { when(amazonSNS.publishBatch(any())).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.getPublishBatchRequestEntries().stream() .map(entry -> new BatchResultErrorEntry().withId(entry.getId())) .collect(Collectors.toList()); @@ -169,7 +169,7 @@ public void testFailureMultipleEntry() { } @Test - public void testFailRiseRuntimeException() { + void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); @@ -186,7 +186,7 @@ public void testFailRiseRuntimeException() { } @Test - public void testFailRiseAwsServiceException() { + void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new AmazonServiceException("error")); diff --git a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java index 0212239..491a64f 100644 --- a/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java +++ b/amazon-sns-java-messaging-lib-v1/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java @@ -24,17 +24,17 @@ import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.amazon.sns.messaging.lib.core.MessageAttributes; import com.amazonaws.services.sns.model.MessageAttributeValue; -public class MessageAttributesTest { +class MessageAttributesTest { private final MessageAttributes messageAttributes = new MessageAttributes(); @Test - public void testSuccessStringHeader() { + void testSuccessStringHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("string", "string"); @@ -46,7 +46,7 @@ public void testSuccessStringHeader() { } @Test - public void testSuccessEnumHeader() { + void testSuccessEnumHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("enum", Cards.A); @@ -58,7 +58,7 @@ public void testSuccessEnumHeader() { } @Test - public void testSuccessNumberHeader() { + void testSuccessNumberHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("number", 1); @@ -70,7 +70,7 @@ public void testSuccessNumberHeader() { } @Test - public void testSuccessBinaryHeader() { + void testSuccessBinaryHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("binary", ByteBuffer.wrap(new byte[0])); @@ -82,7 +82,7 @@ public void testSuccessBinaryHeader() { } @Test - public void testSuccessStringArrayHeader() { + void testSuccessStringArrayHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("stringArray", Arrays.asList("123", 1, new Object(), "456")); @@ -94,7 +94,7 @@ public void testSuccessStringArrayHeader() { } @Test - public void testFailUnsupportedHeader() { + void testFailUnsupportedHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("unsupported", new Object()); diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java index e3f7208..c0eca6d 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerAsyncTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; @@ -32,11 +32,11 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -54,16 +54,15 @@ import software.amazon.awssdk.services.sns.model.PublishBatchResultEntry; // @formatter:off -@RunWith(MockitoJUnitRunner.class) -public class AmazonSnsProducerAsyncTest { +@ExtendWith(MockitoExtension.class) +class AmazonSnsProducerAsyncTest { private AmazonSnsTemplate snsTemplate; @Mock private SnsClient amazonSNS; - - @Before + @BeforeEach public void before() throws Exception { final TopicProperty topicProperty = TopicProperty.builder() .fifo(false) @@ -77,7 +76,7 @@ public void before() throws Exception { } @Test - public void testSuccess() { + void testSuccess() { final String id = UUID.randomUUID().toString(); final PublishBatchResultEntry publishBatchResultEntry = PublishBatchResultEntry.builder().id(id).build(); @@ -100,7 +99,7 @@ public void testSuccess() { } @Test - public void testFailure() { + void testFailure() { final String id = UUID.randomUUID().toString(); final BatchResultErrorEntry batchResultErrorEntry = BatchResultErrorEntry.builder().id(id).build(); @@ -123,10 +122,10 @@ public void testFailure() { } @Test - public void testSuccessMultipleEntry() { + void testSuccessMultipleEntry() { when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) .collect(Collectors.toList()); @@ -148,10 +147,10 @@ public void testSuccessMultipleEntry() { } @Test - public void testFailureMultipleEntry() { + void testFailureMultipleEntry() { when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) .collect(Collectors.toList()); @@ -173,7 +172,7 @@ public void testFailureMultipleEntry() { } @Test - public void testFailRiseRuntimeException() { + void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); @@ -190,7 +189,7 @@ public void testFailRiseRuntimeException() { } @Test - public void testFailRiseAwsServiceException() { + void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); @@ -207,7 +206,7 @@ public void testFailRiseAwsServiceException() { } @Test - public void testSuccessBlockingSubmissionPolicy() { + void testSuccessBlockingSubmissionPolicy() { final TopicProperty topicProperty = TopicProperty.builder() .fifo(false) .linger(50L) diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java index bc4d169..b584b16 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/AmazonSnsProducerSyncTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Matchers.any; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; @@ -31,11 +31,11 @@ import java.util.UUID; import java.util.stream.Collectors; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazon.sns.messaging.lib.core.AmazonSnsTemplate; import com.amazon.sns.messaging.lib.core.helper.ConsumerHelper; @@ -53,15 +53,15 @@ import software.amazon.awssdk.services.sns.model.PublishBatchResultEntry; // @formatter:off -@RunWith(MockitoJUnitRunner.class) -public class AmazonSnsProducerSyncTest { +@ExtendWith(MockitoExtension.class) +class AmazonSnsProducerSyncTest { private AmazonSnsTemplate snsTemplate; @Mock private SnsClient amazonSNS; - @Before + @BeforeEach public void before() throws Exception { final TopicProperty topicProperty = TopicProperty.builder() .fifo(true) @@ -75,7 +75,7 @@ public void before() throws Exception { } @Test - public void testSuccess() { + void testSuccess() { final String id = UUID.randomUUID().toString(); final PublishBatchResultEntry publishBatchResultEntry = PublishBatchResultEntry.builder().id(id).build(); @@ -98,7 +98,7 @@ public void testSuccess() { } @Test - public void testFailure() { + void testFailure() { final String id = UUID.randomUUID().toString(); final BatchResultErrorEntry batchResultErrorEntry = BatchResultErrorEntry.builder().id(id).build(); @@ -121,10 +121,10 @@ public void testFailure() { } @Test - public void testSuccessMultipleEntry() { + void testSuccessMultipleEntry() { when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> PublishBatchResultEntry.builder().id(entry.id()).build()) .collect(Collectors.toList()); @@ -146,10 +146,10 @@ public void testSuccessMultipleEntry() { } @Test - public void testFailureMultipleEntry() { + void testFailureMultipleEntry() { when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenAnswer(invocation -> { - final PublishBatchRequest request = invocation.getArgumentAt(0, PublishBatchRequest.class); + final PublishBatchRequest request = invocation.getArgument(0, PublishBatchRequest.class); final List resultEntries = request.publishBatchRequestEntries().stream() .map(entry -> BatchResultErrorEntry.builder().id(entry.id()).build()) .collect(Collectors.toList()); @@ -171,7 +171,7 @@ public void testFailureMultipleEntry() { } @Test - public void testFailRiseRuntimeException() { + void testFailRiseRuntimeException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(new RuntimeException()); @@ -188,7 +188,7 @@ public void testFailRiseRuntimeException() { } @Test - public void testFailRiseAwsServiceException() { + void testFailRiseAwsServiceException() { final String id = UUID.randomUUID().toString(); when(amazonSNS.publishBatch(any(PublishBatchRequest.class))).thenThrow(AwsServiceException.builder().awsErrorDetails(AwsErrorDetails.builder().build()).build()); diff --git a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java index fb4d167..6cbb57e 100644 --- a/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java +++ b/amazon-sns-java-messaging-lib-v2/src/test/java/com/amazon/sns/messaging/lib/core/core/MessageAttributesTest.java @@ -24,19 +24,19 @@ import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import com.amazon.sns.messaging.lib.core.MessageAttributes; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.sns.model.MessageAttributeValue; -public class MessageAttributesTest { +class MessageAttributesTest { private final MessageAttributes messageAttributes = new MessageAttributes(); @Test - public void testSuccessStringHeader() { + void testSuccessStringHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("string", "string"); @@ -48,7 +48,7 @@ public void testSuccessStringHeader() { } @Test - public void testSuccessEnumHeader() { + void testSuccessEnumHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("enum", Cards.A); @@ -60,7 +60,7 @@ public void testSuccessEnumHeader() { } @Test - public void testSuccessNumberHeader() { + void testSuccessNumberHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("number", 1); @@ -72,7 +72,7 @@ public void testSuccessNumberHeader() { } @Test - public void testSuccessBinaryHeader() { + void testSuccessBinaryHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("binary", ByteBuffer.wrap(new byte[0])); @@ -84,7 +84,7 @@ public void testSuccessBinaryHeader() { } @Test - public void testSuccessStringArrayHeader() { + void testSuccessStringArrayHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("stringArray", Arrays.asList("123", 1, new Object(), "456")); @@ -96,7 +96,7 @@ public void testSuccessStringArrayHeader() { } @Test - public void testFailUnsupportedHeader() { + void testFailUnsupportedHeader() { final Map messageHeaders = new HashMap<>(); messageHeaders.put("unsupported", new Object()); diff --git a/pom.xml b/pom.xml index 3725248..ef52f67 100644 --- a/pom.xml +++ b/pom.xml @@ -1,19 +1,44 @@ - - + + 4.0.0 - + com.github.mvallim amazon-sns-java-messaging-lib 1.0.4-SNAPSHOT pom - + amazon-sns-java-messaging-lib - + - 1.8 + 8 + + UTF-8 UTF-8 UTF-8 - 1.18.26 + UTF-8 + + UTF-8 + ${java.version} + ${java.version} + + 1.18.24 + 1.3.14 + 4.11.0 + 5.10.2 + 2.15.2 + + 3.2.0 + 3.10.1 + 3.0.0 + 3.1.0 + 2.5.3 + 3.3.0 + 3.2.1 + 2.22.2 + 0.8.8 + **/amazon-sns-java-messaging-lib-template/**, **/package-info.**, @@ -23,22 +48,28 @@ + + amazon-sns-java-messaging-lib-template + amazon-sns-java-messaging-lib-v1 + amazon-sns-java-messaging-lib-v2 + + scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib HEAD - + Request Batch combine multiple requests to optimally utilise the network. https://github.com/mvallim/amazon-sns-java-messaging-lib 2022 - + com.github.mvallim https://github.com/mvallim - + Marcos Tischer Vallim @@ -46,7 +77,7 @@ -3 - + Apache 2 @@ -56,142 +87,6 @@ - - - - ${project.basedir} - - NOTICE* - LICENSE* - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.2 - - false - ${jacoco.argLine} -Dfile.encoding=${project.build.sourceEncoding} -Xms1024m -Xmx1024m - - - - - org.jacoco - jacoco-maven-plugin - 0.8.8 - - - **/package-info.** - **/ConsumerHelper.** - **/generated-sources/** - **/generated-test-sources/** - **/test/** - - - - - prepare-agent - - prepare-agent - - - jacoco.argLine - - - - report - verify - - report - - - - - - - org.apache.maven.plugins - maven-clean-plugin - 3.2.0 - true - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - ${java.version} - ${java.version} - ${project.build.sourceEncoding} - true - true - true - true - false - - - org.projectlombok - lombok - ${lombok.version} - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 3.3.0 - - ${project.build.sourceEncoding} - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - true - - - attach-source - - jar - - - - - - - org.apache.maven.plugins - maven-install-plugin - 3.1.0 - true - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.0 - true - - - - org.apache.maven.plugins - maven-release-plugin - - true - false - forked-path - -Dgpg.passphrase=${gpg.passphrase} - - - - - @@ -211,7 +106,7 @@ - + org.slf4j @@ -231,7 +126,7 @@ com.fasterxml.jackson.core jackson-databind - 2.14.0 + ${jackson-databind.version} org.projectlombok @@ -239,12 +134,18 @@ ${lombok.version} provided - - junit - junit - 4.13.1 - test - + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + org.hamcrest hamcrest @@ -253,20 +154,26 @@ org.mockito - mockito-all - 1.10.19 + mockito-junit-jupiter + ${mockito.version} + test + + + org.mockito + mockito-core + ${mockito.version} test ch.qos.logback logback-classic - 1.3.6 + ${logback.version} test ch.qos.logback logback-core - 1.3.6 + ${logback.version} test @@ -277,6 +184,179 @@ + + + + ${project.basedir} + + NOTICE* + LICENSE* + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + ${maven-clean-plugin.version} + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + + org.apache.maven.plugins + maven-install-plugin + ${maven-install-plugin.version} + + + org.apache.maven.plugins + maven-release-plugin + ${maven-release-plugin.version} + + + org.apache.maven.plugins + maven-resources-plugin + ${maven-resources-plugin.version} + + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.jacoco + jacoco-maven-plugin + ${jacoco-maven-plugin.version} + + + + + + + org.apache.maven.plugins + maven-clean-plugin + true + + + org.apache.maven.plugins + maven-deploy-plugin + true + + + org.apache.maven.plugins + maven-install-plugin + true + + + org.apache.maven.plugins + maven-release-plugin + + true + false + forked-path + -Dgpg.passphrase=${gpg.passphrase} + + + + org.apache.maven.plugins + maven-resources-plugin + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-source-plugin + true + + + attach-source + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${jacoco.argLine} -Dfile.encoding=${project.build.sourceEncoding} -Xms1024m -Xmx1024m + + + + org.jacoco + jacoco-maven-plugin + + + XML + CSV + + + **/amazon-sns-java-messaging-lib-template/** + **/package-info.** + **/ConsumerHelper.** + **/generated-sources/** + **/generated-test-sources/** + **/test/** + + + + + prepare-agent + + prepare-agent + + + jacoco.argLine + + + + report + verify + + report + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + true + true + true + true + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + code-ql @@ -387,11 +467,4 @@ - - - amazon-sns-java-messaging-lib-template - amazon-sns-java-messaging-lib-v1 - amazon-sns-java-messaging-lib-v2 - - From 2c15371894094dd11019e3ac90be79cf86226886 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Tue, 20 Feb 2024 20:18:04 -0300 Subject: [PATCH 17/20] chore(refact): improve template --- .../lib/core/AbstractAmazonSnsConsumer.java | 46 ++++++++++++++----- .../lib/core/AbstractAmazonSnsTemplate.java | 4 +- .../messaging/lib/core/AmazonSnsConsumer.java | 30 ++---------- .../messaging/lib/core/AmazonSnsTemplate.java | 6 +-- .../messaging/lib/core/AmazonSnsConsumer.java | 30 ++---------- .../messaging/lib/core/AmazonSnsTemplate.java | 6 +-- 6 files changed, 53 insertions(+), 69 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java index 262f92f..0eb1b94 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsConsumer.java @@ -43,13 +43,15 @@ // @formatter:off //@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -abstract class AbstractAmazonSnsConsumer implements Runnable { +abstract class AbstractAmazonSnsConsumer implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAmazonSnsConsumer.class); private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); - protected final TopicProperty topicProperty; + protected final C amazonSnsClient; + + private final TopicProperty topicProperty; private final ObjectMapper objectMapper; @@ -57,23 +59,17 @@ abstract class AbstractAmazonSnsConsumer implements Runnable { private final BlockingQueue> topicRequests; - protected final ExecutorService executorService; - - protected abstract void publishBatch(final R publishBatchRequest); - - protected abstract void handleError(final R publishBatchRequest, final Throwable throwable); - - protected abstract void handleResponse(final O publishBatchResult); - - protected abstract BiFunction>, R> supplierPublishRequest(); + private final ExecutorService executorService; protected AbstractAmazonSnsConsumer( + final C amazonSnsClient, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests, final ExecutorService executorService) { + this.amazonSnsClient = amazonSnsClient; this.topicProperty = topicProperty; this.objectMapper = objectMapper; this.pendingRequests = pendingRequests; @@ -83,6 +79,34 @@ protected AbstractAmazonSnsConsumer( scheduledExecutorService.scheduleAtFixedRate(this, 0, topicProperty.getLinger(), TimeUnit.MILLISECONDS); } + protected abstract O publish(final R publishBatchRequest); + + protected abstract void handleError(final R publishBatchRequest, final Throwable throwable); + + protected abstract void handleResponse(final O publishBatchResult); + + protected abstract BiFunction>, R> supplierPublishRequest(); + + private void doPublish(final R publishBatchRequest) { + try { + handleResponse(publish(publishBatchRequest)); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + + private void publishBatch(final R publishBatchRequest) { + if (topicProperty.isFifo()) { + doPublish(publishBatchRequest); + } else { + try { + CompletableFuture.runAsync(() -> doPublish(publishBatchRequest), executorService); + } catch (final Exception ex) { + handleError(publishBatchRequest, ex); + } + } + } + @Override @SneakyThrows public void run() { diff --git a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java index 1951ab9..cbc7e66 100644 --- a/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-template/src/main/java/com/amazon/sns/messaging/lib/core/AbstractAmazonSnsTemplate.java @@ -28,11 +28,11 @@ // @formatter:off @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -abstract class AbstractAmazonSnsTemplate { +abstract class AbstractAmazonSnsTemplate { private final AbstractAmazonSnsProducer amazonSnsProducer; - private final AbstractAmazonSnsConsumer amazonSnsConsumer; + private final AbstractAmazonSnsConsumer amazonSnsConsumer; public ListenableFuture send(final RequestEntry requestEntry) { return amazonSnsProducer.send(requestEntry); diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index bb0c497..bfafeea 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.function.BiFunction; @@ -42,44 +41,25 @@ import lombok.SneakyThrows; // @formatter:off -class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); private static final MessageAttributes messageAttributes = new MessageAttributes(); - private final AmazonSNS amazonSNS; - public AmazonSnsConsumer( - final AmazonSNS amazonSNS, + final AmazonSNS amazonSnsClient, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests, final ExecutorService executorService) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, executorService); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } + super(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, executorService); } @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - try { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } + protected PublishBatchResult publish(final PublishBatchRequest publishBatchRequest) { + return amazonSnsClient.publishBatch(publishBatchRequest); } @Override diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index e22f218..7d6f010 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -29,17 +29,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; // @formatter:off -public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { +public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { public AmazonSnsTemplate( - final AmazonSNS amazonSNS, + final AmazonSNS amazonSnsClient, final TopicProperty topicProperty, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { super( new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), - new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) + new AmazonSnsConsumer<>(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) ); } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java index 3fb08fa..b5a82ff 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsConsumer.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.function.BiFunction; @@ -41,44 +40,25 @@ import software.amazon.awssdk.services.sns.model.PublishBatchResponse; // @formatter:off -class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { +class AmazonSnsConsumer extends AbstractAmazonSnsConsumer { private static final Logger LOGGER = LoggerFactory.getLogger(AmazonSnsConsumer.class); private static final MessageAttributes messageAttributes = new MessageAttributes(); - private final SnsClient amazonSNS; - public AmazonSnsConsumer( - final SnsClient amazonSNS, + final SnsClient amazonSnsClient, final TopicProperty topicProperty, final ObjectMapper objectMapper, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests, final ExecutorService executorService) { - super(topicProperty, objectMapper, pendingRequests, topicRequests, executorService); - this.amazonSNS = amazonSNS; - } - - private void publish(final PublishBatchRequest publishBatchRequest) { - try { - handleResponse(amazonSNS.publishBatch(publishBatchRequest)); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } + super(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, executorService); } @Override - protected void publishBatch(final PublishBatchRequest publishBatchRequest) { - if (topicProperty.isFifo()) { - publish(publishBatchRequest); - } else { - try { - CompletableFuture.runAsync(() -> publish(publishBatchRequest), executorService); - } catch (final Exception ex) { - handleError(publishBatchRequest, ex); - } - } + protected PublishBatchResponse publish(final PublishBatchRequest publishBatchRequest) { + return amazonSnsClient.publishBatch(publishBatchRequest); } @Override diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 8a4727b..6ecc32f 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -30,17 +30,17 @@ import software.amazon.awssdk.services.sns.model.PublishBatchResponse; // @formatter:off -public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { +public class AmazonSnsTemplate extends AbstractAmazonSnsTemplate { public AmazonSnsTemplate( - final SnsClient amazonSNS, + final SnsClient amazonSnsClient, final TopicProperty topicProperty, final ConcurrentMap pendingRequests, final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { super( new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), - new AmazonSnsConsumer<>(amazonSNS, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) + new AmazonSnsConsumer<>(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) ); } From 0c1df7df9247d8e7b96c44044fea067dd99b7216 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Tue, 20 Feb 2024 20:33:06 -0300 Subject: [PATCH 18/20] chore(refact): improve producer messages --- .../com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java | 3 ++- .../com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 7d6f010..30cdef0 100644 --- a/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v1/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -19,6 +19,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -38,7 +39,7 @@ public AmazonSnsTemplate( final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { super( - new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), + new AmazonSnsProducer<>(pendingRequests, topicRequests, Executors.newSingleThreadExecutor()), new AmazonSnsConsumer<>(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) ); } diff --git a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java index 6ecc32f..89c50b8 100644 --- a/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java +++ b/amazon-sns-java-messaging-lib-v2/src/main/java/com/amazon/sns/messaging/lib/core/AmazonSnsTemplate.java @@ -19,6 +19,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import com.amazon.sns.messaging.lib.model.RequestEntry; @@ -39,7 +40,7 @@ public AmazonSnsTemplate( final BlockingQueue> topicRequests, final ObjectMapper objectMapper) { super( - new AmazonSnsProducer<>(pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)), + new AmazonSnsProducer<>(pendingRequests, topicRequests, Executors.newSingleThreadExecutor()), new AmazonSnsConsumer<>(amazonSnsClient, topicProperty, objectMapper, pendingRequests, topicRequests, getAmazonSnsThreadPoolExecutor(topicProperty)) ); } From 949a81cfc105d54a62f9c5bfc014ff2357a86257 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Tue, 20 Feb 2024 21:11:04 -0300 Subject: [PATCH 19/20] [maven-release-plugin] prepare release amazon-sns-java-messaging-lib-1.0.4 --- amazon-sns-java-messaging-lib-template/pom.xml | 2 +- amazon-sns-java-messaging-lib-v1/pom.xml | 2 +- amazon-sns-java-messaging-lib-v2/pom.xml | 2 +- pom.xml | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/pom.xml b/amazon-sns-java-messaging-lib-template/pom.xml index dc2a69a..70d7a18 100644 --- a/amazon-sns-java-messaging-lib-template/pom.xml +++ b/amazon-sns-java-messaging-lib-template/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4-SNAPSHOT + 1.0.4 ../pom.xml diff --git a/amazon-sns-java-messaging-lib-v1/pom.xml b/amazon-sns-java-messaging-lib-v1/pom.xml index 8c7fbbb..a10df74 100644 --- a/amazon-sns-java-messaging-lib-v1/pom.xml +++ b/amazon-sns-java-messaging-lib-v1/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4-SNAPSHOT + 1.0.4 ../pom.xml diff --git a/amazon-sns-java-messaging-lib-v2/pom.xml b/amazon-sns-java-messaging-lib-v2/pom.xml index 4e0b790..d23a1a0 100644 --- a/amazon-sns-java-messaging-lib-v2/pom.xml +++ b/amazon-sns-java-messaging-lib-v2/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4-SNAPSHOT + 1.0.4 ../pom.xml diff --git a/pom.xml b/pom.xml index ef52f67..23af931 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,10 @@ - + 4.0.0 com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4-SNAPSHOT + 1.0.4 pom amazon-sns-java-messaging-lib @@ -58,7 +56,7 @@ scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib - HEAD + amazon-sns-java-messaging-lib-1.0.4 Request Batch combine multiple requests to optimally utilise the network. From 180ffbd343fe1f45079562ad6c523119665a0515 Mon Sep 17 00:00:00 2001 From: Marcos Tischer Vallim Date: Tue, 20 Feb 2024 21:11:04 -0300 Subject: [PATCH 20/20] [maven-release-plugin] prepare for next development iteration --- amazon-sns-java-messaging-lib-template/pom.xml | 2 +- amazon-sns-java-messaging-lib-v1/pom.xml | 2 +- amazon-sns-java-messaging-lib-v2/pom.xml | 2 +- pom.xml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/amazon-sns-java-messaging-lib-template/pom.xml b/amazon-sns-java-messaging-lib-template/pom.xml index 70d7a18..66028da 100644 --- a/amazon-sns-java-messaging-lib-template/pom.xml +++ b/amazon-sns-java-messaging-lib-template/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4 + 1.0.5-SNAPSHOT ../pom.xml diff --git a/amazon-sns-java-messaging-lib-v1/pom.xml b/amazon-sns-java-messaging-lib-v1/pom.xml index a10df74..82e6777 100644 --- a/amazon-sns-java-messaging-lib-v1/pom.xml +++ b/amazon-sns-java-messaging-lib-v1/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4 + 1.0.5-SNAPSHOT ../pom.xml diff --git a/amazon-sns-java-messaging-lib-v2/pom.xml b/amazon-sns-java-messaging-lib-v2/pom.xml index d23a1a0..96bcac1 100644 --- a/amazon-sns-java-messaging-lib-v2/pom.xml +++ b/amazon-sns-java-messaging-lib-v2/pom.xml @@ -5,7 +5,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4 + 1.0.5-SNAPSHOT ../pom.xml diff --git a/pom.xml b/pom.xml index 23af931..9c92832 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.github.mvallim amazon-sns-java-messaging-lib - 1.0.4 + 1.0.5-SNAPSHOT pom amazon-sns-java-messaging-lib @@ -56,7 +56,7 @@ scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib scm:git:git@github.com:mvallim/amazon-sns-java-messaging-lib - amazon-sns-java-messaging-lib-1.0.4 + HEAD Request Batch combine multiple requests to optimally utilise the network.