Skip to content

Commit ea97d8e

Browse files
fix:ICacheClient、IDistributedCacheClient、IMultilevelCacheClient object can't release (#492)
* fix:ICacheClient、IDistributedCacheClient、IMultilevelCacheClient object can't release * style:change cache unit test method * feat: IDistributedCacheClientFactory.Create a object instance to support being released * style:rename IDistributedCacheClientDisposeWrapper to IManualDistributedCacheClient
1 parent 05bd805 commit ea97d8e

26 files changed

+157
-105
lines changed

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/CacheClientBase.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
@@ -7,7 +7,6 @@ public abstract class CacheClientBase : ICacheClient
77
{
88
public abstract IEnumerable<T?> GetList<T>(params string[] keys);
99

10-
1110
public abstract Task<IEnumerable<T?>> GetListAsync<T>(params string[] keys);
1211

1312
public virtual void Set<T>(string key, T value, DateTimeOffset? absoluteExpiration, Action<CacheOptions>? action = null)

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/Default/DistributedCacheClientFactoryBase.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public class DistributedCacheClientFactoryBase : CacheClientFactoryBase<IDistributedCacheClient>, IDistributedCacheClientFactory
6+
public class DistributedCacheClientFactoryBase : CacheClientFactoryBase<IManualDistributedCacheClient>, IDistributedCacheClientFactory
77
{
88
protected override string DefaultServiceNotFoundMessage
99
=> "Default DistributedCache not found, you need to add it, like services.AddStackExchangeRedisCache()";
1010

1111
protected override string SpecifyServiceNotFoundMessage => "Please make sure you have used [{0}] DistributedCache, it was not found";
1212

13-
protected override MasaFactoryOptions<CacheRelationOptions<IDistributedCacheClient>> FactoryOptions => _optionsMonitor.CurrentValue;
13+
protected override MasaFactoryOptions<CacheRelationOptions<IManualDistributedCacheClient>> FactoryOptions => _optionsMonitor.CurrentValue;
1414

1515
private readonly IOptionsMonitor<DistributedCacheFactoryOptions> _optionsMonitor;
1616

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/Default/MultilevelCacheClientFactoryBase.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public class MultilevelCacheClientFactoryBase : CacheClientFactoryBase<IMultilevelCacheClient>, IMultilevelCacheClientFactory
6+
public class MultilevelCacheClientFactoryBase : CacheClientFactoryBase<IManualMultilevelCacheClient>, IMultilevelCacheClientFactory
77
{
88
protected override string DefaultServiceNotFoundMessage
99
=> "Default MultilevelCache not found, you need to add it, like services.AddMultilevelCache()";
1010

1111
protected override string SpecifyServiceNotFoundMessage => "Please make sure you have used [{0}] MultilevelCache, it was not found";
1212

13-
protected override MasaFactoryOptions<CacheRelationOptions<IMultilevelCacheClient>> FactoryOptions => _optionsMonitor.CurrentValue;
13+
protected override MasaFactoryOptions<CacheRelationOptions<IManualMultilevelCacheClient>> FactoryOptions => _optionsMonitor.CurrentValue;
1414

1515
private readonly IOptionsMonitor<MultilevelCacheFactoryOptions> _optionsMonitor;
1616

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/DistributedCacheClientBase.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public abstract class DistributedCacheClientBase : CacheClientBase, IDistributedCacheClient
6+
public abstract class DistributedCacheClientBase : CacheClientBase, IManualDistributedCacheClient
77
{
88
public abstract T? Get<T>(string key, Action<CacheOptions>? action = null);
99

@@ -129,4 +129,14 @@ public abstract Task<long> KeyExpireAsync<T>(
129129
IEnumerable<string> keys,
130130
CacheEntryOptions? options = null,
131131
Action<CacheOptions>? action = null);
132+
133+
public void Dispose()
134+
{
135+
Dispose(true);
136+
GC.SuppressFinalize(this);
137+
}
138+
139+
protected virtual void Dispose(bool disposing)
140+
{
141+
}
132142
}

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/Extensions/ServiceCollectionExtensions.Core.cs

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public static IServiceCollection TryAddDistributedCacheCore(IServiceCollection s
1616
services.TryAddSingleton<IDistributedCacheClientFactory, DistributedCacheClientFactoryBase>();
1717
services.TryAddSingleton(serviceProvider
1818
=> serviceProvider.GetRequiredService<IDistributedCacheClientFactory>().Create());
19+
services.TryAddSingleton(typeof(IDistributedCacheClient), serviceProvider
20+
=> serviceProvider.GetRequiredService<IManualDistributedCacheClient>());
1921

2022
services.TryAddSingleton<ITypeAliasFactory, DefaultTypeAliasFactory>();
2123
services.Configure<TypeAliasFactoryOptions>(options => options.TryAdd(name));
@@ -27,6 +29,8 @@ public static IServiceCollection TryAddMultilevelCacheCore(IServiceCollection se
2729
services.TryAddSingleton<IMultilevelCacheClientFactory, MultilevelCacheClientFactoryBase>();
2830
services.TryAddSingleton(serviceProvider
2931
=> serviceProvider.GetRequiredService<IMultilevelCacheClientFactory>().Create());
32+
services.TryAddSingleton(typeof(IMultilevelCacheClient), serviceProvider
33+
=> serviceProvider.GetRequiredService<IManualMultilevelCacheClient>());
3034

3135
services.TryAddSingleton<ITypeAliasFactory, DefaultTypeAliasFactory>();
3236
services.Configure<TypeAliasFactoryOptions>(options => options.TryAdd(name));

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/ICacheClient.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

66
public interface ICacheClient
77
{
8-
IEnumerable<T?> GetList<T>(params string[] keys);
8+
IEnumerable<T?> GetList<T>(params string[] keys);
99

1010
Task<IEnumerable<T?>> GetListAsync<T>(params string[] keys);
1111

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public interface IDistributedCacheClientFactory : ICacheClientFactory<IDistributedCacheClient>
6+
public interface IDistributedCacheClientFactory : ICacheClientFactory<IManualDistributedCacheClient>
77
{
88

99
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) MASA Stack All rights reserved.
2+
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3+
4+
namespace Masa.BuildingBlocks.Caching;
5+
6+
public interface IManualDistributedCacheClient : IDistributedCacheClient, IDisposable
7+
{
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) MASA Stack All rights reserved.
2+
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3+
4+
namespace Masa.BuildingBlocks.Caching;
5+
6+
public interface IManualMultilevelCacheClient : IMultilevelCacheClient, IDisposable
7+
{
8+
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public interface IMultilevelCacheClientFactory: ICacheClientFactory<IMultilevelCacheClient>
6+
public interface IMultilevelCacheClientFactory: ICacheClientFactory<IManualMultilevelCacheClient>
77
{
88

99
}

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/MultilevelCacheClientBase.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public abstract class MultilevelCacheClientBase : CacheClientBase, IMultilevelCacheClient
6+
public abstract class MultilevelCacheClientBase : CacheClientBase, IManualMultilevelCacheClient
77
{
88
/// <summary>
99
/// Get cache
@@ -173,4 +173,14 @@ public abstract Task SetListAsync<T>(
173173
Dictionary<string, T?> keyValues,
174174
CombinedCacheEntryOptions? options,
175175
Action<CacheOptions>? action = null);
176+
177+
public void Dispose()
178+
{
179+
Dispose(true);
180+
GC.SuppressFinalize(this);
181+
}
182+
183+
protected virtual void Dispose(bool disposing)
184+
{
185+
}
176186
}

src/BuildingBlocks/Caching/Masa.BuildingBlocks.Caching/Options/CacheRelationOptions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public class DistributedCacheFactoryOptions : MasaFactoryOptions<CacheRelationOptions<IDistributedCacheClient>>
6+
public class DistributedCacheFactoryOptions : MasaFactoryOptions<CacheRelationOptions<IManualDistributedCacheClient>>
77
{
88

99
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.BuildingBlocks.Caching;
55

6-
public class MultilevelCacheFactoryOptions: MasaFactoryOptions<CacheRelationOptions<IMultilevelCacheClient>>
6+
public class MultilevelCacheFactoryOptions: MasaFactoryOptions<CacheRelationOptions<IManualMultilevelCacheClient>>
77
{
88

99
}

src/Contrib/Caching/Distributed/Masa.Contrib.Caching.Distributed.StackExchangeRedis/Extensions/DistributedCacheOptionsExtensions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
// ReSharper disable once CheckNamespace
@@ -78,7 +78,7 @@ private static DistributedCacheOptions UseStackExchangeRedisCache(
7878
if (options.Options.Any(opt => opt.Name == distributedOptions.Name))
7979
return;
8080

81-
var cacheRelationOptions = new CacheRelationOptions<IDistributedCacheClient>(distributedOptions.Name, serviceProvider =>
81+
var cacheRelationOptions = new CacheRelationOptions<IManualDistributedCacheClient>(distributedOptions.Name, serviceProvider =>
8282
{
8383
var distributedCacheClient = new RedisCacheClient(
8484
serviceProvider.GetRequiredService<IOptionsMonitor<RedisConfigurationOptions>>(),
@@ -123,7 +123,7 @@ internal static void UseStackExchangeRedisCache(
123123
if (options.Options.Any(opt => opt.Name == name))
124124
return;
125125

126-
var cacheRelationOptions = new CacheRelationOptions<IDistributedCacheClient>(name, serviceProvider =>
126+
var cacheRelationOptions = new CacheRelationOptions<IManualDistributedCacheClient>(name, serviceProvider =>
127127
{
128128
var distributedCacheClient = new RedisCacheClient(
129129
redisConfigurationOptions,

src/Contrib/Caching/Distributed/Masa.Contrib.Caching.Distributed.StackExchangeRedis/RedisCacheClient.cs

+2-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.Contrib.Caching.Distributed.StackExchangeRedis;
@@ -17,7 +17,7 @@ public RedisCacheClient(IOptionsMonitor<RedisConfigurationOptions> redisConfigur
1717
{
1818
if (optionName == name)
1919
{
20-
RefreshRedisConfigurationOptions(option);
20+
InitializeRedisConfigurationOptions(option);
2121
GlobalCacheOptions = option.GlobalCacheOptions;
2222
}
2323
});
@@ -576,20 +576,6 @@ public override Task<long> KeyExpireAsync<T>(
576576

577577
#region Private methods
578578

579-
private void RefreshRedisConfigurationOptions(RedisConfigurationOptions redisConfigurationOptions)
580-
{
581-
IConnectionMultiplexer? connection = ConnectionMultiplexer.Connect(redisConfigurationOptions);
582-
Db = connection.GetDatabase();
583-
Subscriber = connection.GetSubscriber();
584-
585-
GlobalCacheEntryOptions = new CacheEntryOptions
586-
{
587-
AbsoluteExpiration = redisConfigurationOptions.AbsoluteExpiration,
588-
AbsoluteExpirationRelativeToNow = redisConfigurationOptions.AbsoluteExpirationRelativeToNow,
589-
SlidingExpiration = redisConfigurationOptions.SlidingExpiration
590-
};
591-
}
592-
593579
private RedisValue[] GetRedisValues(CacheEntryOptions? options, Func<RedisValue[]>? func = null)
594580
{
595581
var creationTime = DateTimeOffset.UtcNow;
@@ -696,5 +682,4 @@ private string FormatKeyPattern<T>(string keyPattern,
696682
}
697683

698684
#endregion
699-
700685
}

src/Contrib/Caching/Distributed/Masa.Contrib.Caching.Distributed.StackExchangeRedis/RedisCacheClientBase.cs

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) MASA Stack All rights reserved.
1+
// Copyright (c) MASA Stack All rights reserved.
22
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.
33

44
namespace Masa.Contrib.Caching.Distributed.StackExchangeRedis;
@@ -8,6 +8,7 @@ public abstract class RedisCacheClientBase : DistributedCacheClientBase
88
protected static readonly Guid UniquelyIdentifies = Guid.NewGuid();
99
protected ISubscriber Subscriber;
1010
protected IDatabase Db;
11+
protected IConnectionMultiplexer? Connection;
1112
protected readonly JsonSerializerOptions GlobalJsonSerializerOptions;
1213
protected CacheEntryOptions GlobalCacheEntryOptions;
1314
protected CacheOptions GlobalCacheOptions;
@@ -17,17 +18,24 @@ protected RedisCacheClientBase(RedisConfigurationOptions redisConfigurationOptio
1718
{
1819
GlobalCacheOptions = redisConfigurationOptions.GlobalCacheOptions;
1920
var redisConfiguration = GetRedisConfigurationOptions(redisConfigurationOptions);
20-
IConnectionMultiplexer? connection = ConnectionMultiplexer.Connect(redisConfiguration);
21-
Db = connection.GetDatabase();
22-
Subscriber = connection.GetSubscriber();
21+
InitializeRedisConfigurationOptions(redisConfiguration);
2322

2423
GlobalJsonSerializerOptions = jsonSerializerOptions ?? new JsonSerializerOptions().EnableDynamicTypes();
24+
}
25+
26+
protected void InitializeRedisConfigurationOptions(RedisConfigurationOptions redisConfigurationOptions)
27+
{
28+
Dispose();
29+
30+
Connection = ConnectionMultiplexer.Connect(redisConfigurationOptions);
31+
Db = Connection.GetDatabase();
32+
Subscriber = Connection.GetSubscriber();
2533

2634
GlobalCacheEntryOptions = new CacheEntryOptions
2735
{
28-
AbsoluteExpiration = redisConfiguration.AbsoluteExpiration,
29-
AbsoluteExpirationRelativeToNow = redisConfiguration.AbsoluteExpirationRelativeToNow,
30-
SlidingExpiration = redisConfiguration.SlidingExpiration
36+
AbsoluteExpiration = redisConfigurationOptions.AbsoluteExpiration,
37+
AbsoluteExpirationRelativeToNow = redisConfigurationOptions.AbsoluteExpirationRelativeToNow,
38+
SlidingExpiration = redisConfigurationOptions.SlidingExpiration
3139
};
3240
}
3341

@@ -236,4 +244,10 @@ private static DataCacheModel MapMetadataByAutomatic(string key, RedisValue[] re
236244
}
237245
return new DataCacheModel(key, absoluteExpiration, slidingExpiration, data);
238246
}
247+
248+
protected override void Dispose(bool disposing)
249+
{
250+
Connection?.Dispose();
251+
base.Dispose(disposing);
252+
}
239253
}

0 commit comments

Comments
 (0)