Skip to content

The search box in the website knows all the secrets—try it!

For any queries, join our Discord Channel to reach us faster.

JasperFx Logo

JasperFx provides formal support for Wolverine and other JasperFx libraries. Please check our Support Plans for more details.

Using Amazon SQS

Wolverine supports Amazon SQS as a messaging transport through the WolverineFx.AmazonSqs package.

Connecting to the Broker

First, if you are using the shared AWS config and credentials files, the SQS connection is just this:

cs
var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        // This does depend on the server having an AWS credentials file
        // See https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html for more information
        opts.UseAmazonSqsTransport()

            // Let Wolverine create missing queues as necessary
            .AutoProvision()

            // Optionally purge all queues on application startup.
            // Warning though, this is potentially slow
            .AutoPurgeOnStartup();
    }).StartAsync();

snippet source | anchor

cs
var builder = Host.CreateApplicationBuilder();
builder.UseWolverine(opts =>
{
    var config = builder.Configuration;

    opts.UseAmazonSqsTransport(sqsConfig =>
        {
            sqsConfig.ServiceURL = config["AwsUrl"];
            // And any other elements of the SQS AmazonSQSConfig
            // that you may need to configure
        })

        // Let Wolverine create missing queues as necessary
        .AutoProvision()

        // Optionally purge all queues on application startup.
        // Warning though, this is potentially slow
        .AutoPurgeOnStartup();
});

using var host = builder.Build();
await host.StartAsync();

snippet source | anchor

If you'd just like to connect to Amazon SQS running from within LocalStack on your development box, there's this helper:

cs
var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        // Connect to an SQS broker running locally
        // through LocalStack
        opts.UseAmazonSqsTransportLocally();
    }).StartAsync();

snippet source | anchor

And lastly, if you want to explicitly supply an access and secret key for your credentials to SQS, you can use this syntax:

cs
var builder = Host.CreateApplicationBuilder();
builder.UseWolverine(opts =>
{
    var config = builder.Configuration;

    opts.UseAmazonSqsTransport(sqsConfig =>
        {
            sqsConfig.ServiceURL = config["AwsUrl"];
            // And any other elements of the SQS AmazonSQSConfig
            // that you may need to configure
        })

        // And you can also add explicit AWS credentials
        .Credentials(new BasicAWSCredentials(config["AwsAccessKey"], config["AwsSecretKey"]))

        // Let Wolverine create missing queues as necessary
        .AutoProvision()

        // Optionally purge all queues on application startup.
        // Warning though, this is potentially slow
        .AutoPurgeOnStartup();
});

using var host = builder.Build();
await host.StartAsync();

snippet source | anchor

Connecting to Multiple Brokers 4.7

Wolverine supports interacting with multiple Amazon SQS brokers within one application like this:

cs
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        opts.UseAmazonSqsTransport(config =>
        {
            // Add configuration for connectivity
        });
        
        opts.AddNamedAmazonSqsBroker(new BrokerName("americas"), config =>
        {
            // Add configuration for connectivity
        });
        
        opts.AddNamedAmazonSqsBroker(new BrokerName("emea"), config =>
        {
            // Add configuration for connectivity
        });

        // Or explicitly make subscription rules
        opts.PublishMessage<SenderConfigurationTests.ColorMessage>()
            .ToSqsQueueOnNamedBroker(new BrokerName("emea"), "colors");

        // Listen to topics
        opts.ListenToSqsQueueOnNamedBroker(new BrokerName("americas"), "red");
        // Other configuration
    }).StartAsync();

snippet source | anchor

Note that the Uri scheme within Wolverine for any endpoints from a "named" Amazon SQS broker is the name that you supply for the broker. So in the example above, you might see Uri values for emea://colors or americas://red.

Identifier Prefixing for Shared Brokers

When sharing a single AWS account or SQS namespace between multiple developers or development environments, you can use PrefixIdentifiers() to automatically prepend a prefix to every queue name created by Wolverine. This helps isolate cloud resources for each developer or environment:

csharp
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        opts.UseAmazonSqsTransport()
            .AutoProvision()

            // Prefix all queue names with "dev-john-"
            .PrefixIdentifiers("dev-john");

        // A queue named "orders" becomes "dev-john-orders"
        opts.ListenToSqsQueue("orders");
    }).StartAsync();

You can also use PrefixIdentifiersWithMachineName() as a convenience to use the current machine name as the prefix:

csharp
opts.UseAmazonSqsTransport()
    .AutoProvision()
    .PrefixIdentifiersWithMachineName();

The default delimiter between the prefix and the original name is - for Amazon SQS (e.g., dev-john-orders).

Request/Reply 5.14

Request/reply mechanics (IMessageBus.InvokeAsync<T>()) are supported with the Amazon SQS transport when system queues are enabled. Wolverine creates a dedicated per-node response queue named like wolverine-response-[service name]-[node id] that is used to receive replies.

To enable request/reply support, call EnableSystemQueues() on the SQS transport configuration:

csharp
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        opts.UseAmazonSqsTransport()
            .AutoProvision()

            // Enable system queues for request/reply support
            .EnableSystemQueues();
    }).StartAsync();

TIP

Unlike Azure Service Bus and RabbitMQ where system queues are enabled by default, SQS system queues require explicit opt-in via EnableSystemQueues(). This is because creating SQS queues requires IAM permissions that your application may not have.

System queues are automatically cleaned up when your application shuts down. Wolverine also tags each system queue with a wolverine:last-active timestamp and runs a background keep-alive timer. On startup, Wolverine scans for orphaned system queues (from crashed nodes) with the wolverine-response- or wolverine-control- prefix and deletes any that have been inactive for more than 5 minutes.

Wolverine Control Queues 5.14

You can opt into using SQS queues for intra-node communication that Wolverine needs for leader election and background worker distribution. Using SQS for this feature is more efficient than the built-in database control queues that Wolverine uses otherwise, and is necessary for message storage options like RavenDb that do not have a built-in control queue mechanism.

csharp
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        opts.UseAmazonSqsTransport()
            .AutoProvision()

            // This enables Wolverine to use SQS queues
            // created at runtime for communication between
            // Wolverine nodes
            .EnableWolverineControlQueues();
    }).StartAsync();

Calling EnableWolverineControlQueues() implicitly enables system queues and request/reply support as well.

Disabling System Queues 5.14

If your application does not have IAM permissions to create or delete queues, you can explicitly disable system queues:

csharp
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        opts.UseAmazonSqsTransport()
            .AutoProvision()
            .SystemQueuesAreEnabled(false);

        opts.ListenToSqsQueue("send-and-receive");
        opts.PublishAllMessages().ToSqsQueue("send-and-receive");
    }).StartAsync();

Released under the MIT License.