1
0
mirror of synced 2024-11-05 02:59:16 +00:00

Fixed "Index out of range" when publishing from multiple thread (or from a message handler with prefetchcount > 1)

This commit is contained in:
Mark van Renswoude 2019-05-20 15:22:40 +02:00
parent 4c08e9b684
commit 0bd9d06795

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -37,6 +38,9 @@ namespace Tapeti.Connection
private IModel channelInstance;
private ulong lastDeliveryTag;
private DateTime connectedDateTime;
// These fields must be locked, since the callbacks for BasicAck/BasicReturn can run in a different thread
private readonly object confirmLock = new Object();
private readonly Dictionary<ulong, ConfirmMessageInfo> confirmMessages = new Dictionary<ulong, ConfirmMessageInfo>();
private readonly Dictionary<string, ReturnInfo> returnRoutingKeys = new Dictionary<string, ReturnInfo>();
@ -208,6 +212,9 @@ namespace Tapeti.Connection
async (handler, next) => await handler.Handle(context, next),
() => taskQueue.Value.Add(async () =>
{
if (Thread.CurrentThread.ManagedThreadId != 3)
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
var body = messageSerializer.Serialize(context.Message, context.Properties);
Task<int> publishResultTask = null;
@ -225,7 +232,16 @@ namespace Tapeti.Connection
{
lastDeliveryTag++;
Monitor.Enter(confirmLock);
try
{
confirmMessages.Add(lastDeliveryTag, messageInfo);
}
finally
{
Monitor.Exit(confirmLock);
}
publishResultTask = messageInfo.CompletionSource.Task;
}
else
@ -326,7 +342,17 @@ namespace Tapeti.Connection
if (config.UsePublisherConfirms)
{
lastDeliveryTag = 0;
Monitor.Enter(confirmLock);
try
{
confirmMessages.Clear();
}
finally
{
Monitor.Exit(confirmLock);
}
channelInstance.ConfirmSelect();
}
@ -402,6 +428,9 @@ namespace Tapeti.Connection
private void HandleBasicAck(object sender, BasicAckEventArgs e)
{
Monitor.Enter(confirmLock);
try
{
foreach (var deliveryTag in GetDeliveryTags(e))
{
@ -421,9 +450,17 @@ namespace Tapeti.Connection
confirmMessages.Remove(deliveryTag);
}
}
finally
{
Monitor.Exit(confirmLock);
}
}
private void HandleBasicNack(object sender, BasicNackEventArgs e)
{
Monitor.Enter(confirmLock);
try
{
foreach (var deliveryTag in GetDeliveryTags(e))
{
@ -434,6 +471,11 @@ namespace Tapeti.Connection
confirmMessages.Remove(e.DeliveryTag);
}
}
finally
{
Monitor.Exit(confirmLock);
}
}
private IEnumerable<ulong> GetDeliveryTags(BasicAckEventArgs e)