Skip to content

Suggestion: Make .NET "Strategy #2: Publishing Messages in Batches" example DRYer #548

@jehrenzweig-captionhealth

Description

Is your feature request related to a problem? Please describe.

The "Strategy #⁠2: Publishing Messages in Batches" .NET code example could be made a bit clearer, as it currently duplicates the following code:

foreach (ValueTask pt in publishTasks)
{
   try
   {
	   await pt;
   }
   catch (Exception ex)
   {
	   Console.Error.WriteLine($"{DateTime.Now} [ERROR] saw nack or return, ex: '{ex}'");
   }
}
publishTasks.Clear();
outstandingMessageCount = 0;
Current Strategy #2: Publishing Messages in Batches code example
var publishTasks = new List<ValueTask>();
for (int i = 0; i < MESSAGE_COUNT; i++)
{
    byte[] body = Encoding.UTF8.GetBytes(i.ToString());
    publishTasks.Add(channel.BasicPublishAsync(exchange: string.Empty, routingKey: queueName, body: body, mandatory: true, basicProperties: props));
    outstandingMessageCount++;

    if (outstandingMessageCount == batchSize)
    {
        foreach (ValueTask pt in publishTasks)
        {
            try
            {
                   await pt;
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"{DateTime.Now} [ERROR] saw nack or return, ex: '{ex}'");
            }
        }
        publishTasks.Clear();
        outstandingMessageCount = 0;
    }
}

if (publishTasks.Count > 0)
{
    foreach (ValueTask pt in publishTasks)
    {
        try
        {
            await pt;
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine($"{DateTime.Now} [ERROR] saw nack or return, ex: '{ex}'");
        }
    }
    publishTasks.Clear();
    outstandingMessageCount = 0;
}

Describe the solution you'd like

Refactor the code example in the docs, as well as the /dotnet/PublisherConfirms/PublisherConfirms.cs file it derives from, to eliminate duplicated code & make it easier for novices (like myself) to understand at first glance.

Proposed "Strategy #2: Publishing Messages in Batches" .NET code example (after refactoring):

var publishTasks = new List<ValueTask>();
for (int i = 0; i < MESSAGE_COUNT; i++)
{
    byte[] body = Encoding.UTF8.GetBytes(i.ToString());
    publishTasks.Add(channel.BasicPublishAsync(exchange: string.Empty, routingKey: queueName, body: body, mandatory: true, basicProperties: props));
    outstandingMessageCount++;

    if (outstandingMessageCount == batchSize || i == MESSAGE_COUNT-1)
    {
       if (publishTasks.Count > 0)
       {
           foreach (ValueTask pt in publishTasks)
           {
               try
               {
                   await pt;
               }
               catch (Exception ex)
               {
                   Console.Error.WriteLine($"{DateTime.Now} [ERROR] saw nack or return, ex: '{ex}'");
               }
           }
           publishTasks.Clear();
           outstandingMessageCount = 0;
       }
    }
}

sw.Stop();
Console.WriteLine($"{DateTime.Now} [INFO] published {MESSAGE_COUNT:N0} messages in batch in {sw.ElapsedMilliseconds:N0} ms");
Proposed /dotnet/PublisherConfirms/PublisherConfirms.cs code (after refactoring)
async Task PublishMessagesInBatchAsync()
{
    Console.WriteLine($"{DateTime.Now} [INFO] publishing {MESSAGE_COUNT:N0} messages and handling confirms in batches");

    await using IConnection connection = await CreateConnectionAsync();
    await using IChannel channel = await connection.CreateChannelAsync(channelOpts);

    // declare a server-named queue
    QueueDeclareOk queueDeclareResult = await channel.QueueDeclareAsync();
    string queueName = queueDeclareResult.QueueName;

    int batchSize = MAX_OUTSTANDING_CONFIRMS / 2;
    int outstandingMessageCount = 0;

    var sw = new Stopwatch();
    sw.Start();

    var publishTasks = new List<ValueTask>();
    for (int i = 0; i < MESSAGE_COUNT; i++)
    {
        byte[] body = Encoding.UTF8.GetBytes(i.ToString());
        publishTasks.Add(channel.BasicPublishAsync(exchange: string.Empty, routingKey: queueName, body: body, mandatory: true, basicProperties: props));
        outstandingMessageCount++;

        if (outstandingMessageCount == batchSize || i == MESSAGE_COUNT-1)
        {
           if (publishTasks.Count > 0)
           {
               foreach (ValueTask pt in publishTasks)
               {
                   try
                   {
                       await pt;
                   }
                   catch (Exception ex)
                   {
                       Console.Error.WriteLine($"{DateTime.Now} [ERROR] saw nack or return, ex: '{ex}'");
                   }
               }
               publishTasks.Clear();
               outstandingMessageCount = 0;
           }
        }
    }

    sw.Stop();
    Console.WriteLine($"{DateTime.Now} [INFO] published {MESSAGE_COUNT:N0} messages in batch in {sw.ElapsedMilliseconds:N0} ms");
}

Describe alternatives you've considered

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions