From b693bac91066af53a36911e5bffb4ef136a08e48 Mon Sep 17 00:00:00 2001 From: Tim Bussmann Date: Wed, 31 Aug 2022 17:10:55 +0200 Subject: [PATCH] Session disposal (#6525) * resolve storage session per call * only dispose session once * approve scope change in test * change registration back to same scope as the referenced type --- ...eSynchronizedStorageSessionAdapterTests.cs | 44 +++++++++++++++++++ ...etableSynchronizedStorageSessionAdapter.cs | 13 +++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/NServiceBus.Core.Tests/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapterTests.cs diff --git a/src/NServiceBus.Core.Tests/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapterTests.cs b/src/NServiceBus.Core.Tests/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapterTests.cs new file mode 100644 index 0000000000..1f37924181 --- /dev/null +++ b/src/NServiceBus.Core.Tests/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapterTests.cs @@ -0,0 +1,44 @@ +namespace NServiceBus.Core.Tests.Reliability +{ + using System.Threading.Tasks; + using Extensibility; + using NServiceBus.Outbox; + using NServiceBus.Persistence; + using NUnit.Framework; + using Transport; + + [TestFixture] + public class CompletableSynchronizedStorageSessionAdapterTests + { + [Test] + public async Task Should_dispose_adapted_session_only_once() + { + var storageAdapter = new FakeStorageAdapter(); + var sessionAdapter = new CompletableSynchronizedStorageSessionAdapter(storageAdapter, null); + await sessionAdapter.TryOpen(new TransportTransaction(), new ContextBag()); + + sessionAdapter.Dispose(); + sessionAdapter.Dispose(); + + Assert.AreEqual(1, storageAdapter.StorageSession.DisposeCounter); + } + } + + public class FakeStorageAdapter : ISynchronizedStorageAdapter + { + public FakeStorageSession StorageSession { get; } = new FakeStorageSession(); + + public Task TryAdapt(OutboxTransaction transaction, ContextBag context) => Task.FromResult(StorageSession); + + public Task TryAdapt(TransportTransaction transportTransaction, ContextBag context) => Task.FromResult(StorageSession); + } + + public class FakeStorageSession : CompletableSynchronizedStorageSession + { + public int DisposeCounter { get; private set; } + + public void Dispose() => DisposeCounter++; + + public Task CompleteAsync() => Task.FromResult(0); + } +} \ No newline at end of file diff --git a/src/NServiceBus.Core/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapter.cs b/src/NServiceBus.Core/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapter.cs index 8342e31473..9fe535bb82 100644 --- a/src/NServiceBus.Core/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapter.cs +++ b/src/NServiceBus.Core/Reliability/SynchronizedStorage/CompletableSynchronizedStorageSessionAdapter.cs @@ -17,7 +17,16 @@ public CompletableSynchronizedStorageSessionAdapter(ISynchronizedStorageAdapter } public CompletableSynchronizedStorageSession AdaptedSession { get; private set; } - public void Dispose() => AdaptedSession?.Dispose(); + public void Dispose() + { + if (disposed) + { + return; + } + + AdaptedSession?.Dispose(); + disposed = true; + } public Task CompleteAsync() => AdaptedSession.CompleteAsync(); @@ -37,6 +46,8 @@ public async Task TryOpen(TransportTransaction transportTransaction, Conte public async Task Open(ContextBag contextBag) => AdaptedSession = await synchronizedStorage.OpenSession(contextBag).ConfigureAwait(false); + bool disposed; + readonly ISynchronizedStorageAdapter synchronizedStorageAdapter; readonly ISynchronizedStorage synchronizedStorage; }