diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ad85ec95..2b4ab1a7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -16,9 +16,9 @@ jobs:
os: [ windows-latest ]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Setup .NET SDK 6.0.x
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
diff --git a/.github/workflows/buildandtest.yml b/.github/workflows/buildandtest.yml
index fb79d718..2466ba79 100644
--- a/.github/workflows/buildandtest.yml
+++ b/.github/workflows/buildandtest.yml
@@ -38,9 +38,9 @@ jobs:
- 11212:11211
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Setup .NET SDK 6.0.x
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ef7049cc..61396945 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -13,9 +13,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v4
- name: Setup .NET Core
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: Build with dotnet
@@ -23,7 +23,7 @@ jobs:
- name: Pack with dotnet
run: dotnet pack /home/runner/work/EasyCaching/EasyCaching/EasyCaching.sln --version-suffix alpha`date +%Y%m%d%H%M%S` -o /home/runner/work/nugetpkgs -c Release --no-build
- name: Upload artifact
- uses: actions/upload-artifact@v1
+ uses: actions/upload-artifact@v3
with:
name: nugetpkgs
path: /home/runner/work/nugetpkgs
@@ -35,9 +35,10 @@ jobs:
steps:
- name: Download build artifacts
- uses: actions/download-artifact@v1
+ uses: actions/download-artifact@v3
with:
name: nugetpkgs
+ path: nugetpkgs
- name: list nugetpkgs
run: ls nugetpkgs
- name: Release
diff --git a/.github/workflows/release_stable.yml b/.github/workflows/release_stable.yml
index cb7a7eca..b4448612 100644
--- a/.github/workflows/release_stable.yml
+++ b/.github/workflows/release_stable.yml
@@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v4
- name: Setup .NET Core
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.0.x
- name: Build with dotnet
@@ -21,7 +21,7 @@ jobs:
- name: Pack with dotnet
run: dotnet pack /home/runner/work/EasyCaching/EasyCaching/EasyCaching.sln -o /home/runner/work/nugetpkgs -c Release --no-build
- name: Upload artifact
- uses: actions/upload-artifact@v1
+ uses: actions/upload-artifact@v3
with:
name: nugetpkgs
path: /home/runner/work/nugetpkgs
@@ -33,9 +33,10 @@ jobs:
steps:
- name: Download build artifacts
- uses: actions/download-artifact@v1
+ uses: actions/download-artifact@v3
with:
name: nugetpkgs
+ path: nugetpkgs
- name: list nugetpkgs
run: ls nugetpkgs
- name: Release
diff --git a/EasyCaching.sln b/EasyCaching.sln
index 7d07ad0a..9ae4c577 100644
--- a/EasyCaching.sln
+++ b/EasyCaching.sln
@@ -1,4 +1,5 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32616.157
MinimumVisualStudioVersion = 10.0.40219.1
@@ -72,12 +73,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyCaching.Serialization.S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyCaching.Bus.ConfluentKafka", "bus\EasyCaching.Bus.ConfluentKafka\EasyCaching.Bus.ConfluentKafka.csproj", "{F7FBADEB-D766-4595-949A-07104B52692C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Bus.Zookeeper", "bus\EasyCaching.Bus.Zookeeper\EasyCaching.Bus.Zookeeper.csproj", "{5E488583-391E-4E15-83C1-7301B4FE79AE}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyCaching.Bus.Zookeeper", "bus\EasyCaching.Bus.Zookeeper\EasyCaching.Bus.Zookeeper.csproj", "{5E488583-391E-4E15-83C1-7301B4FE79AE}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.FasterKv", "src\EasyCaching.FasterKv\EasyCaching.FasterKv.csproj", "{7191E567-38DF-4879-82E1-73EC618AFCAC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyCaching.FasterKv", "src\EasyCaching.FasterKv\EasyCaching.FasterKv.csproj", "{7191E567-38DF-4879-82E1-73EC618AFCAC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Bus.RabbitMQStream", "bus\EasyCaching.Bus.RabbitMQStream\EasyCaching.Bus.RabbitMQStream.csproj", "{3C9D5E40-B3A5-4649-8B40-08094644B0FB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Serialization.MemoryPack", "serialization\EasyCaching.Serialization.MemoryPack\EasyCaching.Serialization.MemoryPack.csproj", "{EEF22C21-F380-4980-B72C-F14488369333}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Demo.Locks", "sample\EasyCaching.Demo.Locks\EasyCaching.Demo.Locks.csproj", "{9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -208,6 +213,14 @@ Global
{EEF22C21-F380-4980-B72C-F14488369333}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3C9D5E40-B3A5-4649-8B40-08094644B0FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3C9D5E40-B3A5-4649-8B40-08094644B0FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3C9D5E40-B3A5-4649-8B40-08094644B0FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3C9D5E40-B3A5-4649-8B40-08094644B0FB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -244,6 +257,8 @@ Global
{5E488583-391E-4E15-83C1-7301B4FE79AE} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
{7191E567-38DF-4879-82E1-73EC618AFCAC} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9}
{EEF22C21-F380-4980-B72C-F14488369333} = {15070C49-A507-4844-BCFE-D319CFBC9A63}
+ {3C9D5E40-B3A5-4649-8B40-08094644B0FB} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
+ {9B15A0A0-BD6B-40B0-90D4-848BC3E4AF98} = {F88D727A-9F9C-43D9-90B1-D4A02BF8BC98}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {63A57886-054B-476C-AAE1-8D7C8917682E}
diff --git a/build/releasenotes.props b/build/releasenotes.props
index 1fe50f01..68666432 100644
--- a/build/releasenotes.props
+++ b/build/releasenotes.props
@@ -14,6 +14,7 @@
1. Upgrading dependencies.
+ 2. Fix no check expires when get cache count
1. Upgrading dependencies.
@@ -59,6 +60,7 @@
1. Upgrading dependencies.
+ 2. Always use utc to compare the expiry
1. Upgrading dependencies.
@@ -69,5 +71,8 @@
1. Upgrading dependencies.
+
+ 1. Initial release.
+
diff --git a/build/version.props b/build/version.props
index 5dc47ec6..18841930 100644
--- a/build/version.props
+++ b/build/version.props
@@ -1,28 +1,29 @@
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
- 1.9.1
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
+ 1.9.2
diff --git a/bus/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs b/bus/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs
index f5a09bf6..359568fe 100644
--- a/bus/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs
+++ b/bus/EasyCaching.Bus.RabbitMQ/Configurations/RabbitMQBusOptions.cs
@@ -6,7 +6,7 @@
/// RabbitMQ Bus options.
///
public class RabbitMQBusOptions : BaseRabbitMQOptions
- {
+ {
///
/// Gets or sets the name of the queue.
///
diff --git a/bus/EasyCaching.Bus.RabbitMQStream/Configurations/EasyCachingOptionsExtensions.cs b/bus/EasyCaching.Bus.RabbitMQStream/Configurations/EasyCachingOptionsExtensions.cs
new file mode 100644
index 00000000..9edbb383
--- /dev/null
+++ b/bus/EasyCaching.Bus.RabbitMQStream/Configurations/EasyCachingOptionsExtensions.cs
@@ -0,0 +1,68 @@
+namespace Microsoft.Extensions.DependencyInjection
+{
+ using System;
+ using EasyCaching.Bus.RabbitMQ;
+ using EasyCaching.Bus.RabbitMQStream;
+ using EasyCaching.Core;
+ using EasyCaching.Core.Configurations;
+ using Microsoft.Extensions.Configuration;
+
+ ///
+ /// EasyCaching options extensions.
+ ///
+ public static class EasyCachingOptionsExtensions
+ {
+ ///
+ /// Withs the RabbitMQStream bus (specify the config via hard code).
+ ///
+ /// Options.
+ /// Configure bus settings.
+
+ public static EasyCachingOptions WithRabbitMQStreamBus(
+ this EasyCachingOptions options
+ , Action configure
+ )
+ {
+ ArgumentCheck.NotNull(configure, nameof(configure));
+
+ options.RegisterExtension(new RabbitMQStreamBusOptionsExtension(configure));
+ return options;
+ }
+
+ ///
+ /// Withs the RabbitMQStream bus (read config from configuration file).
+ ///
+ /// Options.
+ /// The configuration.
+ /// The section name in the configuration file.
+ public static EasyCachingOptions WithRabbitMQStreamBus(
+ this EasyCachingOptions options
+ , IConfiguration configuration
+ , string sectionName = EasyCachingConstValue.RabbitMQBusSection
+ )
+ {
+ var dbConfig = configuration.GetSection(sectionName);
+ var busOptions = new RabbitMQBusOptions();
+ dbConfig.Bind(busOptions);
+
+ void configure(RabbitMQBusOptions x)
+ {
+ x.HostName = busOptions.HostName;
+ x.Password = busOptions.Password;
+ x.Port = busOptions.Port;
+ x.QueueMessageExpires = busOptions.QueueMessageExpires;
+ x.RequestedConnectionTimeout = busOptions.RequestedConnectionTimeout;
+ //x.RouteKey = busOptions.RouteKey;
+ x.SocketReadTimeout = busOptions.SocketReadTimeout;
+ x.SocketWriteTimeout = busOptions.SocketWriteTimeout;
+ x.TopicExchangeName = busOptions.TopicExchangeName;
+ x.UserName = busOptions.UserName;
+ x.VirtualHost = busOptions.VirtualHost;
+ x.QueueName = busOptions.QueueName;
+ }
+
+ options.RegisterExtension(new RabbitMQStreamBusOptionsExtension(configure));
+ return options;
+ }
+ }
+}
\ No newline at end of file
diff --git a/bus/EasyCaching.Bus.RabbitMQStream/Configurations/RabbitMQStreamBusOptionsExtension.cs b/bus/EasyCaching.Bus.RabbitMQStream/Configurations/RabbitMQStreamBusOptionsExtension.cs
new file mode 100644
index 00000000..275cf5ae
--- /dev/null
+++ b/bus/EasyCaching.Bus.RabbitMQStream/Configurations/RabbitMQStreamBusOptionsExtension.cs
@@ -0,0 +1,43 @@
+namespace EasyCaching.Bus.RabbitMQStream
+{
+ using System;
+ using EasyCaching.Bus.RabbitMQ;
+ using EasyCaching.Core.Bus;
+ using EasyCaching.Core.Configurations;
+ using global::RabbitMQ.Client;
+ using Microsoft.Extensions.DependencyInjection;
+ using Microsoft.Extensions.ObjectPool;
+
+ ///
+ /// RabbitMQ Bus options extension.
+ ///
+ public class RabbitMQStreamBusOptionsExtension : IEasyCachingOptionsExtension
+ {
+ ///
+ /// The configure.
+ ///
+ private readonly Action configure;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Configure.
+ public RabbitMQStreamBusOptionsExtension(Action configure)
+ {
+ this.configure = configure;
+ }
+
+ ///
+ /// Adds the services.
+ ///
+ /// Services.
+ public void AddServices(IServiceCollection services)
+ {
+ services.AddOptions();
+ services.Configure(configure);
+
+ services.AddSingleton, ModelPooledObjectPolicy>();
+ services.AddSingleton();
+ }
+ }
+}
diff --git a/bus/EasyCaching.Bus.RabbitMQStream/DefaultRabbitMQStreamBus.cs b/bus/EasyCaching.Bus.RabbitMQStream/DefaultRabbitMQStreamBus.cs
new file mode 100644
index 00000000..ac602cdb
--- /dev/null
+++ b/bus/EasyCaching.Bus.RabbitMQStream/DefaultRabbitMQStreamBus.cs
@@ -0,0 +1,251 @@
+using Microsoft.Extensions.Logging;
+
+namespace EasyCaching.Bus.RabbitMQ
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using EasyCaching.Core;
+ using EasyCaching.Core.Bus;
+ using EasyCaching.Core.Serialization;
+ using global::RabbitMQ.Client;
+ using global::RabbitMQ.Client.Events;
+ using Microsoft.Extensions.ObjectPool;
+ using Microsoft.Extensions.Options;
+
+ ///
+ /// Default RabbitMQ Bus.
+ ///
+ public class DefaultRabbitMQStreamBus : EasyCachingAbstractBus
+ {
+ ///
+ /// The subscriber connection.
+ ///
+ private readonly IConnection _subConnection;
+
+ ///
+ /// The publish channel pool.
+ ///
+ private readonly ObjectPool _pubChannelPool;
+
+ ///
+ /// The rabbitMQ Bus options.
+ ///
+ private readonly RabbitMQBusOptions _options;
+
+ ///
+ /// The serializer.
+ ///
+ private readonly IEasyCachingSerializer _serializer;
+
+ ///
+ /// The logger.
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// The identifier.
+ ///
+ private readonly string _busId;
+
+ private static readonly Dictionary _streamArgs = new Dictionary
+ {
+ { "x-queue-type", "stream" },
+ { "x-max-age", "5m" },
+ { "x-stream-max-segment-size-bytes", 4_000_000 }
+ };
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Object policy.
+ /// RabbitMQ Options.
+ /// Serializer.
+ /// Logger.
+ public DefaultRabbitMQStreamBus(
+ IPooledObjectPolicy objectPolicy
+ , IOptions rabbitMQOptions
+ , IEasyCachingSerializer serializer
+ , Lazy> logger)
+ {
+ this._options = rabbitMQOptions.Value;
+ this._serializer = serializer;
+ this._logger = logger.Value;
+
+ _logger?.LogInformation("DefaultRabbitMQStreamBus: Initializing");
+ try
+ {
+ var factory = new ConnectionFactory
+ {
+ HostName = _options.HostName,
+ UserName = _options.UserName,
+ Port = _options.Port,
+ Password = _options.Password,
+ VirtualHost = _options.VirtualHost,
+ RequestedConnectionTimeout = System.TimeSpan.FromMilliseconds(_options.RequestedConnectionTimeout),
+ SocketReadTimeout = System.TimeSpan.FromMilliseconds(_options.SocketReadTimeout),
+ SocketWriteTimeout = System.TimeSpan.FromMilliseconds(_options.SocketWriteTimeout),
+ ClientProvidedName = _options.ClientProvidedName
+ };
+
+ _subConnection = factory.CreateConnection();
+
+ _subConnection.ConnectionShutdown += (_, e) =>
+ {
+ _logger?.LogError($"ConnectionShutdown: {e.ReplyText}");
+ };
+
+ var provider = new DefaultObjectPoolProvider();
+
+ _pubChannelPool = provider.Create(objectPolicy);
+
+ _busId = Guid.NewGuid().ToString("N");
+
+ BusName = "easycachingbus";
+ }
+ catch (Exception ex)
+ {
+ _logger?.LogError(ex, $"DefaultRabbitMQStreamBus: Initializing failed ({ex.Message})");
+ throw;
+ }
+ }
+
+ ///
+ /// Publish the specified topic and message.
+ ///
+ /// Topic.
+ /// Message.
+ public override void BasePublish(string topic, EasyCachingMessage message)
+ {
+ var channel = _pubChannelPool.Get();
+
+ try
+ {
+ var body = _serializer.Serialize(message);
+
+ channel.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null);
+ channel.BasicPublish(_options.TopicExchangeName, topic, false, null, body);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ finally
+ {
+ _pubChannelPool.Return(channel);
+ }
+ }
+
+ ///
+ /// Publish the specified topic and message async.
+ ///
+ /// The async.
+ /// Topic.
+ /// Message.
+ /// Cancellation token.
+ public override Task BasePublishAsync(string topic, EasyCachingMessage message, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var channel = _pubChannelPool.Get();
+ try
+ {
+ var body = _serializer.Serialize(message);
+
+ channel.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null);
+ channel.BasicPublish(_options.TopicExchangeName, topic, false, null, body);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+ finally
+ {
+ _pubChannelPool.Return(channel);
+ }
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Subscribe the specified topic and action.
+ ///
+ /// Topic.
+ /// Action.
+ public override void BaseSubscribe(string topic, Action action)
+ {
+ var queueName = $"rmq.stream.easycaching.{topic}";
+
+ Task.Factory.StartNew(
+ () => StartConsumer(queueName, topic),
+ TaskCreationOptions.LongRunning);
+ }
+
+ ///
+ /// Subscribe the specified topic and action async.
+ ///
+ /// Topic.
+ /// Action.
+ /// Cancellation token.
+ public override Task BaseSubscribeAsync(string topic, Action action, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ _logger?.LogWarning($"BaseSubscribeAsync for {topic}");
+
+ var queueName = $"rmq.stream.easycaching.{topic}";
+
+ StartConsumer(queueName, topic);
+ return Task.CompletedTask;
+ }
+
+ private void StartConsumer(string queueName, string topic)
+ {
+ _logger?.LogWarning($"Starting Consumer for {topic} ({queueName})");
+ var channel = _subConnection.CreateModel();
+
+ channel.ModelShutdown += (_, e) =>
+ {
+ _logger?.LogError($"ModelShutdown: {e.ReplyText}");
+ };
+
+ // Streams require Qos setup
+ channel.BasicQos(0, 100, false);
+ channel.ExchangeDeclare(_options.TopicExchangeName, ExchangeType.Topic, true, false, null);
+ channel.QueueDeclare(queueName, true, false, false, _streamArgs);
+ // bind the queue with the exchange.
+ channel.QueueBind(queueName, _options.TopicExchangeName, topic);
+ var consumer = new EventingBasicConsumer(channel);
+ consumer.Received += OnMessage;
+
+ consumer.ConsumerCancelled += (sender, e) =>
+ {
+ _logger?.LogError($"EasyCaching.DefaultRabbitMQStreamBus.OnConsumerCancelled: (Q: {queueName})");
+ };
+
+ consumer.Shutdown += (sender, e) =>
+ {
+ _logger?.LogError($"EasyCaching.DefaultRabbitMQStreamBus.OnConsumerShutdown: (Q: {queueName}) {e.ReplyText}");
+ StartConsumer(queueName, topic);
+ BaseOnReconnect();
+ };
+
+ channel.BasicConsume(queueName, false, consumer);
+ }
+
+ ///
+ /// Ons the message.
+ ///
+ /// Sender.
+ /// E.
+ private void OnMessage(object sender, BasicDeliverEventArgs e)
+ {
+ try
+ {
+ var message = _serializer.Deserialize(e.Body.ToArray());
+ _logger?.LogDebug(string.Join(",", message.CacheKeys));
+ BaseOnMessage(message);
+ }
+ finally
+ {
+ (sender as EventingBasicConsumer)?.Model.BasicAck(e.DeliveryTag, false);
+ }
+ }
+ }
+}
diff --git a/bus/EasyCaching.Bus.RabbitMQStream/EasyCaching.Bus.RabbitMQStream.csproj b/bus/EasyCaching.Bus.RabbitMQStream/EasyCaching.Bus.RabbitMQStream.csproj
new file mode 100644
index 00000000..4a1d9b02
--- /dev/null
+++ b/bus/EasyCaching.Bus.RabbitMQStream/EasyCaching.Bus.RabbitMQStream.csproj
@@ -0,0 +1,50 @@
+
+
+
+
+ netstandard2.0;net6.0
+ ncc;Thomas Sarmis
+ ncc;Thomas Sarmis
+ $(EasyCachingRabbitStreamBusPackageVersion)
+
+
+ A simple caching bus(message bus) based on RabbitMQ using amqp Streams.
+
+ Bus,Hybrid,RabbitMQ,Caching,Cache
+ https://github.com/dotnetcore/EasyCaching
+ LICENSE
+ https://github.com/dotnetcore/EasyCaching
+ https://github.com/dotnetcore/EasyCaching
+ nuget-icon.png
+
+ $(EasyCachingRabbitStreamBusPackageNotes)
+
+
+
+
+ true
+ $(NoWarn);1591
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/EasyCaching.Demo.Locks/Controllers/LocksController.cs b/sample/EasyCaching.Demo.Locks/Controllers/LocksController.cs
new file mode 100644
index 00000000..b6400a70
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/Controllers/LocksController.cs
@@ -0,0 +1,70 @@
+namespace EasyCaching.Demo.Locks.Controllers;
+
+[Route("api/[controller]")]
+public class LocksController : Controller
+{
+ private readonly IDistributedLockFactory _distributedLockFactory;
+
+ public LocksController(IDistributedLockFactory distributedLockFactory)
+ {
+ _distributedLockFactory = distributedLockFactory;
+ }
+
+ [HttpPost("distributed-locking")]
+ public async Task DistributedLockingOperation(int millisecondsTimeout)
+ {
+ using var distributedLock = _distributedLockFactory.CreateLock("DefaultRedis", "YourKey");
+
+ try
+ {
+ if (await distributedLock.LockAsync(millisecondsTimeout))
+ {
+ // Simulate operation
+ Thread.Sleep(2000);
+ }
+ else
+ {
+ // Proper error
+ }
+ }
+ catch (Exception ex)
+ {
+ // log error
+ throw new Exception("Exception", ex);
+ }
+ finally
+ {
+ // release lock at the end
+ await distributedLock.ReleaseAsync();
+ }
+ }
+
+ [HttpPost("memory-locking")]
+ public async Task MemoryLockingOperation(int millisecondsTimeout)
+ {
+ using var memoryLock = _distributedLockFactory.CreateLock("DefaultInMemory", "YourKey");
+
+ try
+ {
+ if (await memoryLock.LockAsync(millisecondsTimeout))
+ {
+ // Simulate operation
+ Thread.Sleep(2000);
+ }
+ else
+ {
+ // Proper error
+ }
+ }
+ catch (Exception ex)
+ {
+ // log error
+ throw new Exception("Exception", ex);
+ }
+ finally
+ {
+ // release lock at the end
+ await memoryLock.ReleaseAsync();
+ }
+ }
+}
diff --git a/sample/EasyCaching.Demo.Locks/EasyCaching.Demo.Locks.csproj b/sample/EasyCaching.Demo.Locks/EasyCaching.Demo.Locks.csproj
new file mode 100644
index 00000000..dc06abc5
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/EasyCaching.Demo.Locks.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/EasyCaching.Demo.Locks/GlobalUsings.cs b/sample/EasyCaching.Demo.Locks/GlobalUsings.cs
new file mode 100644
index 00000000..838d0c76
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/GlobalUsings.cs
@@ -0,0 +1,4 @@
+global using EasyCaching.Core.Configurations;
+global using EasyCaching.Core.DistributedLock;
+global using Microsoft.AspNetCore.Mvc;
+global using EasyCaching.Redis.DistributedLock;
\ No newline at end of file
diff --git a/sample/EasyCaching.Demo.Locks/Program.cs b/sample/EasyCaching.Demo.Locks/Program.cs
new file mode 100644
index 00000000..c2d00cdb
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/Program.cs
@@ -0,0 +1,53 @@
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+builder.Services.AddEasyCaching(option =>
+{
+ //use memory cache
+ option.UseInMemory()
+ .UseMemoryLock(); // use memory lock
+
+ //use redis cache
+ option.UseRedis(config =>
+ {
+ config.DBConfig.Endpoints.Add(new ServerEndPoint("127.0.0.1", 6379));
+ config.DBConfig.SyncTimeout = 10000;
+ config.DBConfig.AsyncTimeout = 10000;
+ config.SerializerName = "NewtonsoftJson";
+ })
+ .WithJson()//with josn serialization
+ .UseRedisLock(); // use distributed lock
+});
+
+#region How Inject Distributed and Memory lock
+
+// inject to use distributed lock
+builder.Services.AddSingleton();
+
+// inject to use memory lock
+builder.Services.AddSingleton();
+
+#endregion
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/sample/EasyCaching.Demo.Locks/appsettings.Development.json b/sample/EasyCaching.Demo.Locks/appsettings.Development.json
new file mode 100644
index 00000000..0c208ae9
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/sample/EasyCaching.Demo.Locks/appsettings.json b/sample/EasyCaching.Demo.Locks/appsettings.json
new file mode 100644
index 00000000..10f68b8c
--- /dev/null
+++ b/sample/EasyCaching.Demo.Locks/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj
index 9ddaee11..c651637a 100644
--- a/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj
+++ b/src/EasyCaching.CSRedis/EasyCaching.CSRedis.csproj
@@ -32,7 +32,7 @@
-
+
diff --git a/src/EasyCaching.InMemory/Internal/InMemoryCaching.cs b/src/EasyCaching.InMemory/Internal/InMemoryCaching.cs
index 408f7fa8..913ebb10 100644
--- a/src/EasyCaching.InMemory/Internal/InMemoryCaching.cs
+++ b/src/EasyCaching.InMemory/Internal/InMemoryCaching.cs
@@ -49,8 +49,8 @@ public void Clear(string prefix = "")
public int GetCount(string prefix = "")
{
return string.IsNullOrWhiteSpace(prefix)
- ? _memory.Count
- : _memory.Count(x => x.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase));
+ ? _memory.Values.Where(x => x.ExpiresAt > SystemClock.UtcNow).Count()
+ : _memory.Values.Where(x => x.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && x.ExpiresAt > SystemClock.UtcNow).Count();
}
internal void RemoveExpiredKey(string key)
@@ -283,7 +283,7 @@ public int RemoveByPattern(string searchKey, SearchKeyPattern searchPattern)
public IEnumerable GetAllKeys(string prefix)
{
return _memory.Values.Where(x => x.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && x.ExpiresAt > SystemClock.UtcNow)
- .Select(x=> x.Key).ToList();
+ .Select(x => x.Key).ToList();
}
private static bool FilterByPattern(string key, string searchKey, SearchKeyPattern searchKeyPattern)
@@ -314,10 +314,10 @@ public IDictionary> GetAll(IEnumerable keys)
public IDictionary> GetAll(string prefix = "")
{
- var values = string.IsNullOrEmpty(prefix)
- ? _memory.Values.Where(x => x.ExpiresAt > SystemClock.UtcNow)
+ var values = string.IsNullOrEmpty(prefix)
+ ? _memory.Values.Where(x => x.ExpiresAt > SystemClock.UtcNow)
: _memory.Values.Where(x => x.Key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase) && x.ExpiresAt > SystemClock.UtcNow);
-
+
return values.ToDictionary(k => k.Key, v => new CacheValue(v.GetValue(_options.EnableReadDeepClone), true));
}
diff --git a/src/EasyCaching.LiteDB/DefaultLiteDBCachingProvider.cs b/src/EasyCaching.LiteDB/DefaultLiteDBCachingProvider.cs
index 908919a6..bf2e5809 100644
--- a/src/EasyCaching.LiteDB/DefaultLiteDBCachingProvider.cs
+++ b/src/EasyCaching.LiteDB/DefaultLiteDBCachingProvider.cs
@@ -113,7 +113,7 @@ public override bool BaseExists(string cacheKey)
{
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
- var dbResult = _cache.Count(fc => fc.cachekey == cacheKey && fc.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ var dbResult = _cache.Count(fc => fc.cachekey == cacheKey && fc.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
return dbResult > 0;
}
@@ -131,7 +131,7 @@ public override CacheValue BaseGet(string cacheKey, Func dataRetriever,
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration));
- var cacheItem = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ var cacheItem = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
if (cacheItem != null)
{
@@ -164,7 +164,7 @@ public override CacheValue BaseGet(string cacheKey)
{
ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey));
- var cacheItem = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ var cacheItem = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
if (cacheItem != null || _options.CacheNulls)
{
@@ -317,7 +317,7 @@ public override IDictionary> BaseGetAll(IEnumerable lst.Contains(c.cachekey) && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds()).ToList();
+ var list = _cache.Find(c => lst.Contains(c.cachekey) && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds()).ToList();
return GetDict(list);
}
@@ -354,7 +354,7 @@ private IDictionary> GetDict(List list)
public override IDictionary> BaseGetByPrefix(string prefix)
{
ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));
- var list = _cache.Find(c => c.cachekey.StartsWith(prefix) && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds()).ToList();
+ var list = _cache.Find(c => c.cachekey.StartsWith(prefix) && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds()).ToList();
return GetDict(list);
}
@@ -380,11 +380,11 @@ public override int BaseGetCount(string prefix = "")
{
if (string.IsNullOrWhiteSpace(prefix))
{
- return _cache.Count(c => c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ return _cache.Count(c => c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
}
else
{
- return _cache.Count(c => c.cachekey.StartsWith(prefix) && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ return _cache.Count(c => c.cachekey.StartsWith(prefix) && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
}
}
@@ -413,7 +413,7 @@ public override bool BaseTrySet(string cacheKey, T cacheValue, TimeSpan expir
expiration.Add(new TimeSpan(0, 0, addSec));
}
- var r = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.Now.ToUnixTimeSeconds());
+ var r = _cache.FindOne(c => c.cachekey == cacheKey && c.expiration > DateTimeOffset.UtcNow.ToUnixTimeSeconds());
bool result = false;
if (r == null)
{
diff --git a/src/EasyCaching.LiteDB/EasyCaching.LiteDB.csproj b/src/EasyCaching.LiteDB/EasyCaching.LiteDB.csproj
index 2f6f6724..4c3ccb2b 100644
--- a/src/EasyCaching.LiteDB/EasyCaching.LiteDB.csproj
+++ b/src/EasyCaching.LiteDB/EasyCaching.LiteDB.csproj
@@ -35,7 +35,7 @@
-
+
diff --git a/test/EasyCaching.UnitTests/CachingTests/CSRedisCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/CSRedisCachingProviderTest.cs
index c90a2343..8ded8e1a 100644
--- a/test/EasyCaching.UnitTests/CachingTests/CSRedisCachingProviderTest.cs
+++ b/test/EasyCaching.UnitTests/CachingTests/CSRedisCachingProviderTest.cs
@@ -41,6 +41,32 @@ protected override IEasyCachingProvider CreateCachingProvider(Action();
}
+ /*[Fact]
+ public async void Use_Redis6_ACL_Should_Succeed()
+ {
+ IServiceCollection services = new ServiceCollection();
+ services.AddEasyCaching(x =>
+ x.UseCSRedis(options =>
+ {
+ options.DBConfig = new CSRedisDBOptions
+ {
+ ConnectionStrings = new System.Collections.Generic.List
+ {
+ "127.0.0.1:6388,user=user,password=userpwd,defaultDatabase=13,poolsize=10"
+ }
+ };
+ }).UseCSRedisLock().WithJson(EasyCachingConstValue.DefaultCSRedisName));
+ IServiceProvider serviceProvider = services.BuildServiceProvider();
+ var provider = serviceProvider.GetService();
+ var key = Guid.NewGuid().ToString();
+ var value = "value";
+ await provider.SetAsync(key, value, TimeSpan.FromSeconds(20));
+
+ var getValue = await provider.GetAsync(key);
+
+ Assert.Equal(value, getValue?.Value);
+ }*/
+
[Fact]
public void GetDatabase_Should_Succeed()
{
@@ -148,7 +174,7 @@ public CSRedisCachingProviderWithKeyPrefixTest()
config.SerializerName = "json";
}, "WithKeyPrefix");
-
+
x.WithJson("json");
});
@@ -194,7 +220,7 @@ public void RemoveByPrefixTest()
Assert.False(val3.HasValue);
Assert.False(val4.HasValue);
}
-
+
[Theory]
[InlineData("WithKeyPrefix")]
[InlineData("NotKeyPrefix")]
@@ -219,7 +245,7 @@ public void RemoveByKeyPatternTest(string provider)
var val6 = WithKeyPrefix.Get("sky:birds:bar");
var val7 = WithKeyPrefix.Get("sky:birds:test:bar");
var val8 = WithKeyPrefix.Get("akey");
-
+
Assert.True(val1.HasValue);
Assert.True(val2.HasValue);
Assert.True(val3.HasValue);
@@ -231,15 +257,15 @@ public void RemoveByKeyPatternTest(string provider)
// contains
WithKeyPrefix.RemoveByPattern("*:pots:*");
-
+
// postfix
WithKeyPrefix.RemoveByPattern("*foo");
-
+
// prefix
- WithKeyPrefix.RemoveByPattern("sky*");
-
+ WithKeyPrefix.RemoveByPattern("sky*");
+
// exact
- WithKeyPrefix.RemoveByPattern("akey");
+ WithKeyPrefix.RemoveByPattern("akey");
var val9 = WithKeyPrefix.Get("garden:pots:flowers");
var val10 = WithKeyPrefix.Get("garden:pots:flowers:test");
@@ -249,7 +275,7 @@ public void RemoveByKeyPatternTest(string provider)
var val14 = WithKeyPrefix.Get("sky:birds:bar");
var val15 = WithKeyPrefix.Get("sky:birds:test:bar");
var val16 = WithKeyPrefix.Get("akey");
-
+
Assert.False(val9.HasValue);
Assert.False(val10.HasValue);
Assert.True(val11.HasValue);
@@ -259,8 +285,8 @@ public void RemoveByKeyPatternTest(string provider)
Assert.False(val15.HasValue);
Assert.False(val16.HasValue);
}
-
- [Theory]
+
+ [Theory]
[InlineData("WithKeyPrefix")]
[InlineData("NotKeyPrefix")]
public async Task RemoveByKeyPatternAsyncTest(string provider)
@@ -284,7 +310,7 @@ public async Task RemoveByKeyPatternAsyncTest(string provider)
var val6 = WithKeyPrefix.Get("sky:birds:bar");
var val7 = WithKeyPrefix.Get("sky:birds:test:bar");
var val8 = WithKeyPrefix.Get("akey");
-
+
Assert.True(val1.HasValue);
Assert.True(val2.HasValue);
Assert.True(val3.HasValue);
@@ -296,15 +322,15 @@ public async Task RemoveByKeyPatternAsyncTest(string provider)
// contains
await WithKeyPrefix.RemoveByPatternAsync("*:pots:*");
-
+
// postfix
await WithKeyPrefix.RemoveByPatternAsync("*foo");
-
+
// prefix
- await WithKeyPrefix.RemoveByPatternAsync("sky*");
-
+ await WithKeyPrefix.RemoveByPatternAsync("sky*");
+
// exact
- await WithKeyPrefix.RemoveByPatternAsync("akey");
+ await WithKeyPrefix.RemoveByPatternAsync("akey");
var val9 = WithKeyPrefix.Get("garden:pots:flowers");
var val10 = WithKeyPrefix.Get("garden:pots:flowers:test");
@@ -314,7 +340,7 @@ public async Task RemoveByKeyPatternAsyncTest(string provider)
var val14 = WithKeyPrefix.Get("sky:birds:bar");
var val15 = WithKeyPrefix.Get("sky:birds:test:bar");
var val16 = WithKeyPrefix.Get("akey");
-
+
Assert.False(val9.HasValue);
Assert.False(val10.HasValue);
Assert.True(val11.HasValue);
diff --git a/test/EasyCaching.UnitTests/CachingTests/FasterKvCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/FasterKvCachingProviderTest.cs
index d16ecf8c..6543931b 100644
--- a/test/EasyCaching.UnitTests/CachingTests/FasterKvCachingProviderTest.cs
+++ b/test/EasyCaching.UnitTests/CachingTests/FasterKvCachingProviderTest.cs
@@ -77,7 +77,7 @@ protected override void Get_Parallel_Should_Succeed()
}
public override Task GetAllByPrefix_Async_Should_Throw_ArgumentNullException_When_Prefix_IsNullOrWhiteSpace(
- string preifx)
+ string preifx)
{
return Task.CompletedTask;
}
@@ -92,68 +92,71 @@ protected override Task Get_Count_Async_With_Prefix_Should_Succeed()
return Task.CompletedTask;
}
- protected override Task Get_Count_Async_Without_Prefix_Should_Succeed()
+ public override void RemoveByPattern_Should_Succeed()
{
- return Task.CompletedTask;
}
- protected override void Get_Count_With_Prefix_Should_Succeed()
+ public override Task RemoveByPatternAsync_Should_Succeed()
{
+ return Task.CompletedTask;
}
- protected override void Get_Count_Without_Prefix_Should_Succeed()
- {
- }
+ public override Task RemoveByPrefix_Async_Should_Throw_ArgumentNullException_When_Prefix_IsNullOrWhiteSpace(
+ string preifx)
- protected override void GetByPrefix_Should_Succeed()
{
+ return Task.CompletedTask;
}
- protected override void GetByPrefix_With_Not_Existed_Prefix_Should_Return_Empty_Dict()
+ public override void RemoveByPrefix_Should_Throw_ArgumentNullException_When_CacheKey_IsNullOrWhiteSpace(
+ string prefix)
{
}
- protected override Task GetByPrefixAsync_Should_Succeed()
+ protected override Task Get_Count_Async_Without_Prefix_Should_Succeed()
{
return Task.CompletedTask;
}
- protected override Task GetByPrefixAsync_With_Not_Existed_Prefix_Should_Return_Empty_Dict()
+
+ protected override void Get_Count_With_Prefix_Should_Succeed()
{
- return Task.CompletedTask;
}
- protected override Task GetExpiration_Async_Should_Succeed()
+ protected override void Get_Count_Without_Prefix_Should_Succeed()
{
- return Task.CompletedTask;
}
- protected override void GetExpiration_Should_Succeed()
+ protected override void GetByPrefix_Should_Succeed()
{
}
- public override void RemoveByPattern_Should_Succeed()
+ protected override void GetByPrefix_With_Not_Existed_Prefix_Should_Return_Empty_Dict()
{
}
- public override Task RemoveByPatternAsync_Should_Succeed()
+ protected override Task GetByPrefixAsync_Should_Succeed()
{
return Task.CompletedTask;
}
- public override Task RemoveByPrefix_Async_Should_Throw_ArgumentNullException_When_Prefix_IsNullOrWhiteSpace(
- string preifx)
+
+ protected override Task GetByPrefixAsync_With_Not_Existed_Prefix_Should_Return_Empty_Dict()
{
return Task.CompletedTask;
}
- protected override void RemoveByPrefix_Should_Succeed()
+ protected override Task GetExpiration_Async_Should_Succeed()
{
+ return Task.CompletedTask;
}
- public override void RemoveByPrefix_Should_Throw_ArgumentNullException_When_CacheKey_IsNullOrWhiteSpace(
- string prefix)
+ protected override void GetExpiration_Should_Succeed()
+ {
+ }
+
+ protected override void RemoveByPrefix_Should_Succeed()
{
}
diff --git a/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs b/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs
index 899b2589..0795a6ea 100644
--- a/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs
+++ b/test/EasyCaching.UnitTests/CachingTests/MemoryCachingProviderTest.cs
@@ -155,6 +155,21 @@ public void Evicted_Event_Should_Trigger_When_GetExpiredItems()
_provider.Get(key1);
System.Threading.Thread.Sleep(500);
}
+
+ [Fact]
+ public async void Issues497_GetCountAsync_Check_Expires_Test()
+ {
+ for (int i = 0; i < 9; i++)
+ {
+ await _provider.SetAsync(Guid.NewGuid().ToString(), $"value-{i}", TimeSpan.FromSeconds(5));
+ }
+
+ Assert.Equal(9, await _provider.GetCountAsync());
+
+ await Task.Delay(5000);
+
+ Assert.Equal(0, await _provider.GetCountAsync());
+ }
}
public class MemoryCachingProviderWithFactoryTest : BaseCachingProviderWithFactoryTest
diff --git a/test/EasyCaching.UnitTests/SerializerTests/MemoryPackSerializerTest.cs b/test/EasyCaching.UnitTests/SerializerTests/MemoryPackSerializerTest.cs
index 32cbbfb9..6f65205e 100644
--- a/test/EasyCaching.UnitTests/SerializerTests/MemoryPackSerializerTest.cs
+++ b/test/EasyCaching.UnitTests/SerializerTests/MemoryPackSerializerTest.cs
@@ -14,6 +14,7 @@ public MemoryPackSerializerTest()
}
//This should be overrided becuse it is not supported by memory-pack
+ [Fact]
public override void DeserializeObject_should_Succeed()
{
Person input = new("test", "test1");