All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.otto.synapse.endpoint.SqsClientHelper Maven / Gradle / Ivy

There is a newer version: 0.33.1
Show newest version
package de.otto.synapse.endpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
import software.amazon.awssdk.services.sqs.model.*;

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static de.otto.synapse.endpoint.sender.sqs.SqsMessageSender.MSG_KEY_ATTR;
import static java.time.Instant.now;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonMap;
import static java.util.stream.Collectors.toList;

/**
 * A helper used to write tests for SQS senders or publishers. Not really recommended for production code.
 */
public class SqsClientHelper {

    private static final Logger LOG = LoggerFactory.getLogger(SqsClientHelper.class);

    private final SqsAsyncClient sqsAsyncClient;

    public SqsClientHelper(final SqsAsyncClient sqsAsyncClient) {
        this.sqsAsyncClient = sqsAsyncClient;
        waitForSqsToBeReady();
    }

    public boolean doesChannelExist(final String channelName) {
        try {
            final URL queueUrl = getQueueUrl(channelName);
            return getQueueUrls().contains(queueUrl);
        } catch (final RuntimeException e) {
            return false;
        }
    }

    public boolean doesChannelExist(final URL channelUrl) {
        try {
            return getQueueUrls().contains(channelUrl);
        } catch (final RuntimeException e) {
            return false;
        }
    }

    public List getQueueUrls() {
        try {
            final ListQueuesResponse queuesResponse = sqsAsyncClient.listQueues().get();
            return queuesResponse.queueUrls().stream().map(this::toUrl).collect(toList());
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public URL getQueueUrl(final String channelName) {
        try {
            return toUrl(sqsAsyncClient
                    .getQueueUrl(GetQueueUrlRequest.builder().queueName(channelName).build())
                    .get()
                    .queueUrl());
        } catch (InterruptedException | ExecutionException e) {
            LOG.error("Error fetching queueUrl for SQS channel " + channelName + ": " + e.getMessage(), e);
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void createChannelIfNotExists(final String channelName) {
        try {
            if (!doesChannelExist(channelName)) {
                sqsAsyncClient
                        .createQueue(CreateQueueRequest.builder()
                                .queueName(channelName)
                                .build()).get();
            }
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void purgeQueue(final String channelName) {
        try {
            if (doesChannelExist(channelName)) {
                final URL channelUrl = getQueueUrl(channelName);
                sqsAsyncClient.purgeQueue(PurgeQueueRequest
                        .builder()
                        .queueUrl(channelUrl.toString())
                        .build())
                        .get();
            }
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void purgeQueue(final URL channelUrl) {
        try {
            if (doesChannelExist(channelUrl)) {
                sqsAsyncClient.purgeQueue(PurgeQueueRequest
                        .builder()
                        .queueUrl(channelUrl.toString())
                        .build())
                        .get();
            }
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public List receiveMessages(final String channelName,
                                         final int seconds) {
        final Instant started = now();
        List messages;
        boolean abort;
        do {
            messages = receiveMessages(channelName);
            abort = Duration.between(started, now()).getSeconds() > seconds;
        } while (messages.isEmpty() && !abort);
        return messages;
    }

    public List receiveMessages(final URL channelUrl,
                                         final int seconds) {
        final Instant started = now();
        List messages;
        boolean abort;
        do {
            messages = receiveMessages(channelUrl);
            abort = Duration.between(started, now()).getSeconds() > seconds;
        } while (messages.isEmpty() && !abort);
        return messages;
    }

    public List receiveMessages(final String queueName) {
        final URL channelUrl = getQueueUrl(queueName);
        return receiveMessages(channelUrl);
    }

    public List receiveMessages(final URL channelUrl) {
        try {
            final ReceiveMessageResponse response = sqsAsyncClient
                    .receiveMessage(ReceiveMessageRequest.builder()
                            .waitTimeSeconds(1)
                            .queueUrl(channelUrl.toString())
                            .build())
                    .get();
            if (response.messages() != null) {
                final List messages = response.messages();
                messages.forEach(message -> {
                    acknowledge(message.receiptHandle());
                });
                return messages;
            } else {
                return emptyList();
            }
        } catch (final Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void sendMessage(final String channelName, final String key, final String payload) {
            final URL channelUrl = getQueueUrl(channelName);
            sendMessage(channelUrl, key, payload);
        try {
            final SendMessageResponse response = sqsAsyncClient.sendMessage(SendMessageRequest.builder()
                    .queueUrl(channelUrl.toString())
                    .messageAttributes(
                            singletonMap(MSG_KEY_ATTR, MessageAttributeValue.builder().dataType("String").stringValue(key).build()))
                    .messageBody(payload)
                    .build()
            ).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void sendMessage(final URL channelUrl, final String key, final String payload) {
        try {
            final SendMessageResponse response = sqsAsyncClient.sendMessage(SendMessageRequest.builder()
                    .queueUrl(channelUrl.toString())
                    .messageAttributes(
                            singletonMap(MSG_KEY_ATTR, MessageAttributeValue.builder().dataType("String").stringValue(key).build()))
                    .messageBody(payload)
                    .build()
            ).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public CompletableFuture acknowledge(final String receiptHandle) {
        return sqsAsyncClient.deleteMessage(DeleteMessageRequest
                .builder()
                .receiptHandle(receiptHandle)
                .build());
    }

    public URL toUrl(final String url) {
        try {
            return new URL(url);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void waitForSqsToBeReady() {
        while (true) {

            try {
                LOG.info("Waiting for SQS to be available");
                CompletableFuture queues = sqsAsyncClient.listQueues();
                LOG.info("Following queues are present: " + queues.get().queueUrls());
                break;
            } catch (final Exception ignored) {
                try {
                    Thread.sleep(500);
                } catch (final InterruptedException e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
            }
        }
        LOG.info("SQS is available");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy