From 4dd22c743372a44cec3631cb55b1b71a661299c4 Mon Sep 17 00:00:00 2001 From: martincostello Date: Thu, 20 Jun 2019 17:30:22 +0100 Subject: [PATCH 01/10] Remove commented-out code Remove leftover code from previous refactors. --- ...WhenExactlyOnceIsAppliedToHandlerWithoutExplicitTimeout.cs | 1 - JustSaying/Messaging/MessageHandling/ExactlyOnceAttribute.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/JustSaying.UnitTests/AwsTools/MessageHandling/SqsNotificationListener/WhenExactlyOnceIsAppliedToHandlerWithoutExplicitTimeout.cs b/JustSaying.UnitTests/AwsTools/MessageHandling/SqsNotificationListener/WhenExactlyOnceIsAppliedToHandlerWithoutExplicitTimeout.cs index 1bcf58c32..633cb46aa 100644 --- a/JustSaying.UnitTests/AwsTools/MessageHandling/SqsNotificationListener/WhenExactlyOnceIsAppliedToHandlerWithoutExplicitTimeout.cs +++ b/JustSaying.UnitTests/AwsTools/MessageHandling/SqsNotificationListener/WhenExactlyOnceIsAppliedToHandlerWithoutExplicitTimeout.cs @@ -12,7 +12,6 @@ namespace JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener { public class WhenExactlyOnceIsAppliedWithoutSpecificTimeout : BaseQueuePollingTest { - //private readonly int _maximumTimeout = int.MaxValue; private readonly int _maximumTimeout = (int)TimeSpan.MaxValue.TotalSeconds; private readonly TaskCompletionSource _tcs = new TaskCompletionSource(); private ExactlyOnceSignallingHandler _handler; diff --git a/JustSaying/Messaging/MessageHandling/ExactlyOnceAttribute.cs b/JustSaying/Messaging/MessageHandling/ExactlyOnceAttribute.cs index 5fecc729d..452a751b6 100644 --- a/JustSaying/Messaging/MessageHandling/ExactlyOnceAttribute.cs +++ b/JustSaying/Messaging/MessageHandling/ExactlyOnceAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace JustSaying.Messaging.MessageHandling { @@ -7,9 +7,9 @@ public class ExactlyOnceAttribute : Attribute { public ExactlyOnceAttribute() { - //TimeOut = int.MaxValue; TimeOut = (int)TimeSpan.MaxValue.TotalSeconds; } + public int TimeOut { get; set; } } } From f0b70bfd4286ffc4219acae6563c4596606c276a Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 29 Jun 2019 14:43:50 +0100 Subject: [PATCH 02/10] Try and fix integration test Try and fix integration tests failing if tasks transition so they're already completed. --- JustSaying.IntegrationTests/Fluent/IntegrationTestBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JustSaying.IntegrationTests/Fluent/IntegrationTestBase.cs b/JustSaying.IntegrationTests/Fluent/IntegrationTestBase.cs index f5375f1f3..e3613a6cd 100644 --- a/JustSaying.IntegrationTests/Fluent/IntegrationTestBase.cs +++ b/JustSaying.IntegrationTests/Fluent/IntegrationTestBase.cs @@ -79,7 +79,7 @@ protected IHandlerAsync CreateHandler(TaskCompletionSource complet handler.Handle(Arg.Any()) .Returns(true) - .AndDoes((_) => completionSource.SetResult(null)); + .AndDoes((_) => completionSource.TrySetResult(null)); return handler; } From 48c0bb67ffd4fc728b953a8df022faaa57884826 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sat, 29 Jun 2019 14:59:27 +0100 Subject: [PATCH 03/10] Update NuGet packages Update various NuGet pacakges to their latest versions. --- Directory.Build.props | 4 ++-- .../JustSaying.IntegrationTests.csproj | 8 ++++---- .../JustSaying.TestingFramework.csproj | 2 +- JustSaying.UnitTests/JustSaying.UnitTests.csproj | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index f5cf2592f..439835264 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,9 +5,9 @@ - + - + diff --git a/JustSaying.IntegrationTests/JustSaying.IntegrationTests.csproj b/JustSaying.IntegrationTests/JustSaying.IntegrationTests.csproj index d150e7392..b7fe34e94 100644 --- a/JustSaying.IntegrationTests/JustSaying.IntegrationTests.csproj +++ b/JustSaying.IntegrationTests/JustSaying.IntegrationTests.csproj @@ -12,11 +12,11 @@ - - - + + + - + diff --git a/JustSaying.TestingFramework/JustSaying.TestingFramework.csproj b/JustSaying.TestingFramework/JustSaying.TestingFramework.csproj index b21fd0c85..5f19a91bf 100644 --- a/JustSaying.TestingFramework/JustSaying.TestingFramework.csproj +++ b/JustSaying.TestingFramework/JustSaying.TestingFramework.csproj @@ -8,7 +8,7 @@ - + diff --git a/JustSaying.UnitTests/JustSaying.UnitTests.csproj b/JustSaying.UnitTests/JustSaying.UnitTests.csproj index 69a3a5c7f..f75e269d7 100644 --- a/JustSaying.UnitTests/JustSaying.UnitTests.csproj +++ b/JustSaying.UnitTests/JustSaying.UnitTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.2 @@ -12,10 +12,10 @@ - - - - + + + + From 8618000cfd74b6a4b349456a8fdcd4144db9d8de Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:37:47 +0100 Subject: [PATCH 04/10] Refactor ExactlyOnceHandler Change timeout constructor parameter to a TimeSpan. This makes the unit clearer and removes the need to create a new TimeSpan for every message invocation. Compute the message lock key suffix once, rather than per message invocation, as it does not change for the lifetime of the handler. --- ...EnsuringMessageIsOnlyHandledExactlyOnce.cs | 2 +- .../MessageHandling/MessageHandlerWrapper.cs | 4 +++- .../MessageHandling/ExactlyOnceHandler.cs | 21 +++++++++++-------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/JustSaying.UnitTests/Messaging/MessageHandling/WhenEnsuringMessageIsOnlyHandledExactlyOnce.cs b/JustSaying.UnitTests/Messaging/MessageHandling/WhenEnsuringMessageIsOnlyHandledExactlyOnce.cs index eb8c99b1f..a6ff81c5b 100644 --- a/JustSaying.UnitTests/Messaging/MessageHandling/WhenEnsuringMessageIsOnlyHandledExactlyOnce.cs +++ b/JustSaying.UnitTests/Messaging/MessageHandling/WhenEnsuringMessageIsOnlyHandledExactlyOnce.cs @@ -15,7 +15,7 @@ public async Task WhenMessageIsLockedByAnotherHandler_MessageWillBeLeftInTheQueu { var messageLock = Substitute.For(); messageLock.TryAquireLockAsync(Arg.Any(), Arg.Any()).Returns(new MessageLockResponse { DoIHaveExclusiveLock = false }); - var sut = new ExactlyOnceHandler(Substitute.For>(), messageLock, 1, "handlerName"); + var sut = new ExactlyOnceHandler(Substitute.For>(), messageLock, TimeSpan.FromSeconds(1), "handlerName"); var result = await sut.Handle(new OrderAccepted()); diff --git a/JustSaying/AwsTools/MessageHandling/MessageHandlerWrapper.cs b/JustSaying/AwsTools/MessageHandling/MessageHandlerWrapper.cs index 45ed10d37..d02f56eb0 100644 --- a/JustSaying/AwsTools/MessageHandling/MessageHandlerWrapper.cs +++ b/JustSaying/AwsTools/MessageHandling/MessageHandlerWrapper.cs @@ -44,7 +44,9 @@ private IHandlerAsync MaybeWrapWithExactlyOnce(IHandlerAsync handler) w } var handlerName = handlerType.FullName.ToLowerInvariant(); - return new ExactlyOnceHandler(handler, _messageLock, exactlyOnceMetadata.GetTimeOut(), handlerName); + var timeout = TimeSpan.FromSeconds(exactlyOnceMetadata.GetTimeOut()); + + return new ExactlyOnceHandler(handler, _messageLock, timeout, handlerName); } private IHandlerAsync MaybeWrapWithStopwatch(IHandlerAsync handler) where T : Message diff --git a/JustSaying/Messaging/MessageHandling/ExactlyOnceHandler.cs b/JustSaying/Messaging/MessageHandling/ExactlyOnceHandler.cs index 0664ba73b..6125414e6 100644 --- a/JustSaying/Messaging/MessageHandling/ExactlyOnceHandler.cs +++ b/JustSaying/Messaging/MessageHandling/ExactlyOnceHandler.cs @@ -8,15 +8,15 @@ public class ExactlyOnceHandler : IHandlerAsync where T : Message { private readonly IHandlerAsync _inner; private readonly IMessageLockAsync _messageLock; - private readonly int _timeOut; - private readonly string _handlerName; + private readonly TimeSpan _timeout; + private readonly string _lockSuffixKeyForHandler; - public ExactlyOnceHandler(IHandlerAsync inner, IMessageLockAsync messageLock, int timeOut, string handlerName) + public ExactlyOnceHandler(IHandlerAsync inner, IMessageLockAsync messageLock, TimeSpan timeout, string handlerName) { _inner = inner; _messageLock = messageLock; - _timeOut = timeOut; - _handlerName = handlerName; + _timeout = timeout; + _lockSuffixKeyForHandler = $"{typeof(T).ToString().ToLowerInvariant()}-{handlerName}"; } private const bool RemoveTheMessageFromTheQueue = true; @@ -24,8 +24,9 @@ public ExactlyOnceHandler(IHandlerAsync inner, IMessageLockAsync messageLock, public async Task Handle(T message) { - var lockKey = $"{message.UniqueKey()}-{typeof(T).ToString().ToLowerInvariant()}-{_handlerName}"; - var lockResponse = await _messageLock.TryAquireLockAsync(lockKey, TimeSpan.FromSeconds(_timeOut)).ConfigureAwait(false); + string lockKey = $"{message.UniqueKey()}-{_lockSuffixKeyForHandler}"; + MessageLockResponse lockResponse = await _messageLock.TryAquireLockAsync(lockKey, _timeout).ConfigureAwait(false); + if (!lockResponse.DoIHaveExclusiveLock) { if (lockResponse.IsMessagePermanentlyLocked) @@ -38,14 +39,16 @@ public async Task Handle(T message) try { - var successfullyHandled = await _inner.Handle(message).ConfigureAwait(false); + bool successfullyHandled = await _inner.Handle(message).ConfigureAwait(false); + if (successfullyHandled) { await _messageLock.TryAquireLockPermanentlyAsync(lockKey).ConfigureAwait(false); } + return successfullyHandled; } - catch + catch (Exception) { await _messageLock.ReleaseLockAsync(lockKey).ConfigureAwait(false); throw; From 3478da8e17817f82fecc7c00b1ab86ee8b23b419 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:38:42 +0100 Subject: [PATCH 05/10] Refactor StopwatchHandler Do a reflection call to get the inner handler's type once per instance, rather than once per message. --- JustSaying/Messaging/Monitoring/StopwatchHandler.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/JustSaying/Messaging/Monitoring/StopwatchHandler.cs b/JustSaying/Messaging/Monitoring/StopwatchHandler.cs index a2eb51d85..0b96ee210 100644 --- a/JustSaying/Messaging/Monitoring/StopwatchHandler.cs +++ b/JustSaying/Messaging/Monitoring/StopwatchHandler.cs @@ -1,3 +1,4 @@ +using System; using System.Diagnostics; using System.Threading.Tasks; using JustSaying.Messaging.MessageHandling; @@ -9,21 +10,25 @@ public class StopwatchHandler : IHandlerAsync where T : Message { private readonly IHandlerAsync _inner; private readonly IMeasureHandlerExecutionTime _monitoring; + private readonly Type _handlerType; public StopwatchHandler(IHandlerAsync inner, IMeasureHandlerExecutionTime monitoring) { _inner = inner; _monitoring = monitoring; + _handlerType = _inner.GetType(); } public async Task Handle(T message) { - var watch = Stopwatch.StartNew(); - var result = await _inner.Handle(message).ConfigureAwait(false); + var stopwatch = Stopwatch.StartNew(); - watch.Stop(); + bool result = await _inner.Handle(message).ConfigureAwait(false); + + stopwatch.Stop(); + + _monitoring.HandlerExecutionTime(_handlerType, message.GetType(), stopwatch.Elapsed); - _monitoring.HandlerExecutionTime(_inner.GetType(), message.GetType(), watch.Elapsed); return result; } } From 0540f488444d65b994e2016bf61c511767b027d7 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:39:44 +0100 Subject: [PATCH 06/10] Use local function Use a local function for the worker task, rather than explicitly creating a Func. --- .../AwsTools/MessageHandling/SqsNotificationListener.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs b/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs index 38c8eb875..5ecf00db4 100644 --- a/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs +++ b/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs @@ -237,8 +237,12 @@ private async Task GetNumberOfMessagesToReadFromSqs() private Task HandleMessage(Amazon.SQS.Model.Message message, CancellationToken ct) { - var action = new Func(() => _messageDispatcher.DispatchMessage(message, ct)); - return _messageProcessingStrategy.StartWorker(action, ct); + async Task DispatchAsync() + { + await _messageDispatcher.DispatchMessage(message, ct); + } + + return _messageProcessingStrategy.StartWorker(DispatchAsync, ct); } public ICollection Subscribers { get; } From a0d10c3dadf05e1c8e2d14c8acc27ebdb43160f8 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:40:08 +0100 Subject: [PATCH 07/10] Make field readonly Make field readonly as its value is never reassigned. --- JustSaying/JustSayingBus.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JustSaying/JustSayingBus.cs b/JustSaying/JustSayingBus.cs index 3e9377388..2227ebb4a 100644 --- a/JustSaying/JustSayingBus.cs +++ b/JustSaying/JustSayingBus.cs @@ -34,7 +34,7 @@ public IMessageMonitor Monitor public IMessageLockAsync MessageLock { get; set; } public IMessageContextAccessor MessageContextAccessor { get; set; } - private ILogger _log; + private readonly ILogger _log; private readonly object _syncRoot = new object(); private readonly ICollection _publishers; From c73690fc3862bbbdafe411933e90f1bb9296ea6a Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:41:23 +0100 Subject: [PATCH 08/10] Reduce GetType() calls Reduce the number of calls to message.GetType(). Change logger overloads to not specify an event Id of zero. --- JustSaying/JustSayingBus.cs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/JustSaying/JustSayingBus.cs b/JustSaying/JustSayingBus.cs index 2227ebb4a..f5988d735 100644 --- a/JustSaying/JustSayingBus.cs +++ b/JustSaying/JustSayingBus.cs @@ -170,14 +170,18 @@ private IMessagePublisher GetActivePublisherForMessage(Message message) throw new InvalidOperationException($"Error publishing message. No publishers registered for active region '{activeRegion}'."); } - var topic = message.GetType().ToTopicName(); + var messageType = message.GetType(); + var topic = messageType.ToTopicName(); var publisherFound = publishersForRegion.TryGetValue(topic, out var publisher); if (!publisherFound) { - _log.LogError("Error publishing message. No publishers registered for message type '{MessageType}' in active region '{Region}'.", - message.GetType(), activeRegion); - throw new InvalidOperationException($"Error publishing message, no publishers registered for message type '{message.GetType()}' in active region '{activeRegion}'."); + _log.LogError( + "Error publishing message. No publishers registered for message type '{MessageType}' in active region '{Region}'.", + messageType, + activeRegion); + + throw new InvalidOperationException($"Error publishing message, no publishers registered for message type '{messageType}' in active region '{activeRegion}'."); } return publisher; @@ -236,16 +240,27 @@ await publisher.PublishAsync(message, metadata, cancellationToken) } catch (Exception ex) { + var messageType = message.GetType(); + if (attemptCount >= Config.PublishFailureReAttempts) { Monitor.IssuePublishingMessage(); - _log.LogError(0, ex, "Failed to publish a message of type '{MessageType}'. Halting after attempt number {PublishAttemptCount}.", - message.GetType(), attemptCount); + + _log.LogError( + ex, + "Failed to publish a message of type '{MessageType}'. Halting after attempt number {PublishAttemptCount}.", + messageType, + attemptCount); + throw; } - _log.LogWarning(0, ex, "Failed to publish a message of type '{MessageType}'. Retrying after attempt number {PublishAttemptCount} of {PublishFailureReattempts}.", - message.GetType(), attemptCount, Config.PublishFailureReAttempts); + _log.LogWarning( + ex, + "Failed to publish a message of type '{MessageType}'. Retrying after attempt number {PublishAttemptCount} of {PublishFailureReattempts}.", + messageType, + attemptCount, + Config.PublishFailureReAttempts); var delayForAttempt = TimeSpan.FromMilliseconds(Config.PublishFailureBackoff.TotalMilliseconds * attemptCount); await Task.Delay(delayForAttempt, cancellationToken).ConfigureAwait(false); From 17c87ecb225aa2394f1fdba74ca7ebae8f170d91 Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:43:39 +0100 Subject: [PATCH 09/10] Refactor logging Change log overloads used to not specify an event Id of zero. Reduce calls to message.GetType(). Include receipt handle in log message. --- .../MessageHandling/MessageDispatcher.cs | 43 ++++++++++++++----- .../SqsNotificationListener.cs | 28 ++++++++---- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs b/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs index 0285405c0..7a46b0a42 100644 --- a/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs +++ b/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs @@ -61,18 +61,26 @@ public async Task DispatchMessage(SQSMessage message, CancellationToken cancella } catch (MessageFormatNotSupportedException ex) { - _logger.LogTrace("Could not handle message with Id '{MessageId}' because a deserializer for the content is not configured. Message body: '{MessageBody}'.", - message.MessageId, message.Body); + _logger.LogTrace( + "Could not handle message with Id '{MessageId}' because a deserializer for the content is not configured. Message body: '{MessageBody}'.", + message.MessageId, + message.Body); + await DeleteMessageFromQueue(message.ReceiptHandle).ConfigureAwait(false); _onError(ex, message); + return; } #pragma warning disable CA1031 catch (Exception ex) #pragma warning restore CA1031 { - _logger.LogError(0, ex, "Error deserializing message with Id '{MessageId}' and body '{MessageBody}'.", - message.MessageId, message.Body); + _logger.LogError( + ex, + "Error deserializing message with Id '{MessageId}' and body '{MessageBody}'.", + message.MessageId, + message.Body); + _onError(ex, message); return; } @@ -98,8 +106,11 @@ public async Task DispatchMessage(SQSMessage message, CancellationToken cancella catch (Exception ex) #pragma warning restore CA1031 { - _logger.LogError(0, ex, "Error handling message with Id '{MessageId}' and body '{MessageBody}'.", - message.MessageId, message.Body); + _logger.LogError( + ex, + "Error handling message with Id '{MessageId}' and body '{MessageBody}'.", + message.MessageId, + message.Body); if (typedMessage != null) { @@ -123,7 +134,9 @@ public async Task DispatchMessage(SQSMessage message, CancellationToken cancella private async Task CallMessageHandler(Message message) { - var handler = _handlerMap.Get(message.GetType()); + var messageType = message.GetType(); + + var handler = _handlerMap.Get(messageType); if (handler == null) { @@ -135,8 +148,13 @@ private async Task CallMessageHandler(Message message) var handlerSucceeded = await handler(message).ConfigureAwait(false); watch.Stop(); - _logger.LogTrace("Handled message of type {MessageType} in {TimeToHandle}.", - message.GetType(), watch.Elapsed); + + _logger.LogTrace( + "Handled message with Id '{MessageId}' of type {MessageType} in {TimeToHandle}.", + message.Id, + messageType, + watch.Elapsed); + _messagingMonitor.HandleTime(watch.Elapsed); return handlerSucceeded; @@ -173,7 +191,12 @@ private async Task UpdateMessageVisibilityTimeout(SQSMessage message, string rec } catch (AmazonServiceException ex) { - _logger.LogError(0, ex, "Failed to update message visibility timeout by {VisibilityTimeout} seconds.", visibilityTimeoutSeconds); + _logger.LogError( + ex, + "Failed to update message visibility timeout by {VisibilityTimeout} seconds for message with receipt handle '{ReceiptHandle}'.", + visibilityTimeoutSeconds, + receiptHandle); + _onError(ex, message); } } diff --git a/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs b/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs index 5ecf00db4..fe2261ac1 100644 --- a/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs +++ b/JustSaying/AwsTools/MessageHandling/SqsNotificationListener.cs @@ -132,20 +132,29 @@ internal async Task ListenLoop(CancellationToken ct) } catch (InvalidOperationException ex) { - _log.LogTrace(0, ex, "Could not determine number of messages to read from queue '{QueueName}' in '{Region}'.", - queueName, regionName); + _log.LogTrace( + ex, + "Could not determine number of messages to read from queue '{QueueName}' in '{Region}'.", + queueName, + regionName); } catch (OperationCanceledException ex) { - _log.LogTrace(0, ex, "Suspected no message on queue '{QueueName}' in region '{Region}'.", - queueName, regionName); + _log.LogTrace( + ex, + "Suspected no message on queue '{QueueName}' in region '{Region}'.", + queueName, + regionName); } #pragma warning disable CA1031 catch (Exception ex) #pragma warning restore CA1031 { - _log.LogError(0, ex, "Error receiving messages on queue '{QueueName}' in region '{Region}'.", - queueName, regionName); + _log.LogError( + ex, + "Error receiving messages on queue '{QueueName}' in region '{Region}'.", + queueName, + regionName); } try @@ -166,8 +175,11 @@ internal async Task ListenLoop(CancellationToken ct) catch (Exception ex) #pragma warning restore CA1031 { - _log.LogError(0, ex, "Error in message handling loop for queue '{QueueName}' in region '{Region}'.", - queueName, regionName); + _log.LogError( + ex, + "Error in message handling loop for queue '{QueueName}' in region '{Region}'.", + queueName, + regionName); } } } From 53aa40bd974c64bdef8d8e7c15919465a1a5775a Mon Sep 17 00:00:00 2001 From: martincostello Date: Sun, 30 Jun 2019 14:44:14 +0100 Subject: [PATCH 10/10] Ensure MessageContext is reset Ensure that the MessageContext is reset to null if an exception is thrown when updating the message visibility timeout. --- .../MessageHandling/MessageDispatcher.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs b/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs index 7a46b0a42..e1f57bf5e 100644 --- a/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs +++ b/JustSaying/AwsTools/MessageHandling/MessageDispatcher.cs @@ -123,12 +123,17 @@ public async Task DispatchMessage(SQSMessage message, CancellationToken cancella } finally { - if (!handlingSucceeded && _messageBackoffStrategy != null) + try { - await UpdateMessageVisibilityTimeout(message, message.ReceiptHandle, typedMessage, lastException).ConfigureAwait(false); + if (!handlingSucceeded && _messageBackoffStrategy != null) + { + await UpdateMessageVisibilityTimeout(message, message.ReceiptHandle, typedMessage, lastException).ConfigureAwait(false); + } + } + finally + { + _messageContextAccessor.MessageContext = null; } - - _messageContextAccessor.MessageContext = null; } } @@ -206,7 +211,8 @@ private static bool TryGetApproxReceiveCount(IDictionary attribu { approxReceiveCount = 0; - return attributes.TryGetValue(MessageSystemAttributeName.ApproximateReceiveCount, out string rawApproxReceiveCount) && int.TryParse(rawApproxReceiveCount, out approxReceiveCount); + return attributes.TryGetValue(MessageSystemAttributeName.ApproximateReceiveCount, out string rawApproxReceiveCount) && + int.TryParse(rawApproxReceiveCount, out approxReceiveCount); } } }