-
-
Notifications
You must be signed in to change notification settings - Fork 249
Fixes #411: Adds option to dispose underlying scoped implementations #412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -10,20 +10,22 @@ namespace Foundatio.Caching; | |||||||||||||
|
|
||||||||||||||
| public class ScopedHybridCacheClient : ScopedCacheClient, IHybridCacheClient | ||||||||||||||
| { | ||||||||||||||
| public ScopedHybridCacheClient(IHybridCacheClient client, string scope = null) : base(client, scope) { } | ||||||||||||||
| public ScopedHybridCacheClient(IHybridCacheClient client, string scope = null, bool shouldDispose = false) : base(client, scope, shouldDispose) { } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public class ScopedCacheClient : ICacheClient, IHaveLogger, IHaveLoggerFactory, IHaveTimeProvider, IHaveResiliencePolicyProvider | ||||||||||||||
| { | ||||||||||||||
| private string _keyPrefix; | ||||||||||||||
| private bool _isLocked; | ||||||||||||||
| private readonly object _lock = new(); | ||||||||||||||
| private readonly bool _shouldDispose; | ||||||||||||||
|
|
||||||||||||||
|
||||||||||||||
| public ScopedCacheClient(ICacheClient client, string scope = null, bool shouldDispose = false) | |
| : this(client, scope, shouldDispose) | |
| { | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| using System; | ||
| using Foundatio.Caching; | ||
| using Xunit; | ||
| using Xunit.Abstractions; | ||
|
|
||
| namespace Foundatio.Tests.Caching; | ||
| public class ScopedCacheClientShouldDisposeTests : IDisposable | ||
| { | ||
| private readonly ITestOutputHelper _output; | ||
|
|
||
| public ScopedCacheClientShouldDisposeTests(ITestOutputHelper output) | ||
| { | ||
| _output = output; | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_DefaultBehavior_DoesNotDisposeUnderlyingCache() | ||
| { | ||
| // Arrange | ||
| var innerCache = new TrackableDisposableCacheClient(); | ||
| var scopedCache = new ScopedCacheClient(innerCache, "test"); | ||
|
|
||
| // Act | ||
| scopedCache.Dispose(); | ||
|
|
||
| // Assert | ||
| Assert.False(innerCache.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_ShouldDisposeTrue_DisposesUnderlyingCache() | ||
| { | ||
| // Arrange | ||
| var innerCache = new TrackableDisposableCacheClient(); | ||
| var scopedCache = new ScopedCacheClient(innerCache, "test", shouldDispose: true); | ||
|
|
||
| // Act | ||
| scopedCache.Dispose(); | ||
|
|
||
| // Assert | ||
| Assert.True(innerCache.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_WithUsingStatementAndShouldDisposeTrue_DisposesUnderlyingCache() | ||
| { | ||
| // Arrange | ||
| var innerCache = new TrackableDisposableCacheClient(); | ||
|
|
||
| // Act | ||
| using (var scopedCache = new ScopedCacheClient(innerCache, "test", shouldDispose: true)) | ||
| { | ||
| // No operations needed | ||
| } | ||
|
|
||
| // Assert | ||
| Assert.True(innerCache.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_WithUsingStatementAndShouldDisposeFalse_DoesNotDisposeUnderlyingCache() | ||
| { | ||
| // Arrange | ||
| var innerCache = new TrackableDisposableCacheClient(); | ||
|
|
||
| // Act | ||
| using (var scopedCache = new ScopedCacheClient(innerCache, "test", shouldDispose: false)) | ||
| { | ||
| // No operations needed | ||
| } | ||
|
|
||
| // Assert | ||
| Assert.False(innerCache.WasDisposed); | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| // Cleanup if needed | ||
| } | ||
|
|
||
| private class TrackableDisposableCacheClient : InMemoryCacheClient | ||
| { | ||
| public bool WasDisposed { get; private set; } | ||
|
|
||
| public new void Dispose() | ||
| { | ||
| WasDisposed = true; | ||
| base.Dispose(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| using System; | ||
| using Foundatio.Storage; | ||
| using Xunit; | ||
| using Xunit.Abstractions; | ||
|
|
||
| namespace Foundatio.Tests.Storage; | ||
| public class ScopedFileStorageShouldDisposeTests : IDisposable | ||
| { | ||
| private readonly ITestOutputHelper _output; | ||
|
|
||
| public ScopedFileStorageShouldDisposeTests(ITestOutputHelper output) | ||
| { | ||
| _output = output; | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_DefaultBehavior_DoesNotDisposeUnderlyingStorage() | ||
| { | ||
| // Arrange | ||
| var innerStorage = new TrackableDisposableFileStorage(); | ||
| var scopedStorage = new ScopedFileStorage(innerStorage, "test"); | ||
|
|
||
| // Act | ||
| scopedStorage.Dispose(); | ||
|
|
||
| // Assert | ||
| Assert.False(innerStorage.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_ShouldDisposeTrue_DisposesUnderlyingStorage() | ||
| { | ||
| // Arrange | ||
| var innerStorage = new TrackableDisposableFileStorage(); | ||
| var scopedStorage = new ScopedFileStorage(innerStorage, "test", shouldDispose: true); | ||
|
|
||
| // Act | ||
| scopedStorage.Dispose(); | ||
|
|
||
| // Assert | ||
| Assert.True(innerStorage.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_WithUsingStatementAndShouldDisposeTrue_DisposesUnderlyingStorage() | ||
| { | ||
| // Arrange | ||
| var innerStorage = new TrackableDisposableFileStorage(); | ||
|
|
||
| // Act | ||
| using (var scopedStorage = new ScopedFileStorage(innerStorage, "test", shouldDispose: true)) | ||
| { | ||
| // No operations needed | ||
| } | ||
|
|
||
| // Assert | ||
| Assert.True(innerStorage.WasDisposed); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Dispose_WithUsingStatementAndShouldDisposeFalse_DoesNotDisposeUnderlyingStorage() | ||
| { | ||
| // Arrange | ||
| var innerStorage = new TrackableDisposableFileStorage(); | ||
|
|
||
| // Act | ||
| using (var scopedStorage = new ScopedFileStorage(innerStorage, "test", shouldDispose: false)) | ||
| { | ||
| // No operations needed | ||
| } | ||
|
|
||
| // Assert | ||
| Assert.False(innerStorage.WasDisposed); | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| // Cleanup if needed | ||
| } | ||
|
|
||
| private class TrackableDisposableFileStorage : InMemoryFileStorage | ||
| { | ||
| public bool WasDisposed { get; private set; } | ||
|
|
||
| public new void Dispose() | ||
| { | ||
| WasDisposed = true; | ||
| base.Dispose(); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
ScopedHybridCacheClientconstructor maintains the default value forscopeparameter while the baseScopedCacheClientconstructor removes it. This inconsistency could lead to confusion and compilation errors when the base constructor is called.