Documentation

Claim-Check messaging through AMQP broker like RabbitMQ

Store message data in a persistent store and pass a Claim Check to subsequent components. These components can use the Claim Check to retrieve the stored information. It is mostly use to pass big files around.

The Claim Check pattern is used to efficiently handle large data transfers between components. Instead of passing large files or messages directly, the sender stores the data in a persistent storage (e.g., a database, cloud storage, or file system). A small lightweight token or reference (the “Claim Check”) is then passed to subsequent components in the workflow. These components use the Claim Check to retrieve the stored data when needed. This approach improves system performance and reduces memory usage by avoiding the direct transfer of large payloads, making it particularly useful in distributed systems, queues, and integration scenarios.

Pattern page: https://www.enterpriseintegrationpatterns.com/patterns/messaging/StoreInLibrary.html

To save and retrieve a file from the storage service, you need to register one of the file storage providers.

1. Register claim-check sender

Here is a basic broker configuration:

{
  "BrokerConfiguration": {
    "HostName": "localhost",
    "Port": 5672,
    "UserName": "guest",
    "Password": "guest"
  },
  ...
}

Get broker configuration:

var brokerConfiguration = Configuration
    .GetSection("Nomirun.Module:Nomirun.Demo.Module:BrokerConfiguration")
    .Get<BrokerConfiguration>();

Register file storage provider you want to use, for example:

services.AddSingleton(resolver => new AzureStorageOptions()
{
   ConnectionString = Configuration.GetValue<string>($"Nomirun.Module:Nomirun.Demo.Module:Storage:AzureStorage:ConnectionString")
});

services.AddTransient<IStorageService<FileObject>, AzureStorageService>();

File storage service will be used by claim-check to save and retrieve the file.

Next, register claim-check sender that will upload a file to Azure storage and send the internal ClaimCheck message to the broker.

services.AddAmqpClaimCheckSender<AzureStorageService>(
    brokerConfiguration,
    options =>
    {
        options.RoutingKey = null;
        options.Queue = "claim_queue";
        options.Exchange = "claim_exchange";
        options.ExchangeType = "fanout";
    });

2. Register claim-check receiver

On the other end, you need to repeat the configuration.

{
  "BrokerConfiguration": {
    "HostName": "localhost",
    "Port": 5672,
    "UserName": "guest",
    "Password": "guest"
  },
  ...
}

Get broker configuration:

var brokerConfiguration = Configuration
    .GetSection("Nomirun.Module:Nomirun.Demo.Module:BrokerConfiguration")
    .Get<BrokerConfiguration>();

Register file storage provider you want to use, for example:

services.AddSingleton(resolver => new AzureStorageOptions()
{
   ConnectionString = Configuration.GetValue<string>($"Nomirun.Module:Nomirun.Demo.Module:Storage:AzureStorage:ConnectionString")
});

services.AddTransient<IStorageService<FileObject>, AzureStorageService>();

Register claim check receiver in another service or application. It will fetch the NewFileImport message from the broker and download the file from Azure Storage service

services.AddAmqpClaimCheckReceiver<AzureStorageService, MyClaimConsumer>(
    brokerConfiguration,
    options =>
    {
        options.RoutingKey = null;
        options.Queue = "claim_queue";
        options.Exchange = "claim_exchange";
        options.ExchangeType = "fanout";
        options.AutoAck = false;
    });

Create the consumer that implements IConsumeFileClaim to process the file:

public class MyClaimConsumer: IConsumeFileClaim
{
    private readonly ILogger<MyClaimConsumer> _logger;

    public MyClaimConsumer(ILogger<MyClaimConsumer> logger)
    {
        _logger = logger;
    }

    public  async Task ConsumeMessage(FileClaim message, BasicDeliverEventArgs eventArgs)
    {
        _logger.LogInformation($"Consumed file claim in the consumer: {message.FileName}, Correlation ID: {eventArgs.BasicProperties.CorrelationId}");

        await Task.CompletedTask;
    }
}