diff --git a/.editorconfig b/.editorconfig index e58aad46..1e70922a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -130,6 +130,25 @@ csharp_space_between_parentheses = false csharp_space_between_square_brackets = false # Xml project files + +# CA1305: Specify IFormatProvider +dotnet_diagnostic.CA1305.severity = suggestion + +# CA1303: Do not pass literals as localized parameters +dotnet_diagnostic.CA1303.severity = suggestion + +# CS8602: Dereference of a possibly null reference. +dotnet_diagnostic.CS8602.severity = error + +# CA1716: Identifiers should not match keywords +dotnet_diagnostic.CA1716.severity = silent + +# CA1825: Avoid zero-length array allocations. +dotnet_diagnostic.CA1825.severity = silent + +# CA1028: Enum Storage should be Int32 +dotnet_diagnostic.CA1028.severity = silent + [*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] indent_size = 2 @@ -143,4 +162,4 @@ indent_size = 2 # Shell scripts [*.sh] -end_of_line = lf \ No newline at end of file +end_of_line = lf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..76e3c49b --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: MichaCo diff --git a/Benchmarks.md b/Benchmarks.md index c626dca1..a7321c58 100644 --- a/Benchmarks.md +++ b/Benchmarks.md @@ -1,6 +1,8 @@ ## Benchmarks +TODO: needs update + Benchmarks have been implemented with [BenchmarkDotNet](https://github.com/PerfDotNet/BenchmarkDotNet). All CacheManager instances used in the benchmarks have only one cache handle configured, either the Dictionary, System.Runtime or Redis handle. diff --git a/CacheManager.sln b/CacheManager.sln index 8681186a..292ee09e 100644 --- a/CacheManager.sln +++ b/CacheManager.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.13 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35122.118 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{58CC885F-40A7-4C82-990D-3F36AAA088A7}" EndProject @@ -10,7 +10,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig Benchmarks.md = Benchmarks.md tools\CodeAnalysis.ruleset = tools\CodeAnalysis.ruleset - docfx.json = docfx.json README.md = README.md tools\stylecop.json = tools\stylecop.json EndProjectSection @@ -41,12 +40,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.SystemRuntimeC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.StackExchange.Redis", "src\CacheManager.StackExchange.Redis\CacheManager.StackExchange.Redis.csproj", "{BA03975E-39CD-4318-8ED3-239AA399DC87}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Couchbase", "src\CacheManager.Couchbase\CacheManager.Couchbase.csproj", "{6436C729-A28B-4D90-B3B8-7ED003341199}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Web", "src\CacheManager.Web\CacheManager.Web.csproj", "{4FBE8026-2FAE-462C-9446-33B49CA5A25D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Config.Tests", "test\CacheManager.Config.Tests\CacheManager.Config.Tests.csproj", "{35A16A79-63DE-418E-AF5E-6865E5718008}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Tests", "test\CacheManager.Tests\CacheManager.Tests.csproj", "{EEED5086-976C-4063-A61D-D5FAE7652758}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Examples", "samples\CacheManager.Examples\CacheManager.Examples.csproj", "{8F8E0F73-F11A-4F9A-91F5-9C8E798752D9}" @@ -55,25 +48,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Serialization. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Microsoft.Extensions.Configuration", "src\CacheManager.Microsoft.Extensions.Configuration\CacheManager.Microsoft.Extensions.Configuration.csproj", "{D68182DA-FB4D-45A9-9A09-AD07A45FE5FF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Microsoft.Extensions.Logging", "src\CacheManager.Microsoft.Extensions.Logging\CacheManager.Microsoft.Extensions.Logging.csproj", "{97C864BD-D4C7-4DF6-92D0-4D76A89F6706}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Memcached", "src\CacheManager.Memcached\CacheManager.Memcached.csproj", "{5E5AFEF6-C13E-4D78-87D6-50407002A9B1}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.MSConfiguration.TypeLoad.Tests", "test\CacheManager.MSConfiguration.TypeLoad.Tests\CacheManager.MSConfiguration.TypeLoad.Tests.csproj", "{360D0B25-F9EB-4553-92DC-FB0FD24EF344}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Microsoft.Extensions.Caching.Memory", "src\CacheManager.Microsoft.Extensions.Caching.Memory\CacheManager.Microsoft.Extensions.Caching.Memory.csproj", "{48DD6E04-0CFD-4FB4-A178-749B0FBFBA36}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Serialization.ProtoBuf", "src\CacheManager.Serialization.ProtoBuf\CacheManager.Serialization.ProtoBuf.csproj", "{85CD8BC7-3E72-422E-AF91-6FDF2133E155}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspnetCore.WebApp", "samples\AspnetCore.WebApp\AspnetCore.WebApp.csproj", "{CB9C05BF-E567-412F-B3C8-C85289E60DBC}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Serialization.Bond", "src\CacheManager.Serialization.Bond\CacheManager.Serialization.Bond.csproj", "{2FB30F61-B2E7-43AC-80AF-C45218F1D4BA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Benchmarks", "test\CacheManager.Benchmarks\CacheManager.Benchmarks.csproj", "{987C4CD7-D162-4635-8C50-214A25494676}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{CB286D98-C974-4266-B8F2-1F9DE8B2B0EC}" ProjectSection(SolutionItems) = preProject - appveyor.yml = appveyor.yml + azure-pipelines-ci.yml = azure-pipelines-ci.yml tools\common.props = tools\common.props NuGet.Config = NuGet.Config tools\version.props = tools\version.props @@ -86,9 +71,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "schema", "schema", "{DB13A4 tools\RedisCfg.xsd = tools\RedisCfg.xsd EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CacheManager.Events.Tests", "test\CacheManager.Events.Tests\CacheManager.Events.Tests.csproj", "{AA4A2053-1ECD-4331-B805-BF8062B04CFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Serialization.DataContract", "src\CacheManager.Serialization.DataContract\CacheManager.Serialization.DataContract.csproj", "{38709D89-E43C-44E3-A865-39BBEBF28D98}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{81E202D2-BEB7-4BAF-B7BE-53D628120F8A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Benchmarks", "benchmarks\CacheManager.Benchmarks\CacheManager.Benchmarks.csproj", "{8B8E87C2-5FD1-4D17-901A-53713566A84D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Examples.Configuration", "samples\CacheManager.Examples.Configuration\CacheManager.Examples.Configuration.csproj", "{29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Config.Tests", "benchmarks\CacheManager.Config.Tests\CacheManager.Config.Tests.csproj", "{C7745B11-4A2E-4278-9F1E-774AC7153CD2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CacheManager.Events.Tests", "benchmarks\CacheManager.Events.Tests\CacheManager.Events.Tests.csproj", "{2DF724CF-E4F3-4663-880C-5359F2EAEA1A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "samples\AspNetCore\Web.csproj", "{1291DAA1-25C8-4648-9216-BF338EE5C2DD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -108,18 +101,6 @@ Global {BA03975E-39CD-4318-8ED3-239AA399DC87}.Debug|Any CPU.Build.0 = Debug|Any CPU {BA03975E-39CD-4318-8ED3-239AA399DC87}.Release|Any CPU.ActiveCfg = Release|Any CPU {BA03975E-39CD-4318-8ED3-239AA399DC87}.Release|Any CPU.Build.0 = Release|Any CPU - {6436C729-A28B-4D90-B3B8-7ED003341199}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6436C729-A28B-4D90-B3B8-7ED003341199}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6436C729-A28B-4D90-B3B8-7ED003341199}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6436C729-A28B-4D90-B3B8-7ED003341199}.Release|Any CPU.Build.0 = Release|Any CPU - {4FBE8026-2FAE-462C-9446-33B49CA5A25D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FBE8026-2FAE-462C-9446-33B49CA5A25D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FBE8026-2FAE-462C-9446-33B49CA5A25D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FBE8026-2FAE-462C-9446-33B49CA5A25D}.Release|Any CPU.Build.0 = Release|Any CPU - {35A16A79-63DE-418E-AF5E-6865E5718008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {35A16A79-63DE-418E-AF5E-6865E5718008}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35A16A79-63DE-418E-AF5E-6865E5718008}.Release|Any CPU.ActiveCfg = Release|Any CPU - {35A16A79-63DE-418E-AF5E-6865E5718008}.Release|Any CPU.Build.0 = Release|Any CPU {EEED5086-976C-4063-A61D-D5FAE7652758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EEED5086-976C-4063-A61D-D5FAE7652758}.Debug|Any CPU.Build.0 = Debug|Any CPU {EEED5086-976C-4063-A61D-D5FAE7652758}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -136,14 +117,6 @@ Global {D68182DA-FB4D-45A9-9A09-AD07A45FE5FF}.Debug|Any CPU.Build.0 = Debug|Any CPU {D68182DA-FB4D-45A9-9A09-AD07A45FE5FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {D68182DA-FB4D-45A9-9A09-AD07A45FE5FF}.Release|Any CPU.Build.0 = Release|Any CPU - {97C864BD-D4C7-4DF6-92D0-4D76A89F6706}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97C864BD-D4C7-4DF6-92D0-4D76A89F6706}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97C864BD-D4C7-4DF6-92D0-4D76A89F6706}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97C864BD-D4C7-4DF6-92D0-4D76A89F6706}.Release|Any CPU.Build.0 = Release|Any CPU - {5E5AFEF6-C13E-4D78-87D6-50407002A9B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5E5AFEF6-C13E-4D78-87D6-50407002A9B1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5E5AFEF6-C13E-4D78-87D6-50407002A9B1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5E5AFEF6-C13E-4D78-87D6-50407002A9B1}.Release|Any CPU.Build.0 = Release|Any CPU {360D0B25-F9EB-4553-92DC-FB0FD24EF344}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {360D0B25-F9EB-4553-92DC-FB0FD24EF344}.Debug|Any CPU.Build.0 = Debug|Any CPU {360D0B25-F9EB-4553-92DC-FB0FD24EF344}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -156,26 +129,30 @@ Global {85CD8BC7-3E72-422E-AF91-6FDF2133E155}.Debug|Any CPU.Build.0 = Debug|Any CPU {85CD8BC7-3E72-422E-AF91-6FDF2133E155}.Release|Any CPU.ActiveCfg = Release|Any CPU {85CD8BC7-3E72-422E-AF91-6FDF2133E155}.Release|Any CPU.Build.0 = Release|Any CPU - {CB9C05BF-E567-412F-B3C8-C85289E60DBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB9C05BF-E567-412F-B3C8-C85289E60DBC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB9C05BF-E567-412F-B3C8-C85289E60DBC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB9C05BF-E567-412F-B3C8-C85289E60DBC}.Release|Any CPU.Build.0 = Release|Any CPU {2FB30F61-B2E7-43AC-80AF-C45218F1D4BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2FB30F61-B2E7-43AC-80AF-C45218F1D4BA}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FB30F61-B2E7-43AC-80AF-C45218F1D4BA}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FB30F61-B2E7-43AC-80AF-C45218F1D4BA}.Release|Any CPU.Build.0 = Release|Any CPU - {987C4CD7-D162-4635-8C50-214A25494676}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {987C4CD7-D162-4635-8C50-214A25494676}.Debug|Any CPU.Build.0 = Debug|Any CPU - {987C4CD7-D162-4635-8C50-214A25494676}.Release|Any CPU.ActiveCfg = Release|Any CPU - {987C4CD7-D162-4635-8C50-214A25494676}.Release|Any CPU.Build.0 = Release|Any CPU - {AA4A2053-1ECD-4331-B805-BF8062B04CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AA4A2053-1ECD-4331-B805-BF8062B04CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AA4A2053-1ECD-4331-B805-BF8062B04CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AA4A2053-1ECD-4331-B805-BF8062B04CFC}.Release|Any CPU.Build.0 = Release|Any CPU - {29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB}.Release|Any CPU.Build.0 = Release|Any CPU + {38709D89-E43C-44E3-A865-39BBEBF28D98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38709D89-E43C-44E3-A865-39BBEBF28D98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38709D89-E43C-44E3-A865-39BBEBF28D98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38709D89-E43C-44E3-A865-39BBEBF28D98}.Release|Any CPU.Build.0 = Release|Any CPU + {8B8E87C2-5FD1-4D17-901A-53713566A84D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B8E87C2-5FD1-4D17-901A-53713566A84D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B8E87C2-5FD1-4D17-901A-53713566A84D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B8E87C2-5FD1-4D17-901A-53713566A84D}.Release|Any CPU.Build.0 = Release|Any CPU + {C7745B11-4A2E-4278-9F1E-774AC7153CD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7745B11-4A2E-4278-9F1E-774AC7153CD2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7745B11-4A2E-4278-9F1E-774AC7153CD2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7745B11-4A2E-4278-9F1E-774AC7153CD2}.Release|Any CPU.Build.0 = Release|Any CPU + {2DF724CF-E4F3-4663-880C-5359F2EAEA1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DF724CF-E4F3-4663-880C-5359F2EAEA1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DF724CF-E4F3-4663-880C-5359F2EAEA1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DF724CF-E4F3-4663-880C-5359F2EAEA1A}.Release|Any CPU.Build.0 = Release|Any CPU + {1291DAA1-25C8-4648-9216-BF338EE5C2DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1291DAA1-25C8-4648-9216-BF338EE5C2DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1291DAA1-25C8-4648-9216-BF338EE5C2DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1291DAA1-25C8-4648-9216-BF338EE5C2DD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -185,25 +162,24 @@ Global {C9B4E53B-15FC-42AF-9107-0C2E52E8680B} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} {49A1A508-1A92-4F6A-8654-B0E71C07BD53} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} {BA03975E-39CD-4318-8ED3-239AA399DC87} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {6436C729-A28B-4D90-B3B8-7ED003341199} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {4FBE8026-2FAE-462C-9446-33B49CA5A25D} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {35A16A79-63DE-418E-AF5E-6865E5718008} = {C013E552-43F5-4496-BE29-DB401C3334BB} {EEED5086-976C-4063-A61D-D5FAE7652758} = {C013E552-43F5-4496-BE29-DB401C3334BB} {8F8E0F73-F11A-4F9A-91F5-9C8E798752D9} = {C23C189C-3AFC-45D6-8E32-9B5E190BBA20} {3F3A3386-DFED-489C-A97D-541D43AA6C12} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} {D68182DA-FB4D-45A9-9A09-AD07A45FE5FF} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {97C864BD-D4C7-4DF6-92D0-4D76A89F6706} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {5E5AFEF6-C13E-4D78-87D6-50407002A9B1} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} {360D0B25-F9EB-4553-92DC-FB0FD24EF344} = {C013E552-43F5-4496-BE29-DB401C3334BB} {48DD6E04-0CFD-4FB4-A178-749B0FBFBA36} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} {85CD8BC7-3E72-422E-AF91-6FDF2133E155} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {CB9C05BF-E567-412F-B3C8-C85289E60DBC} = {C23C189C-3AFC-45D6-8E32-9B5E190BBA20} {2FB30F61-B2E7-43AC-80AF-C45218F1D4BA} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} - {987C4CD7-D162-4635-8C50-214A25494676} = {C013E552-43F5-4496-BE29-DB401C3334BB} {CB286D98-C974-4266-B8F2-1F9DE8B2B0EC} = {D83D3737-3BD4-4AEE-8C42-CDED9410DB79} {DB13A410-EAF1-4966-BA56-FC73BAC7CF3D} = {D83D3737-3BD4-4AEE-8C42-CDED9410DB79} - {AA4A2053-1ECD-4331-B805-BF8062B04CFC} = {C013E552-43F5-4496-BE29-DB401C3334BB} - {29E6BC78-BD1E-4E83-AAC6-D3D21DA883AB} = {C23C189C-3AFC-45D6-8E32-9B5E190BBA20} + {38709D89-E43C-44E3-A865-39BBEBF28D98} = {58CC885F-40A7-4C82-990D-3F36AAA088A7} + {8B8E87C2-5FD1-4D17-901A-53713566A84D} = {81E202D2-BEB7-4BAF-B7BE-53D628120F8A} + {C7745B11-4A2E-4278-9F1E-774AC7153CD2} = {81E202D2-BEB7-4BAF-B7BE-53D628120F8A} + {2DF724CF-E4F3-4663-880C-5359F2EAEA1A} = {81E202D2-BEB7-4BAF-B7BE-53D628120F8A} + {1291DAA1-25C8-4648-9216-BF338EE5C2DD} = {C23C189C-3AFC-45D6-8E32-9B5E190BBA20} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {55AD6484-7AB9-4CE1-B604-3410DA3876C0} EndGlobalSection GlobalSection(Performance) = preSolution HasPerformanceSessions = true diff --git a/LICENSE b/LICENSE index e06d2081..261eeb9e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +178,7 @@ Apache License APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +186,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -199,4 +199,3 @@ Apache License WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - diff --git a/NuGet.Config b/NuGet.Config index 37fbe07c..39983a7e 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,8 +1,6 @@  - - \ No newline at end of file + diff --git a/README.md b/README.md index c7d45467..87cd6fce 100644 --- a/README.md +++ b/README.md @@ -8,29 +8,41 @@ The developer can opt-in to those features only if needed. ## Build Status -Build Server | Status +Branch | Status --- | :---: -Windows, MSBuild | [![Build status](https://ci.appveyor.com/api/projects/status/mv4u7eg5vq6ty5s4?svg=true)](https://ci.appveyor.com/project/MichaCo/cachemanager-ak9g3) -Linux, Mono | - +Dev | [![Build Status](https://dev.azure.com/michaco/CacheManager/_apis/build/status%2FMichaCo.CacheManager?branchName=dev)](https://dev.azure.com/michaco/CacheManager/_build/latest?definitionId=3&branchName=dev) +Master | [![Build Status](https://dev.azure.com/michaco/CacheManager/_apis/build/status%2FMichaCo.CacheManager?branchName=master)](https://dev.azure.com/michaco/CacheManager/_build/latest?definitionId=3&branchName=master) ## CacheManager Nuget Packages -| Package Name | .Net 4.0 | .Net 4.5 | .NET Standard -|--------------| :-------: | :-------: | :-------: -| [CacheManager.Core][Core.nuget] | x | x | 1.2 -| [CacheManager.StackExchange.Redis][Redis.nuget] | - | x | 1.5 -| [CacheManager.SystemRuntimeCaching][SystemRuntimeCaching.nuget] | x | x | - -| [CacheManager.Microsoft.Extensions.Caching.Memory][MSCache.nuget] | - | x | 1.3 -| [CacheManager.Microsoft.Extensions.Configuration][Configuration.nuget] | - | x | 1.2 -| [CacheManager.Microsoft.Extensions.Logging][Logging.nuget] | - | x | 1.2 -| [CacheManager.Serialization.Bond][Bond.nuget] | x | x | 1.2 -| [CacheManager.Serialization.Json][Json.nuget] | x | x | 1.2 -| [CacheManager.Serialization.ProtoBuf][ProtoBuf.nuget] | x | x | 1.3 -| [CacheManager.Web][Web.nuget] | - | x | - -| [CacheManager.Memcached][Memcached.nuget] | x | x | - -| [CacheManager.Couchbase][Couchbase.nuget] | - | x | 1.5 - -### Beta Packages +| Package Name | FullFramework | .NET Standard | net8.0 | +| -------------- | :-------: | :-------: | :-------: | +| [CacheManager.Core][Core.nuget] | 4.7.2 | 2.0 | net8.0 | +| [CacheManager.Microsoft.Extensions.Caching.Memory][MSCache.nuget] | - | 2.0 | net8.0 | +| [CacheManager.Microsoft.Extensions.Configuration][Configuration.nuget] | - | 2.0 | net8.0 | +| [CacheManager.Serialization.Bond][Bond.nuget] | - | 2.0 | net8.0 | +| [CacheManager.Serialization.DataContract][DataContract.nuget] | - | 2.0 | net8.0 | +| [CacheManager.Serialization.Json][Json.nuget] | - | 2.0 | net8.0 | +| [CacheManager.Serialization.ProtoBuf][ProtoBuf.nuget] | - | 2.0 | net8.0 | +| [CacheManager.StackExchange.Redis][Redis.nuget] | 4.7.2 | 2.0 | net8.0 | +| [CacheManager.SystemRuntimeCaching][SystemRuntimeCaching.nuget] | 4.7.2 | 2.0 | net8.0 | + +## Version 2.0 Breaking Changes + +* CacheManager.Microsoft.Extensions.Logging is not a separated package anymore. Logging is now part of the Core package. +* CacheManager.Memcached is not supported anymore +* CacheManager.Couchbase is not supported anymore +* CacheManager.Web is not supported anymore +* PerformanceCounters are not available for now + +### Testing with Microsoft.Garnet + +For testing and benchmarking, this project is now using Microsoft.Garnet, which allows to create a Redis server which runs in process and is easy to setup. +This has some limitations though and before you use Microsoft.Garnet in production, be aware that for example key space notifications are not supported yet. + +See https://github.com/microsoft/garnet for details. + +## Beta Packages Beta versions of the CacheManager packages are getting pushed to https://www.myget.org/gallery/cachemanager on each build. Add the following feed, if you want to play with the not yet released bits: @@ -77,9 +89,6 @@ See [benchmarks results](https://github.com/MichaCo/CacheManager/blob/dev/Benchm * **MemoryCache** (System.Runtime.Caching) * **MemoryCache** based on Microsoft.Extensions.Caching.Memory * **Redis** using [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis) - * **Memcached** using [Enyim.Memcached](https://github.com/enyim/EnyimMemcached) - * **Couchbase** using [Couchbase.Net.Client v2](https://github.com/couchbase/couchbase-net-client) - * **System.Web.Caching** based (included in the Web package) * **Serialization** can now be configured. Serialization is only needed in distributed caches. If no additional serialization package is installed and configured, Binary serialization will be used (if available) The following are the currently available serialization options: @@ -87,14 +96,12 @@ The following are the currently available serialization options: * **Json** based on the popular Newtonsoft.Json library * **Json** with Gzip compression * **Bond** based on Microsoft.Bond supporting all three available variants + * **DataContract** based on System.Runtime.Serialization library supporting binary, Json & Json with Gzip compression * **Protocol Buffer** Google's protobuf. The package uses Mark's [protobuf-net](https://github.com/mgravell/protobuf-net) implementation. * **Update values with lock or transaction** for distributed caches. The interfaced provides a simple update method which internally ensures you work with the latest version. And CacheManager handles version conflicts for you. -* **Logging** CacheManager comes with an extensible logging API. - * All standard cache operations are logged - * Based on log levels more or less information will be logged (try Trace and Debug) - * Current concrete implementation is based on the ASP.NET Core logging. Other implementation of CacheManager's ILoggerFactory might follow. +* **Logging** using Microsoft.Extensions.Logging. * **Strongly typed** cache interface. * **Multiple layers** By having multiple cache handles managed by CacheManager, you can easily implement layered caches. For example, an in process cache in front of your distributed cache, to make read access faster. @@ -112,16 +119,13 @@ The following are the supported expiration modes: * **Cache Regions**: Even if some cache systems do not support or implement cache regions, the CacheManager implements the mechanism. This can be used to for example group elements and remove all of them at once. * **Statistics**: Counters for all kind of cache actions. -* **Performance Counters**: To be able to inspect certain numbers with `perfmon`, CacheManager supports performance counters per instance of the manager and per cache handle. * **Event System**: CacheManager triggers events for common cache actions: OnGet, OnAdd, OnPut, OnRemove, OnClear, OnClearRegion * Events also get triggered by the backplane (if enabled) when multiple instances are sharing the same cache. * New `OnRemoveByHandle` events triggered by actual expiration or memory pressure eviction by the cache vendor * Events also get triggered through the backplane and via Redis keyspace events (if configured) -* **System.Web.OutputCache** implementation to use CacheManager as OutputCache provider which makes the OutputCache extremely flexible, for example by using a distributed cache like Redis across many web servers. * **Cache clients synchronization** * Implemented with the Redis pub/sub feature -* Supports .Net 4.0, .Net 4.5, and can be used in cross platform projects with the new **.NET Core** runtime [releases]: https://github.com/MichaCo/CacheManager/releases [Core.nuget]: https://www.nuget.org/packages/CacheManager.Core @@ -152,3 +156,4 @@ OnGet, OnAdd, OnPut, OnRemove, OnClear, OnClearRegion [MSCache.nuget]: https://www.nuget.org/packages/CacheManager.Microsoft.Extensions.Caching.Memory [ProtoBuf.nuget]: https://www.nuget.org/packages/CacheManager.Serialization.ProtoBuf [Bond.nuget]: https://www.nuget.org/packages/CacheManager.Serialization.Bond +[DataContract.nuget]: https://www.nuget.org diff --git a/_disable_.travis.yml b/_disable_.travis.yml deleted file mode 100644 index 96ab1d45..00000000 --- a/_disable_.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: csharp -sudo: required -dist: trusty -os: - - linux - - osx -addons: - apt: - packages: - - gettext - - libcurl4-openssl-dev - - libicu-dev - - libssl-dev - - libunwind8 - - zlib1g -mono: - - 4.0.5 -osx_image: xcode7.1 -services: - - redis-server -before_install: - - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install icu4c; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi -env: - - KOREBUILD_TEST_SKIPMONO=1 -script: - - chmod a+x ./build.sh - - ./build.sh --quiet verify - \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 2a6e757e..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: 1.1.0-beta-{build} -image: Visual Studio 2017 -configuration: Release -clone_folder: C:\projects\CacheManager\ -init: -- cmd: if "%APPVEYOR_REPO_BRANCH%" == "master" (set VersionSuffix=) else (set VersionSuffix=beta) -environment: - BuildNumber: $(APPVEYOR_BUILD_NUMBER) -install: -- ps: C:\projects\CacheManager\tools\redis\install-service.cmd -before_build: -- cmd: dotnet restore -build: - project: CacheManager.sln - parallel: true - verbosity: minimal -after_build: -- cmd: "dotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Core \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Couchbase \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Memcached \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Microsoft.Extensions.Caching.Memory \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Microsoft.Extensions.Configuration \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Microsoft.Extensions.Logging \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Serialization.Json \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Serialization.ProtoBuf \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.StackExchange.Redis \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.SystemRuntimeCaching \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Web \ndotnet pack -o C:\\projects\\CacheManager\\artifacts -c Release src\\CacheManager.Serialization.Bond" -test_script: -- cmd: >- - dotnet test test\CacheManager.Tests\CacheManager.Tests.csproj -c Release --no-build --filter "category!=Unreliable&category!=memcached&category!=Redis" - - dotnet test test\CacheManager.MSConfiguration.TypeLoad.Tests\CacheManager.MSConfiguration.TypeLoad.Tests.csproj --no-build -c Release -artifacts: -- path: artifacts\*.nupkg - name: nugets -deploy: -- provider: NuGet - server: https://www.myget.org/F/cachemanager/api/v2/package - symbol_server: https://www.myget.org/F/cachemanager/api/v2/package - artifact: nugets \ No newline at end of file diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml new file mode 100644 index 00000000..e973f0d6 --- /dev/null +++ b/azure-pipelines-ci.yml @@ -0,0 +1,68 @@ +name: '$(Date:yyyyMMdd)$(Rev:.r)' + +trigger: +- dev +- master + +pr: + autoCancel: false + branches: + include: + - '*' + +# pool: +# vmImage: 'windows-latest' + +variables: + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + ${{ if not(eq(variables['Build.SourceBranch'], 'refs/heads/master')) }}: + versionSuffix: 'beta-$(Build.BuildNumber)' + ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: + versionSuffix: '' + +jobs: +- job: Windows + displayName: 'Build & Test' + pool: + vmImage: 'windows-latest' + + steps: + - task: DotNetCoreCLI@2 + displayName: 'dotnet build' + inputs: + command: 'build' + projects: | + CacheManager.sln + arguments: '-c Release' + name: 'Build' + - task: DotNetCoreCLI@2 + displayName: "dotnet test" + inputs: + command: 'test' + projects: 'test/**/*.csproj' + publishTestResults: true + arguments: '-c Release --no-build --no-restore --filter category!=Unreliable' + - script: 'dotnet pack src\CacheManager.Core\CacheManager.Core.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack Core' + - script: 'dotnet pack src\CacheManager.Microsoft.Extensions.Caching.Memory\CacheManager.Microsoft.Extensions.Caching.Memory.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Microsoft.Extensions.Caching.Memory' + - script: 'dotnet pack src\CacheManager.Microsoft.Extensions.Configuration\CacheManager.Microsoft.Extensions.Configuration.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Microsoft.Extensions.Configuration' + - script: 'dotnet pack src\CacheManager.Serialization.Bond\CacheManager.Serialization.Bond.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Serialization.Bond' + - script: 'dotnet pack src\CacheManager.Serialization.DataContract\CacheManager.Serialization.DataContract.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Serialization.DataContract' + - script: 'dotnet pack src\CacheManager.Serialization.Json\CacheManager.Serialization.Json.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Serialization.Json' + - script: 'dotnet pack src\CacheManager.Serialization.ProtoBuf\CacheManager.Serialization.ProtoBuf.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.Serialization.ProtoBuf' + - script: 'dotnet pack src\CacheManager.StackExchange.Redis\CacheManager.StackExchange.Redis.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.StackExchange.Redis' + - script: 'dotnet pack src\CacheManager.SystemRuntimeCaching\CacheManager.SystemRuntimeCaching.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)' + displayName: 'dotnet pack CacheManager.SystemRuntimeCaching' + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifacts' + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: 'cachemanager' diff --git a/benchmarks/CacheManager.Benchmarks/.gitignore b/benchmarks/CacheManager.Benchmarks/.gitignore new file mode 100644 index 00000000..91a99327 --- /dev/null +++ b/benchmarks/CacheManager.Benchmarks/.gitignore @@ -0,0 +1 @@ +BenchmarkDotNet.Artifacts/ diff --git a/test/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs b/benchmarks/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs similarity index 97% rename from test/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs index 9ddefcc5..f6694873 100644 --- a/test/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/BackplaneMessageBenchmark.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using BenchmarkDotNet.Attributes; @@ -7,6 +8,7 @@ namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public class BackplaneMessageBenchmarkMultiple { private static byte[] _ownderBytes = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()); @@ -49,6 +51,7 @@ public void DeserializeMany() } } + [ExcludeFromCodeCoverage] public class BackplaneMessageBenchmark { private static byte[] _ownderBytes = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()); @@ -128,4 +131,4 @@ public void DeserializeRemove() var msg = BackplaneMessage.Deserialize(_rawSingleRemove).ToArray(); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs b/benchmarks/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs similarity index 81% rename from test/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs index b165682c..11d655db 100644 --- a/test/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/BaseCacheManagerBenchmark.cs @@ -1,38 +1,28 @@ using System; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using BenchmarkDotNet.Attributes; using CacheManager.Core; -using Enyim.Caching; -using Enyim.Caching.Configuration; namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public abstract class BaseCacheBenchmark { private static ICacheManagerConfiguration BaseConfig - => new ConfigurationBuilder() - .WithMaxRetries(10) - .WithRetryTimeout(500) - .WithJsonSerializer() - .WithUpdateMode(CacheUpdateMode.Up) - .Build(); - - private static IMemcachedClientConfiguration MemcachedConfig - { - get - { - var cfg = new MemcachedClientConfiguration(); - cfg.AddServer("localhost", 11211); - return cfg; - } - } + => new CacheConfigurationBuilder() + .WithMaxRetries(10) + .WithRetryTimeout(500) + .WithJsonSerializer() + .WithUpdateMode(CacheUpdateMode.Up) + .Build(); + protected ICacheManager DictionaryCache = new BaseCacheManager(BaseConfig.Builder.WithDictionaryHandle().Build()); protected ICacheManager RuntimeCache = new BaseCacheManager(BaseConfig.Builder.WithSystemRuntimeCacheHandle().Build()); protected ICacheManager RedisCache = new BaseCacheManager( - BaseConfig + BaseConfig .Builder .WithRedisConfiguration("redisKey", "localhost:6379,allowAdmin=true") .WithRedisCacheHandle("redisKey") @@ -40,18 +30,13 @@ private static IMemcachedClientConfiguration MemcachedConfig protected ICacheManager MsMemoryCache = new BaseCacheManager(BaseConfig.Builder.WithMicrosoftMemoryCacheHandle().Build()); - protected ICacheManager MemcachedCache = - new BaseCacheManager(BaseConfig.Builder - .WithMemcachedCacheHandle(new MemcachedClient(MemcachedConfig)).Build()); - - [Setup] + [GlobalSetup] public void Setup() { DictionaryCache.Clear(); RuntimeCache.Clear(); RedisCache.Clear(); MsMemoryCache.Clear(); - MemcachedCache.Clear(); SetupBench(); } @@ -79,12 +64,6 @@ public void Redis() Excecute(RedisCache); } - [Benchmark] - public void Memcached() - { - Excecute(MemcachedCache); - } - protected abstract void Excecute(ICacheManager cache); protected virtual void SetupBench() @@ -94,6 +73,7 @@ protected virtual void SetupBench() #region add + [ExcludeFromCodeCoverage] public class AddSingleBenchmark : BaseCacheBenchmark { private string _key = Guid.NewGuid().ToString(); @@ -107,6 +87,7 @@ protected override void Excecute(ICacheManager cache) } } + [ExcludeFromCodeCoverage] public class AddWithRegionSingleBenchmark : BaseCacheBenchmark { private string _key = Guid.NewGuid().ToString(); @@ -124,6 +105,7 @@ protected override void Excecute(ICacheManager cache) #region put + [ExcludeFromCodeCoverage] public class PutSingleBenchmark : BaseCacheBenchmark { private string _key = Guid.NewGuid().ToString(); @@ -134,6 +116,7 @@ protected override void Excecute(ICacheManager cache) } } + [ExcludeFromCodeCoverage] public class PutWithRegionSingleBenchmark : BaseCacheBenchmark { private string _key = Guid.NewGuid().ToString(); @@ -148,6 +131,7 @@ protected override void Excecute(ICacheManager cache) #region get + [ExcludeFromCodeCoverage] public class GetSingleBenchmark : BaseCacheBenchmark { protected string Key = Guid.NewGuid().ToString(); @@ -171,13 +155,12 @@ protected override void SetupBench() RuntimeCache.Add(Key, Key, "region"); MsMemoryCache.Add(Key, Key); MsMemoryCache.Add(Key, Key, "region"); - MemcachedCache.Add(Key, Key); - MemcachedCache.Add(Key, Key, "region"); RedisCache.Add(Key, Key); RedisCache.Add(Key, Key, "region"); } } + [ExcludeFromCodeCoverage] public class GetWithRegionSingleBenchmark : GetSingleBenchmark { protected override void Excecute(ICacheManager cache) @@ -194,6 +177,7 @@ protected override void Excecute(ICacheManager cache) #region update + [ExcludeFromCodeCoverage] public class UpdateSingleBenchmark : GetSingleBenchmark { protected override void Excecute(ICacheManager cache) @@ -207,4 +191,4 @@ protected override void Excecute(ICacheManager cache) } #endregion upate -} \ No newline at end of file +} diff --git a/test/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj b/benchmarks/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj similarity index 76% rename from test/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj rename to benchmarks/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj index f34ceb8f..dfcff79b 100644 --- a/test/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj +++ b/benchmarks/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj @@ -1,15 +1,15 @@  - net46 + net8.0 CacheManager.Benchmarks Exe CacheManager.Benchmarks false false false + false - @@ -18,13 +18,9 @@ - - - + true - - \ No newline at end of file diff --git a/test/CacheManager.Benchmarks/GzBenchmark.cs b/benchmarks/CacheManager.Benchmarks/GzBenchmark.cs similarity index 98% rename from test/CacheManager.Benchmarks/GzBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/GzBenchmark.cs index ad50d49a..4b605910 100644 --- a/test/CacheManager.Benchmarks/GzBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/GzBenchmark.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Compression; using System.Linq; @@ -9,13 +10,14 @@ namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public class GzBenchmark { private static ArrayPool _pool = ArrayPool.Create(); private byte[] _payload; - [Setup] + [GlobalSetup] public void Setup() { var list = new List(); @@ -170,4 +172,4 @@ public byte[] Decompression(byte[] compressedData) } } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs b/benchmarks/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs similarity index 97% rename from test/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs index 8b7fd44f..fc8fd657 100644 --- a/test/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public class PlainDictionaryUpdateBenchmark { private const int Threads = 6; @@ -92,4 +94,4 @@ private void RunParallel(Action act, int threads, int iterations) Parallel.Invoke(tasks.ToArray()); } } -} \ No newline at end of file +} diff --git a/benchmarks/CacheManager.Benchmarks/Program.cs b/benchmarks/CacheManager.Benchmarks/Program.cs new file mode 100644 index 00000000..4076da50 --- /dev/null +++ b/benchmarks/CacheManager.Benchmarks/Program.cs @@ -0,0 +1,33 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Running; + +namespace CacheManager.Benchmarks +{ + [ExcludeFromCodeCoverage] + public class Program + { + public static void Main(string[] args) + { + do + { + var config = ManualConfig.CreateMinimumViable() + .AddJob(Job.Default + .WithIterationCount(10) + .WithWarmupCount(2) + .WithLaunchCount(1)) + .AddDiagnoser(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default); + + BenchmarkSwitcher + .FromAssembly(typeof(Program).GetTypeInfo().Assembly) + .Run(args, config); + + Console.WriteLine("done!"); + Console.WriteLine("Press escape to exit or any key to continue..."); + } while (Console.ReadKey().Key != ConsoleKey.Escape); + } + } +} diff --git a/test/CacheManager.Benchmarks/Properties/AssemblyInfo.cs b/benchmarks/CacheManager.Benchmarks/Properties/AssemblyInfo.cs similarity index 100% rename from test/CacheManager.Benchmarks/Properties/AssemblyInfo.cs rename to benchmarks/CacheManager.Benchmarks/Properties/AssemblyInfo.cs diff --git a/test/CacheManager.Benchmarks/SerializationBenchmark.cs b/benchmarks/CacheManager.Benchmarks/SerializationBenchmark.cs similarity index 87% rename from test/CacheManager.Benchmarks/SerializationBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/SerializationBenchmark.cs index 34ffe55a..389b8b61 100644 --- a/test/CacheManager.Benchmarks/SerializationBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/SerializationBenchmark.cs @@ -1,28 +1,21 @@ using System; -using System.Buffers; using System.Collections.Generic; -using System.IO; +using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; using CacheManager.Core; using CacheManager.Core.Internal; using CacheManager.Serialization.Bond; using CacheManager.Serialization.Json; using CacheManager.Serialization.ProtoBuf; -using Microsoft.Extensions.ObjectPool; -using Newtonsoft.Json; namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public class SerializationBenchmark { private int _iterations = 1000; private Queue> _payload; - private BinaryCacheSerializer _binary = new BinaryCacheSerializer(); private JsonCacheSerializer _json = new JsonCacheSerializer(); private GzJsonCacheSerializer _jsonGz = new GzJsonCacheSerializer(); private ProtoBufSerializer _proto = new Serialization.ProtoBuf.ProtoBufSerializer(); @@ -31,7 +24,7 @@ public class SerializationBenchmark private BondSimpleJsonCacheSerializer _bondSimpleJson = new BondSimpleJsonCacheSerializer(); private readonly Type _pocoType = typeof(TestPoco); - [Setup] + [GlobalSetup] public void Setup() { var rnd = new Random(); @@ -73,20 +66,6 @@ private void ExecRun(Action> action) _payload.Enqueue(item); } - [Benchmark()] - public void BinarySerializer() - { - ExecRun((item) => - { - var data = _binary.SerializeCacheItem(item); - var result = _binary.DeserializeCacheItem(data, _pocoType); - if (result == null) - { - throw new Exception(); - } - }); - } - [Benchmark(Baseline = true)] public void JsonSerializer() { @@ -171,4 +150,4 @@ public void BondSimpleJsonSerializer() }); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Benchmarks/TestPoco.cs b/benchmarks/CacheManager.Benchmarks/TestPoco.cs similarity index 91% rename from test/CacheManager.Benchmarks/TestPoco.cs rename to benchmarks/CacheManager.Benchmarks/TestPoco.cs index a4250f23..b2207156 100644 --- a/test/CacheManager.Benchmarks/TestPoco.cs +++ b/benchmarks/CacheManager.Benchmarks/TestPoco.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Newtonsoft.Json; using ProtoBuf; namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] [Serializable] [JsonObject] [ProtoContract] @@ -33,6 +35,7 @@ public class TestPoco public List OList { get; set; } } + [ExcludeFromCodeCoverage] [Serializable] [ProtoContract] [JsonObject] @@ -49,4 +52,4 @@ public class TestSubPoco [Bond.Id(2)] public string Val { get; set; } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Benchmarks/UnixTimestampBenchmark.cs b/benchmarks/CacheManager.Benchmarks/UnixTimestampBenchmark.cs similarity index 73% rename from test/CacheManager.Benchmarks/UnixTimestampBenchmark.cs rename to benchmarks/CacheManager.Benchmarks/UnixTimestampBenchmark.cs index 7c52f650..3dffe7c2 100644 --- a/test/CacheManager.Benchmarks/UnixTimestampBenchmark.cs +++ b/benchmarks/CacheManager.Benchmarks/UnixTimestampBenchmark.cs @@ -1,10 +1,10 @@ using System; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using BenchmarkDotNet.Attributes; -using CacheManager.Core.Utility; namespace CacheManager.Benchmarks { + [ExcludeFromCodeCoverage] public class UnixTimestampBenchmark { [Benchmark(Baseline = true)] @@ -20,11 +20,5 @@ public long ManualCalcNaive() { return (long)(DateTime.UtcNow - _date1970).TotalMilliseconds; } - - [Benchmark()] - public long ManualCalcOptimized() - { - return Clock.GetUnixTimestampMillis(); - } } -} \ No newline at end of file +} diff --git a/samples/CacheManager.Examples.Configuration/CacheManager.Examples.Configuration.csproj b/benchmarks/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj similarity index 54% rename from samples/CacheManager.Examples.Configuration/CacheManager.Examples.Configuration.csproj rename to benchmarks/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj index 56226f1a..3fb140bf 100644 --- a/samples/CacheManager.Examples.Configuration/CacheManager.Examples.Configuration.csproj +++ b/benchmarks/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj @@ -1,34 +1,38 @@  + CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. + 2.0.0 + MichaConrad + net8.0 + CacheManager.Config.Tests Exe - net462 + ../../tools/key.snk + true + true + CacheManager.Config.Tests + false - - + + PreserveNewest + + + + - - + + - - - - - - - - - PreserveNewest - + + - + - \ No newline at end of file diff --git a/benchmarks/CacheManager.Config.Tests/Program.cs b/benchmarks/CacheManager.Config.Tests/Program.cs new file mode 100644 index 00000000..41836cd2 --- /dev/null +++ b/benchmarks/CacheManager.Config.Tests/Program.cs @@ -0,0 +1,122 @@ +using System; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using CacheManager.Core; +using Garnet; +using Garnet.client; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace CacheManager.Config.Tests; + +internal class Program +{ + public static GarnetServer StartServer(ILoggerFactory loggerFactory) + { + var server = new GarnetServer(new GarnetServerOptions() + { + EnableLua = true, + LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)), + EndPoint = new IPEndPoint(IPAddress.Loopback, 6379) + }, + loggerFactory: loggerFactory); + + server.Start(); + + return server; + } + + public static void Main(string[] args) + { + ThreadPool.SetMinThreads(100, 100); + + var iterations = 100; + try + { + var services = new ServiceCollection(); + + services.AddLogging(c => + { + c.AddSystemdConsole(); + c.SetMinimumLevel(LogLevel.Information); + }); + + var provider = services.BuildServiceProvider(); + var loggerFactory = provider.GetRequiredService(); + + using var server = StartServer(loggerFactory); + + var builder = new Core.CacheConfigurationBuilder("myCache"); + + builder + .WithRetryTimeout(500) + .WithMaxRetries(3); + + builder + .WithDictionaryHandle() + .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(20)) + .DisableStatistics(); + + builder + .WithRedisCacheHandle("redis", true) + .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60)) + .DisableStatistics(); + + builder.WithRedisBackplane("redis"); + + builder.WithRedisConfiguration("redis", config => + { + config + //.UseTwemproxy() + //.UseCompatibilityMode("2.4") + .WithAllowAdmin() + .WithDatabase(0) + .WithConnectionTimeout(5000) + .EnableKeyspaceEvents() + .WithEndpoint("127.0.0.1", 6379); + }); + + //builder.WithRedisConfiguration("redis", "localhost:22121"); + + builder.WithBondCompactBinarySerializer(); + + var cacheA = new BaseCacheManager(builder.Build()); + cacheA.Clear(); + + for (var i = 0; i < iterations; i++) + { + try + { + Tests.PumpData(cacheA).GetAwaiter().GetResult(); + break; // specified runtime (todo: rework this anyways) + } + catch (AggregateException ex) + { + ex.Handle((e) => + { + Console.WriteLine(e); + return true; + }); + } + catch (Exception e) + { + Console.WriteLine("Error: " + e.Message + "\n" + e.StackTrace); + Thread.Sleep(1000); + } + + Console.WriteLine("---------------------------------------------------------"); + } + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + + Console.ForegroundColor = ConsoleColor.DarkGreen; + Console.WriteLine("We are done..."); + Console.ForegroundColor = ConsoleColor.Gray; + Console.ReadKey(); + } +} diff --git a/test/CacheManager.Config.Tests/Properties/launchSettings.json b/benchmarks/CacheManager.Config.Tests/Properties/launchSettings.json similarity index 100% rename from test/CacheManager.Config.Tests/Properties/launchSettings.json rename to benchmarks/CacheManager.Config.Tests/Properties/launchSettings.json diff --git a/test/CacheManager.Config.Tests/Settings.StyleCop b/benchmarks/CacheManager.Config.Tests/Settings.StyleCop similarity index 100% rename from test/CacheManager.Config.Tests/Settings.StyleCop rename to benchmarks/CacheManager.Config.Tests/Settings.StyleCop diff --git a/test/CacheManager.Config.Tests/Tests.cs b/benchmarks/CacheManager.Config.Tests/Tests.cs similarity index 83% rename from test/CacheManager.Config.Tests/Tests.cs rename to benchmarks/CacheManager.Config.Tests/Tests.cs index 70466053..9cc66e17 100644 --- a/test/CacheManager.Config.Tests/Tests.cs +++ b/benchmarks/CacheManager.Config.Tests/Tests.cs @@ -73,6 +73,95 @@ public static void CacheThreadTest(ICacheManager cache, int seed = 42) eventRemoveCount)); } + public static async Task PumpData(ICacheManager cache, int runForSeconds = 300) + { + var source = new CancellationTokenSource(TimeSpan.FromSeconds(runForSeconds)); + var maxItems = 500000; + var numReaders = 10; + var puts = 0; + var hits = 0; + var misses = 0; + var putIterations = 0; + + var pumpTask = Task.Factory.StartNew( + () => + { + var count = 0; + while (!source.Token.IsCancellationRequested) + { + try + { + count++; + cache.Put("key" + count, Guid.NewGuid().ToString()); + + Interlocked.Increment(ref puts); + + if (count == maxItems) + { + count = 0; + cache.Clear(); + Interlocked.Increment(ref putIterations); + } + } + catch + { + // resuming if some timeouts happen + } + } + }, + source.Token); + + var readers = new List(); + for (var i = 0; i < numReaders; i++) + { + readers.Add(Read()); + } + + try + { + await LogProgress(); + await Task.WhenAll(readers.ToArray()); + } + catch (OperationCanceledException) + { + } + + async Task LogProgress() + { + while (!source.Token.IsCancellationRequested) + { + await Task.Delay(1000); + Console.WriteLine($"Pumped {puts,-10} keys overall in {putIterations,3} iterations. ({numReaders})Readers got {hits,5} cache hits and {misses,5} misses."); + } + } + + async Task Read() + { + var rnd = new Random(); + while (!source.Token.IsCancellationRequested) + { + try + { + var value = cache.Get("key" + rnd.Next(0, maxItems)); + if (value == null) + { + Interlocked.Increment(ref misses); + } + else + { + Interlocked.Increment(ref hits); + } + } + catch + { + // resuming if some timeouts happen + } + + await Task.Delay(100, source.Token); + } + } + } + public static void PutAndMultiGetTest(params ICacheManager[] caches) { var swatch = Stopwatch.StartNew(); @@ -125,7 +214,7 @@ public static void PutAndMultiGetTest(params ICacheManager[] caches) }); } - Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = 8 }, actions.ToArray()); + Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = 16 }, actions.ToArray()); } var elapsed = swatch.ElapsedMilliseconds; diff --git a/test/CacheManager.Config.Tests/cache.json b/benchmarks/CacheManager.Config.Tests/cache.json similarity index 97% rename from test/CacheManager.Config.Tests/cache.json rename to benchmarks/CacheManager.Config.Tests/cache.json index e773cfaa..28afbcbe 100644 --- a/test/CacheManager.Config.Tests/cache.json +++ b/benchmarks/CacheManager.Config.Tests/cache.json @@ -18,7 +18,7 @@ "maxRetries": 1000, "name": "cachename", "retryTimeout": 100, - "updateMode": "Full", + "updateMode": "Up", "backplane": { "key": "redisConnection", "knownType": "Redis", diff --git a/test/CacheManager.Events.Tests/CacheEvent.cs b/benchmarks/CacheManager.Events.Tests/CacheEvent.cs similarity index 100% rename from test/CacheManager.Events.Tests/CacheEvent.cs rename to benchmarks/CacheManager.Events.Tests/CacheEvent.cs diff --git a/test/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj b/benchmarks/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj similarity index 71% rename from test/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj rename to benchmarks/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj index 14df05af..ea06c2cc 100644 --- a/test/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj +++ b/benchmarks/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj @@ -2,22 +2,22 @@ Exe - net462 + net8.0 + false - - + + - + - \ No newline at end of file diff --git a/test/CacheManager.Events.Tests/EventCommand.cs b/benchmarks/CacheManager.Events.Tests/EventCommand.cs similarity index 99% rename from test/CacheManager.Events.Tests/EventCommand.cs rename to benchmarks/CacheManager.Events.Tests/EventCommand.cs index c6f35a9c..a977f999 100644 --- a/test/CacheManager.Events.Tests/EventCommand.cs +++ b/benchmarks/CacheManager.Events.Tests/EventCommand.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using CacheManager.Core; using CacheManager.Core.Internal; -using Microsoft.Extensions.CommandLineUtils; +using McMaster.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; namespace CacheManager.Events.Tests @@ -163,4 +163,4 @@ private static IEnumerable GetStatus(EventCounter + { + c.AddConsole(); + c.SetMinimumLevel(LogLevel.Warning); + }); + + var provider = services.BuildServiceProvider(); + var loggerFactory = provider.GetRequiredService(); + + using var server = StartServer(loggerFactory); + + var app = new CommandLineApplication(); + app.Command("redis", (cmdApp) => new RedisCommand(cmdApp, loggerFactory)); + app.Command("redisAndMemory", (cmdApp) => new RedisAndMemoryCommand(cmdApp, loggerFactory)); + app.Command("redisAndMemoryNoMessages", (cmdApp) => new RedisAndMemoryNoMessagingCommand(cmdApp, loggerFactory)); + app.Command("memoryOnly", (cmdApp) => new MemoryOnlyCommand(cmdApp, loggerFactory)); + app.HelpOption("-h|--help"); + if (args.Length == 0) + { + app.ShowHelp(); + } + + try + { + app.Execute(args); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } +} diff --git a/test/CacheManager.Events.Tests/Properties/launchSettings.json b/benchmarks/CacheManager.Events.Tests/Properties/launchSettings.json similarity index 62% rename from test/CacheManager.Events.Tests/Properties/launchSettings.json rename to benchmarks/CacheManager.Events.Tests/Properties/launchSettings.json index a8986eb0..63b7de9b 100644 --- a/test/CacheManager.Events.Tests/Properties/launchSettings.json +++ b/benchmarks/CacheManager.Events.Tests/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "CacheManager.Events.Tests": { "commandName": "Project", - "commandLineArgs": "redis -r 20 -j 10" + "commandLineArgs": "redisAndMemory -r 20 -j 10" } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Events.Tests/RedisAndMemoryCommand.cs b/benchmarks/CacheManager.Events.Tests/RedisAndMemoryCommand.cs similarity index 89% rename from test/CacheManager.Events.Tests/RedisAndMemoryCommand.cs rename to benchmarks/CacheManager.Events.Tests/RedisAndMemoryCommand.cs index 5a550c18..47165ed9 100644 --- a/test/CacheManager.Events.Tests/RedisAndMemoryCommand.cs +++ b/benchmarks/CacheManager.Events.Tests/RedisAndMemoryCommand.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using CacheManager.Core; using CacheManager.Core.Internal; -using Microsoft.Extensions.CommandLineUtils; +using McMaster.Extensions.CommandLineUtils; using Microsoft.Extensions.Logging; using StackExchange.Redis; @@ -19,8 +19,7 @@ protected override void Configure() base.Configure(); _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true"); - _configuration = new ConfigurationBuilder() - .WithMicrosoftLogging(LoggerFactory) + _configuration = new CacheConfigurationBuilder() .WithMicrosoftMemoryCacheHandle("in-memory") .And .WithJsonSerializer() @@ -41,8 +40,7 @@ protected override void Configure() base.Configure(); _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true"); - _configuration = new ConfigurationBuilder() - .WithMicrosoftLogging(LoggerFactory) + _configuration = new CacheConfigurationBuilder() .WithRedisBackplane("redisConfig") .WithJsonSerializer() .WithRedisConfiguration("redisConfig", _multiplexer, enableKeyspaceNotifications: true) @@ -65,8 +63,7 @@ protected override void Configure() base.Configure(); _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true"); - _configuration = new ConfigurationBuilder() - .WithMicrosoftLogging(LoggerFactory) + _configuration = new CacheConfigurationBuilder() .WithMicrosoftMemoryCacheHandle("in-memory") .And .WithRedisBackplane("redisConfig") @@ -93,7 +90,7 @@ public override async Task Execute() cacheA.TryUpdate(key, (oldVal) => oldVal + 1, out int? newValue); - _multiplexer.GetDatabase(0).KeyDelete(key, CommandFlags.HighPriority); + _multiplexer.GetDatabase(0).KeyDelete(key); await Task.Delay(0); }); @@ -106,4 +103,4 @@ public override async Task Execute() return 0; } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Events.Tests/Spinner.cs b/benchmarks/CacheManager.Events.Tests/Spinner.cs similarity index 100% rename from test/CacheManager.Events.Tests/Spinner.cs rename to benchmarks/CacheManager.Events.Tests/Spinner.cs diff --git a/samples/AspNetCore/Controllers/InfoController.cs b/samples/AspNetCore/Controllers/InfoController.cs new file mode 100644 index 00000000..7d9e49af --- /dev/null +++ b/samples/AspNetCore/Controllers/InfoController.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace Web.Controllers +{ + [Route("api/[controller]")] + public class InfoController : Controller + { + [HttpGet("")] + public IActionResult Index() + { + var result = new Dictionary(); + result.Add(nameof(Microsoft.Extensions.Configuration), typeof(Microsoft.Extensions.Configuration.ConfigurationProvider).Assembly.GetName().Version.ToString()); + result.Add(nameof(Microsoft.Extensions.Logging), typeof(Microsoft.Extensions.Logging.LoggerFactory).Assembly.GetName().Version.ToString()); + result.Add(nameof(Microsoft.Extensions.Caching), typeof(Microsoft.Extensions.Caching.Memory.MemoryCache).Assembly.GetName().Version.ToString()); + result.Add(nameof(Microsoft.Extensions.DependencyInjection), typeof(Microsoft.Extensions.DependencyInjection.ServiceProvider).Assembly.GetName().Version.ToString()); + result.Add(nameof(Microsoft.Extensions.Options), typeof(Microsoft.Extensions.Options.Options).Assembly.GetName().Version.ToString()); + result.Add(nameof(Microsoft.AspNetCore.Hosting), typeof(Microsoft.AspNetCore.Hosting.WebHostBuilder).Assembly.GetName().Version.ToString()); + + return Json(result); + } + } +} diff --git a/samples/AspnetCore.WebApp/Controllers/ValuesController.cs b/samples/AspNetCore/Controllers/ValuesController.cs similarity index 91% rename from samples/AspnetCore.WebApp/Controllers/ValuesController.cs rename to samples/AspNetCore/Controllers/ValuesController.cs index 8c16b9b0..923d7d4c 100644 --- a/samples/AspnetCore.WebApp/Controllers/ValuesController.cs +++ b/samples/AspNetCore/Controllers/ValuesController.cs @@ -10,12 +10,10 @@ public class ValuesController : Controller { private readonly ICacheManager _cache; - public ValuesController(ICacheManager valuesCache, ICacheManager intCache, ICacheManager dates) + public ValuesController(ICacheManager valuesCache, ICacheManager nullableInts) { _cache = valuesCache; - - dates.Add("now", DateTime.UtcNow); - intCache.Add("count", 1); + nullableInts.Add("key", 1); } // DELETE api/values/key @@ -67,4 +65,4 @@ public IActionResult Put(string key, [FromBody]string value) return NotFound(); } } -} \ No newline at end of file +} diff --git a/samples/AspNetCore/Program.cs b/samples/AspNetCore/Program.cs new file mode 100644 index 00000000..a6a5beb2 --- /dev/null +++ b/samples/AspNetCore/Program.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; +using System.Net; +using Garnet; +using Garnet.server; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace AspnetCore.WebApp; + +public class Program +{ + public static GarnetServer StartServer(ILoggerFactory loggerFactory = null) + { + var server = new GarnetServer(new GarnetServerOptions() + { + EnableLua = true, + LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)), + EndPoint = new IPEndPoint(IPAddress.Loopback, 6379) + }, + loggerFactory: loggerFactory); + + server.Start(); + + return server; + } + + public static void Main(string[] args) + { + using var server = StartServer(); + CreateHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup() + .ConfigureAppConfiguration((ctx, builder) => + { + builder.AddJsonFile("cache.json", optional: false); + }); +} diff --git a/samples/AspNetCore/Properties/launchSettings.json b/samples/AspNetCore/Properties/launchSettings.json new file mode 100644 index 00000000..730e96ba --- /dev/null +++ b/samples/AspNetCore/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "AspnetCore.WebApp": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "http://localhost:5000/swagger/ui", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:5000" + } + } +} diff --git a/samples/AspNetCore/Startup.cs b/samples/AspNetCore/Startup.cs new file mode 100644 index 00000000..f311a67e --- /dev/null +++ b/samples/AspNetCore/Startup.cs @@ -0,0 +1,101 @@ +namespace AspnetCore.WebApp +{ + using System; + using CacheManager.Core; + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.Hosting; + + public class Startup + { + public Startup(IWebHostEnvironment env, IConfiguration configuration, ILoggerFactory loggerFactory) + { + HostingEnvironment = env ?? throw new ArgumentNullException(nameof(env)); + Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); + LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + } + + public IWebHostEnvironment HostingEnvironment { get; } + + public IConfiguration Configuration { get; } + + public ILoggerFactory LoggerFactory { get; } + + public void ConfigureServices(IServiceCollection services) + { + services.AddMvc(); + + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", + new Microsoft.OpenApi.Models.OpenApiInfo + { + Title = "My API - V1", + Version = "v1" + } + ); + }); + + // uses a refined configuration (this will not log, as we added the MS Logger only to the configuration above + services.AddCacheManagerConfiguration(Configuration, configure: builder => builder + .WithJsonSerializer() + .WithRedisConfiguration("redis", c => c.WithEndpoint("localhost", 6379)) + .WithRedisCacheHandle("redis")); + + // creates a completely new configuration for this instance (also not logging) + services.AddCacheManager(inline => inline.WithDictionaryHandle()); + + // any other type will be this. Configuration used will be the one defined by AddCacheManagerConfiguration earlier. + services.AddCacheManager(); + } + + public void Configure(IApplicationBuilder app) + { + // give some error details in debug mode + if (HostingEnvironment.IsDevelopment()) + { + app.Use(async (ctx, next) => + { + try + { + await next.Invoke(); + } + catch (Exception ex) + { + await ctx.Response.WriteAsync($"{{\"error\": \"{ex}\"}}"); + } + }); + } + + // lets redirect to the swagger UI, there is nothing else to display otherwise ;) + app.Use(async (ctx, next) => + { + if (ctx.Request.Path.StartsWithSegments("/")) + { + ctx.Response.Redirect("/swagger/"); + } + else + { + await next.Invoke(); + } + }); + + app.UseStaticFiles(); + app.UseRouting(); + app.UseCors(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseEndpoints(b => b.MapControllers()); + + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + }); + } + } +} diff --git a/samples/AspNetCore/Web.csproj b/samples/AspNetCore/Web.csproj new file mode 100644 index 00000000..97eacf8c --- /dev/null +++ b/samples/AspNetCore/Web.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + true + AspnetCore.WebApp + Exe + AspnetCore.WebApp + false + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/AspnetCore.WebApp/appsettings.json b/samples/AspNetCore/appsettings.json similarity index 68% rename from samples/AspnetCore.WebApp/appsettings.json rename to samples/AspNetCore/appsettings.json index bd260c7a..7efae0d9 100644 --- a/samples/AspnetCore.WebApp/appsettings.json +++ b/samples/AspNetCore/appsettings.json @@ -1,9 +1,8 @@ { "Logging": { - "IncludeScopes": false, "LogLevel": { "Default": "Debug", - "CacheManager": "Debug", + "CacheManager": "Trace", "System": "Error", "Microsoft": "Error" } diff --git a/samples/AspnetCore.WebApp/cache.json b/samples/AspNetCore/cache.json similarity index 100% rename from samples/AspnetCore.WebApp/cache.json rename to samples/AspNetCore/cache.json diff --git a/samples/AspnetCore.WebApp/web.config b/samples/AspNetCore/web.config similarity index 100% rename from samples/AspnetCore.WebApp/web.config rename to samples/AspNetCore/web.config diff --git a/samples/AspnetCore.WebApp/AspnetCore.WebApp.csproj b/samples/AspnetCore.WebApp/AspnetCore.WebApp.csproj deleted file mode 100644 index 8ab25c3d..00000000 --- a/samples/AspnetCore.WebApp/AspnetCore.WebApp.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - netcoreapp1.0 - true - AspnetCore.WebApp - Exe - AspnetCore.WebApp - 1.1.1 - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/AspnetCore.WebApp/Program.cs b/samples/AspnetCore.WebApp/Program.cs deleted file mode 100644 index 1b58aeb7..00000000 --- a/samples/AspnetCore.WebApp/Program.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; - -namespace AspnetCore.WebApp -{ - public class Program - { - public static void Main(string[] args) - { - var host = new WebHostBuilder() - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() - .Build(); - - host.Run(); - } - } -} \ No newline at end of file diff --git a/samples/AspnetCore.WebApp/Properties/launchSettings.json b/samples/AspnetCore.WebApp/Properties/launchSettings.json deleted file mode 100644 index 2d46cd93..00000000 --- a/samples/AspnetCore.WebApp/Properties/launchSettings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:58186", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": false, - "launchUrl": "/swagger/ui", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "AspnetCore.WebApp": { - "commandName": "Project", - "launchBrowser": false, - "launchUrl": "http://localhost:5000/swagger/ui", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:5000" - } - } -} \ No newline at end of file diff --git a/samples/AspnetCore.WebApp/Startup.cs b/samples/AspnetCore.WebApp/Startup.cs deleted file mode 100644 index 5d3a8d00..00000000 --- a/samples/AspnetCore.WebApp/Startup.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Linq; -using CacheManager.Core; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -namespace AspnetCore.WebApp -{ - using Microsoft.Extensions.Configuration; - - public class Startup - { - public Startup(IHostingEnvironment env) - { - var builder = new ConfigurationBuilder() - .SetBasePath(env.ContentRootPath) - .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) - .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) - // adding cache.json which contains cachemanager configuration(s) - .AddJsonFile("cache.json", optional: false) - .AddEnvironmentVariables(); - - Configuration = builder.Build(); - } - - public IConfigurationRoot Configuration { get; } - - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc(); - services.AddSwaggerGen(); - - // using the new overload which adds a singleton of the configuration to services and the configure method to add logging - // TODO: still not 100% happy with the logging part - services.AddCacheManagerConfiguration(Configuration, cfg => cfg.WithMicrosoftLogging(services)); - - // uses a refined configurastion (this will not log, as we added the MS Logger only to the configuration above - services.AddCacheManager(Configuration, configure: builder => builder.WithJsonSerializer()); - - // creates a completely new configuration for this instance (also not logging) - services.AddCacheManager(inline => inline.WithDictionaryHandle()); - - // any other type will be this. Configurastion used will be the one defined by AddCacheManagerConfiguration earlier. - services.AddCacheManager(); - } - - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) - { - // add console logging with the configured log levels from appsettings.json - loggerFactory.AddConsole(Configuration.GetSection("Logging")); - - // give some error details in debug mode - if (env.IsDevelopment()) - { - app.Use(async (ctx, next) => - { - try - { - await next.Invoke(); - } - catch (Exception ex) - { - await ctx.Response.WriteAsync($"{{\"error\": \"{ex}\"}}"); - } - }); - } - - // lets redirect to the swagger ui, there is nothing else to display otherwise ;) - app.Use(async (ctx, next) => - { - if (ctx.Request.Path.StartsWithSegments("/")) - { - ctx.Response.Redirect("/swagger/ui"); - } - else - { - await next.Invoke(); - } - }); - - //app.UseStaticFiles(); - app.UseMvc(); - - app.UseSwagger(); - app.UseSwaggerUi(); - } - } -} \ No newline at end of file diff --git a/samples/CacheManager.Examples.Configuration/Couchbase.cs b/samples/CacheManager.Examples.Configuration/Couchbase.cs deleted file mode 100644 index 75eb40b4..00000000 --- a/samples/CacheManager.Examples.Configuration/Couchbase.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using CacheManager.Core; -using Couchbase; -using Couchbase.Authentication; -using Couchbase.Configuration.Client; - -namespace Configuration -{ - public class Couchbase - { - public void UsingClusterHelper() - { - var cfg = new ClientConfiguration() - { - Servers = new List() - { - new Uri("http://127.0.0.1:8091") - } - }; - - ClusterHelper.Initialize(cfg); - ClusterHelper.Get().Authenticate(new PasswordAuthenticator("admin", "password")); - - // using cluster helper is enough for CacheManager since 1.0.2 as it falls back to ClusterHelper internally - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseCacheHandle("cb") - .Build(); - - var cache = new BaseCacheManager(cacheConfig); - cache.AddOrUpdate("test", 1, (v) => v + 1); - } - - public void UsingAppConfig() - { - // see couchbaseClients/couchbase section in app.config of this project - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseCacheHandle("couchbaseClients/couchbase") - .Build(); - - var cache = new BaseCacheManager(cacheConfig); - cache.AddOrUpdate("test", 1, (v) => v + 1); - } - - public void UsingAppConfigWithAuthentication() - { - // see couchbaseClients/couchbase section in app.config of this project - // Note: even though we pass in "cb", CacheManager will fall back to the - // default couchbase section at couchbaseClients/couchbase! - // We could also pass in the section name explicitly instead of "cb". - - ClusterHelper.Initialize("couchbaseClients/couchbase"); - ClusterHelper.Get().Authenticate(new PasswordAuthenticator("admin", "password")); - - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseCacheHandle("keydoesnotmatter") - .Build(); - - var cache = new BaseCacheManager(cacheConfig); - cache.AddOrUpdate("test", 1, (v) => v + 1); - } - - public void UsingClientConfiguration() - { - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseConfiguration("myConfig", new ClientConfiguration()) // add the configuration you need here... - .WithCouchbaseCacheHandle("myConfig") - .Build(); - } - - public void UsingAlreadyDefinedCluster() - { - var cluster = new Cluster(new ClientConfiguration()); - cluster.Authenticate(new PasswordAuthenticator("admin", "password")); - - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseCluster("myCluster", cluster) - .WithCouchbaseCacheHandle("myCluster") - .Build(); - } - - public void UsingExplicitBucketName() - { - ClusterHelper.Initialize(); - ClusterHelper.Get().Authenticate(new PasswordAuthenticator("admin", "password")); - - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseCacheHandle("keydoesnotmatter", "beer-sample") // passing in a bucket name which should be used - .Build(); - - var cache = new BaseCacheManager(cacheConfig); - cache.AddOrUpdate("test", 1, (v) => v + 1); - } - - public void UsingExplicitBucketNameWithPassword() - { - var cacheConfig = new ConfigurationBuilder() - .WithCouchbaseConfiguration("cb", new ClientConfiguration()) - .WithCouchbaseCacheHandle("cb", "secret-bucket", "secret") // passing in a bucket-name and bucket-password - .Build(); - - var cache = new BaseCacheManager(cacheConfig); - cache.AddOrUpdate("test", 1, (v) => v + 1); - } - } -} \ No newline at end of file diff --git a/samples/CacheManager.Examples.Configuration/Program.cs b/samples/CacheManager.Examples.Configuration/Program.cs deleted file mode 100644 index 4677b0c4..00000000 --- a/samples/CacheManager.Examples.Configuration/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; - -namespace Configuration -{ - class Program - { - static void Main(string[] args) - { - //var cb = new Couchbase(); - //cb.UsingClusterHelper(); - //cb.UsingAppConfig(); - //cb.UsingAppConfigWithAuthentication(); - //cb.UsingExplicitBucketName(); - //cb.UsingExplicitBucketNameWithPassword(); - } - } -} \ No newline at end of file diff --git a/samples/CacheManager.Examples.Configuration/app.config b/samples/CacheManager.Examples.Configuration/app.config deleted file mode 100644 index 1a94b5f2..00000000 --- a/samples/CacheManager.Examples.Configuration/app.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
- - - - - - - - - - - - - - - \ No newline at end of file diff --git a/samples/CacheManager.Examples/App.config b/samples/CacheManager.Examples/App.config index 2a2a36c0..c901d07c 100644 --- a/samples/CacheManager.Examples/App.config +++ b/samples/CacheManager.Examples/App.config @@ -10,7 +10,7 @@ - + diff --git a/samples/CacheManager.Examples/CacheManager.Examples.csproj b/samples/CacheManager.Examples/CacheManager.Examples.csproj index 550dfb58..4ea3b89a 100644 --- a/samples/CacheManager.Examples/CacheManager.Examples.csproj +++ b/samples/CacheManager.Examples/CacheManager.Examples.csproj @@ -3,7 +3,7 @@ CacheManager.Examples Console Application MICHA - net451 + net8.0 CacheManager.Examples Exe CacheManager.Examples @@ -13,6 +13,7 @@ false false false + false @@ -22,21 +23,13 @@ - - - - - - + - - - + - - + \ No newline at end of file diff --git a/samples/CacheManager.Examples/Program.cs b/samples/CacheManager.Examples/Program.cs index 358eeda1..3752d825 100644 --- a/samples/CacheManager.Examples/Program.cs +++ b/samples/CacheManager.Examples/Program.cs @@ -2,363 +2,311 @@ using System.Threading; using CacheManager.Core; using Microsoft.Extensions.Logging; -#if NET451 -using Microsoft.Practices.Unity; -#else -using Unity; -#endif +using Microsoft.Extensions.DependencyInjection; +using System.Net; +using Garnet.server; +using Garnet; -namespace CacheManager.Examples +namespace CacheManager.Examples; + +public class Program { - public class Program + public static GarnetServer StartServer(ILoggerFactory loggerFactory = null) { - private static void Main() + var server = new GarnetServer(new GarnetServerOptions() { - EventsExample(); - UnityInjectionExample(); - UnityInjectionExample_Advanced(); - SimpleCustomBuildConfigurationUsingConfigBuilder(); - SimpleCustomBuildConfigurationUsingFactory(); - UpdateTest(); - UpdateCounterTest(); - LoggingSample(); - } + EnableLua = true, + LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)), + EndPoint = new IPEndPoint(IPAddress.Loopback, 6379) + }, + loggerFactory: loggerFactory); -#if !NETCOREAPP + server.Start(); - private static void MostSimpleCacheManager() - { - var config = new ConfigurationBuilder() - .WithSystemRuntimeCacheHandle() - .Build(); + return server; + } - var cache = new BaseCacheManager(config); - // or - var cache2 = CacheFactory.FromConfiguration(config); - } + private static void Main() + { + using var server = StartServer(); + EventsExample(); + MostSimpleCacheManagerWithLogging(); + SimpleCustomBuildConfigurationUsingConfigBuilder(); + SimpleCustomBuildConfigurationUsingFactory(); + UpdateTest(); + UpdateCounterTest(); + LoggingSample(); + } - private static void MostSimpleCacheManagerB() - { - var cache = new BaseCacheManager( - new CacheManagerConfiguration() - .Builder - .WithSystemRuntimeCacheHandle() - .Build()); - } + private static void MostSimpleCacheManager() + { + var config = new CacheConfigurationBuilder() + .WithSystemRuntimeCacheHandle() + .Build(); - private static void MostSimpleCacheManagerC() - { - var cache = CacheFactory.Build( - p => p.WithSystemRuntimeCacheHandle()); - } + var cache = new BaseCacheManager(config); + // or + var cache2 = CacheFactory.FromConfiguration(config); + } - private static void MostSimpleCacheManagerWithLogging() - { - var config = new ConfigurationBuilder() - .WithMicrosoftLogging(l => l.AddConsole(LogLevel.Information)) + private static void MostSimpleCacheManagerB() + { + var cache = new BaseCacheManager( + new CacheManagerConfiguration() + .Builder .WithSystemRuntimeCacheHandle() - .Build(); + .Build()); + } - var cache = new BaseCacheManager(config); - // or - var cache2 = CacheFactory.FromConfiguration(config); - } + private static void MostSimpleCacheManagerC() + { + var cache = CacheFactory.Build( + p => p.WithSystemRuntimeCacheHandle()); + } - private static void EditExistingConfiguration() - { - var config = new ConfigurationBuilder() - .WithSystemRuntimeCacheHandle() - .EnableStatistics() - .Build(); + private static void MostSimpleCacheManagerWithLogging() + { + var services = new ServiceCollection(); + services.AddLogging(c => c.AddConsole().SetMinimumLevel(LogLevel.Trace)); + var loggerFactory = services.BuildServiceProvider().GetService(); - config = new ConfigurationBuilder(config) - .WithMicrosoftLogging(f => f.AddConsole()) - .Build(); - } + var config = new CacheConfigurationBuilder() + .WithSystemRuntimeCacheHandle() + .Build(); -#endif + ICacheManager cache = new BaseCacheManager(config, loggerFactory); + cache.Add("test", "test"); + cache.Exists("test no"); + cache.Remove("test"); - private static void LoggingSample() - { - var cache = CacheFactory.Build( - c => - c.WithMicrosoftLogging(log => - { - log.AddConsole(LogLevel.Trace); - }) - .WithDictionaryHandle() - .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10))); + // or + cache = CacheFactory.FromConfiguration(config, loggerFactory); - cache.AddOrUpdate("myKey", "someregion", "value", _ => "new value"); - cache.AddOrUpdate("myKey", "someregion", "value", _ => "new value"); - cache.Expire("myKey", "someregion", TimeSpan.FromMinutes(10)); - var val = cache.Get("myKey", "someregion"); - } + cache.Add("test", "test"); + cache.Exists("test no"); + cache.Remove("test"); + } -#if !NETCOREAPP + private static void EditExistingConfiguration() + { + var config = new CacheConfigurationBuilder() + .WithSystemRuntimeCacheHandle() + .EnableStatistics() + .Build(); - private static void AppConfigLoadInstalledCacheCfg() - { - var cache = CacheFactory.FromConfiguration("myCache"); - cache.Add("key", "value"); - } + config = new CacheConfigurationBuilder(config) + .Build(); + } -#endif + private static void LoggingSample() + { + var services = new ServiceCollection(); + services.AddLogging(c => c.AddConsole().SetMinimumLevel(LogLevel.Trace)); + var loggerFactory = services.BuildServiceProvider().GetService(); + + var cache = CacheFactory.Build( + c => c.WithDictionaryHandle() + .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)), + loggerFactory); + + cache.AddOrUpdate("myKey", "someregion", "value", _ => "new value"); + cache.AddOrUpdate("myKey", "someregion", "value", _ => "new value"); + cache.Expire("myKey", "someregion", TimeSpan.FromMinutes(10)); + var val = cache.Get("myKey", "someregion"); + } - private static void EventsExample() - { - var cache = CacheFactory.Build(s => s.WithDictionaryHandle()); - cache.OnAdd += (sender, args) => Console.WriteLine("Added " + args.Key); - cache.OnGet += (sender, args) => Console.WriteLine("Got " + args.Key); - cache.OnRemove += (sender, args) => Console.WriteLine("Removed " + args.Key); - - cache.Add("key", "value"); - var val = cache.Get("key"); - cache.Remove("key"); - } + private static void AppConfigLoadInstalledCacheCfg() + { + var services = new ServiceCollection(); + services.AddLogging(c => c.AddConsole()); + var loggerFactory = services.BuildServiceProvider().GetService(); -#if !NETCOREAPP + var cache = CacheFactory.FromConfiguration("myCache", loggerFactory); + cache.Add("key", "value"); + } - private static void RedisSample() - { - var cache = CacheFactory.Build(settings => - { - settings - .WithSystemRuntimeCacheHandle() - .And - .WithRedisConfiguration("redis", config => - { - config.WithAllowAdmin() - .WithDatabase(0) - .WithEndpoint("localhost", 6379); - }) - .WithMaxRetries(1000) - .WithRetryTimeout(100) - .WithRedisBackplane("redis") - .WithRedisCacheHandle("redis", true); - }); + private static void EventsExample() + { + var services = new ServiceCollection(); + services.AddLogging(c => c.AddConsole()); + var loggerFactory = services.BuildServiceProvider().GetService(); + + var cache = CacheFactory.Build(s => s.WithDictionaryHandle(), loggerFactory); + cache.OnAdd += (sender, args) => Console.WriteLine("Added " + args.Key); + cache.OnGet += (sender, args) => Console.WriteLine("Got " + args.Key); + cache.OnRemove += (sender, args) => Console.WriteLine("Removed " + args.Key); + + cache.Add("key", "value"); + var val = cache.Get("key"); + cache.Remove("key"); + } - cache.Add("test", 123456); + private static void RedisSample() + { + var services = new ServiceCollection(); + services.AddLogging(c => c.AddConsole()); + var loggerFactory = services.BuildServiceProvider().GetService(); - cache.Update("test", p => p + 1); + var cache = CacheFactory.Build(settings => + { + settings + .WithSystemRuntimeCacheHandle() + .And + .WithRedisConfiguration("redis", config => + { + config.WithAllowAdmin() + .WithDatabase(0) + .WithEndpoint("localhost", 6379); + }) + .WithMaxRetries(1000) + .WithRetryTimeout(100) + .WithRedisBackplane("redis") + .WithRedisCacheHandle("redis", true); + }, + loggerFactory); - var result = cache.Get("test"); - } + cache.Add("test", 123456); -#endif + cache.Update("test", p => p + 1); - private static void SimpleCustomBuildConfigurationUsingConfigBuilder() - { - // this is using the CacheManager.Core.Configuration.ConfigurationBuilder to build a - // custom config you can do the same with the CacheFactory - var cfg = ConfigurationBuilder.BuildConfiguration(settings => - { - settings.WithUpdateMode(CacheUpdateMode.Up) - .WithDictionaryHandle() - .EnablePerformanceCounters() - .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); - }); - - var cache = CacheFactory.FromConfiguration(cfg); - cache.Add("key", "value"); - - // reusing the configuration and using the same cache for different types: - var numbers = CacheFactory.FromConfiguration(cfg); - numbers.Add("intKey", 2323); - numbers.Update("intKey", v => v + 1); - } + var result = cache.Get("test"); + } - private static void SimpleCustomBuildConfigurationUsingFactory() - { - var cache = CacheFactory.Build(settings => + private static void SimpleCustomBuildConfigurationUsingConfigBuilder() + { + // this is using the CacheManager.Core.Configuration.ConfigurationBuilder to build a + // custom config you can do the same with the CacheFactory + var cfg = CacheConfigurationBuilder.BuildConfiguration(settings => { - settings - .WithUpdateMode(CacheUpdateMode.Up) + settings.WithUpdateMode(CacheUpdateMode.Up) .WithDictionaryHandle() - .EnablePerformanceCounters() .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); }); - cache.Add("key", "value"); - } + var cache = CacheFactory.FromConfiguration(cfg); + cache.Add("key", "value"); - private static void UnityInjectionExample() + // reusing the configuration and using the same cache for different types: + var numbers = CacheFactory.FromConfiguration(cfg); + numbers.Add("intKey", 2323); + numbers.Update("intKey", v => v + 1); + } + + private static void SimpleCustomBuildConfigurationUsingFactory() + { + var cache = CacheFactory.Build(settings => { - var container = new UnityContainer(); - container.RegisterType>( - new ContainerControlledLifetimeManager(), - new InjectionFactory((c) => CacheFactory.Build(s => s.WithDictionaryHandle()))); + settings + .WithUpdateMode(CacheUpdateMode.Up) + .WithDictionaryHandle() + .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); + }); - container.RegisterType(); + cache.Add("key", "value"); + } - // resolving the test target object should also resolve the cache instance - var target = container.Resolve(); - target.PutSomethingIntoTheCache(); + private static void UpdateTest() + { + var cache = CacheFactory.Build(s => s.WithDictionaryHandle()); - // our cache manager instance should still be there so should the object we added in the - // previous step. - var checkTarget = container.Resolve(); - checkTarget.GetSomething(); - } + Console.WriteLine("Testing update..."); - private static void UnityInjectionExample_Advanced() + if (!cache.TryUpdate("test", v => "item has not yet been added", out string newValue)) { - var container = new UnityContainer(); - container.RegisterType( - typeof(ICacheManager<>), - new ContainerControlledLifetimeManager(), - new InjectionFactory( - (c, t, n) => CacheFactory.FromConfiguration( - t.GetGenericArguments()[0], - ConfigurationBuilder.BuildConfiguration(cfg => cfg.WithDictionaryHandle())))); - - var stringCache = container.Resolve>(); - - // testing if we create a singleton instance per type, every Resolve of the same type should return the same instance! - var stringCacheB = container.Resolve>(); - stringCache.Put("key", "something"); - - var intCache = container.Resolve>(); - var intCacheB = container.Resolve>(); - intCache.Put("key", 22); - - var boolCache = container.Resolve>(); - var boolCacheB = container.Resolve>(); - boolCache.Put("key", false); - - Console.WriteLine("Value type is: " + stringCache.GetType().GetGenericArguments()[0].Name + " test value: " + stringCacheB["key"]); - Console.WriteLine("Value type is: " + intCache.GetType().GetGenericArguments()[0].Name + " test value: " + intCacheB["key"]); - Console.WriteLine("Value type is: " + boolCache.GetType().GetGenericArguments()[0].Name + " test value: " + boolCacheB["key"]); + Console.WriteLine("Value not added?: {0}", newValue == null); } - private static void UpdateTest() - { - var cache = CacheFactory.Build(s => s.WithDictionaryHandle()); - - Console.WriteLine("Testing update..."); - - if (!cache.TryUpdate("test", v => "item has not yet been added", out string newValue)) - { - Console.WriteLine("Value not added?: {0}", newValue == null); - } - - cache.Add("test", "start"); - Console.WriteLine("Initial value: {0}", cache["test"]); + cache.Add("test", "start"); + Console.WriteLine("Initial value: {0}", cache["test"]); - cache.AddOrUpdate("test", "adding again?", v => "updating and not adding"); - Console.WriteLine("After AddOrUpdate: {0}", cache["test"]); + cache.AddOrUpdate("test", "adding again?", v => "updating and not adding"); + Console.WriteLine("After AddOrUpdate: {0}", cache["test"]); - cache.Remove("test"); - try - { - var removeValue = cache.Update("test", v => "updated?"); - } - catch - { - Console.WriteLine("Error as expected because item didn't exist."); - } - - // use try update to not deal with exceptions - if (!cache.TryUpdate("test", v => v, out string removedValue)) - { - Console.WriteLine("Value after remove is null?: {0}", removedValue == null); - } + cache.Remove("test"); + try + { + var removeValue = cache.Update("test", v => "updated?"); } - - private static void UpdateCounterTest() + catch { - var cache = CacheFactory.Build(s => s.WithDictionaryHandle()); - - Console.WriteLine("Testing update counter..."); - - cache.AddOrUpdate("counter", 0, v => v + 1); - - Console.WriteLine("Initial value: {0}", cache.Get("counter")); - - for (var i = 0; i < 12345; i++) - { - cache.Update("counter", v => v + 1); - } - - Console.WriteLine("Final value: {0}", cache.Get("counter")); + Console.WriteLine("Error as expected because item didn't exist."); } - private static void MultiCacheEvictionWithoutRedisCacheHandle() + // use try update to not deal with exceptions + if (!cache.TryUpdate("test", v => v, out string removedValue)) { - var config = new ConfigurationBuilder("Redis with Redis Backplane") - .WithDictionaryHandle(true) - .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(5)) - .And - .WithRedisBackplane("redisConfig") - .WithRedisConfiguration("redisConfig", "localhost,allowadmin=true", enableKeyspaceNotifications: true) - //.WithMicrosoftLogging(new LoggerFactory().AddConsole(LogLevel.Debug)) - .Build(); + Console.WriteLine("Value after remove is null?: {0}", removedValue == null); + } + } - var cacheA = new BaseCacheManager(config); - var cacheB = new BaseCacheManager(config); + private static void UpdateCounterTest() + { + var cache = CacheFactory.Build(s => s.WithDictionaryHandle()); - var key = "someKey"; + Console.WriteLine("Testing update counter..."); - cacheA.OnRemove += (s, args) => - { - Console.WriteLine("A triggered remove: " + args.ToString() + " - key still exists? " + cacheA.Exists(key)); - }; - cacheB.OnRemove += (s, args) => - { - Console.WriteLine("B triggered remove: " + args.ToString() + " - key still exists? " + cacheB.Exists(key)); - }; + cache.AddOrUpdate("counter", 0, v => v + 1); - cacheA.OnRemoveByHandle += (s, args) => - { - cacheA.Remove(args.Key); - Console.WriteLine("A triggered removeByHandle: " + args.ToString() + " - key still exists? " + cacheA.Exists(key)); - }; + Console.WriteLine("Initial value: {0}", cache.Get("counter")); - cacheB.OnRemoveByHandle += (s, args) => - { - Console.WriteLine("B triggered removeByHandle: " + args.ToString() + " - key still exists? " + cacheA.Exists(key) + " in A? " + cacheA.Exists(key)); - }; + for (var i = 0; i < 12345; i++) + { + cache.Update("counter", v => v + 1); + } - cacheA.OnAdd += (s, args) => - { - Console.WriteLine("A triggered add: " + args.ToString()); - }; + Console.WriteLine("Final value: {0}", cache.Get("counter")); + } - cacheB.OnAdd += (s, args) => - { - Console.WriteLine("B triggered add: " + args.ToString()); - }; + private static void MultiCacheEvictionWithoutRedisCacheHandle() + { + var config = new CacheConfigurationBuilder("Redis with Redis Backplane") + .WithDictionaryHandle(true) + .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(5)) + .And + .WithRedisBackplane("redisConfig") + .WithRedisConfiguration("redisConfig", "localhost,allowadmin=true", enableKeyspaceNotifications: true) + //.WithMicrosoftLogging(new LoggerFactory().AddConsole(LogLevel.Debug)) + .Build(); - Console.WriteLine("Add to A: " + cacheA.Add(key, "some value")); - Console.WriteLine("Add to B: " + cacheB.Add(key, "some value")); + var cacheA = new BaseCacheManager(config); + var cacheB = new BaseCacheManager(config); - Thread.Sleep(2000); - cacheA.Remove(key); - } - } + var key = "someKey"; - public class UnityInjectionExampleTarget - { - private ICacheManager _cache; + cacheA.OnRemove += (s, args) => + { + Console.WriteLine("A triggered remove: " + args.ToString() + " - key still exists? " + cacheA.Exists(key)); + }; + cacheB.OnRemove += (s, args) => + { + Console.WriteLine("B triggered remove: " + args.ToString() + " - key still exists? " + cacheB.Exists(key)); + }; - public UnityInjectionExampleTarget(ICacheManager cache) + cacheA.OnRemoveByHandle += (s, args) => { - _cache = cache ?? throw new ArgumentNullException(nameof(cache)); - } + cacheA.Remove(args.Key); + Console.WriteLine("A triggered removeByHandle: " + args.ToString() + " - key still exists? " + cacheA.Exists(key)); + }; - public void GetSomething() + cacheB.OnRemoveByHandle += (s, args) => { - var value = _cache.Get("myKey"); - var x = value; - if (value == null) - { - throw new InvalidOperationException(); - } - } + Console.WriteLine("B triggered removeByHandle: " + args.ToString() + " - key still exists? " + cacheA.Exists(key) + " in A? " + cacheA.Exists(key)); + }; - public void PutSomethingIntoTheCache() + cacheA.OnAdd += (s, args) => { - _cache.Put("myKey", "something"); - } + Console.WriteLine("A triggered add: " + args.ToString()); + }; + + cacheB.OnAdd += (s, args) => + { + Console.WriteLine("B triggered add: " + args.ToString()); + }; + + Console.WriteLine("Add to A: " + cacheA.Add(key, "some value")); + Console.WriteLine("Add to B: " + cacheB.Add(key, "some value")); + + Thread.Sleep(2000); + cacheA.Remove(key); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/BaseCacheManager.Expire.cs b/src/CacheManager.Core/BaseCacheManager.Expire.cs index ab1b7050..c67453c8 100644 --- a/src/CacheManager.Core/BaseCacheManager.Expire.cs +++ b/src/CacheManager.Core/BaseCacheManager.Expire.cs @@ -1,17 +1,18 @@ using System; using System.Linq; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; + namespace CacheManager.Core { public partial class BaseCacheManager { /// - public void Expire(string key, ExpirationMode mode, TimeSpan timeout) + public virtual void Expire(string key, ExpirationMode mode, TimeSpan timeout) => ExpireInternal(key, null, mode, timeout); /// - public void Expire(string key, string region, ExpirationMode mode, TimeSpan timeout) + public virtual void Expire(string key, string region, ExpirationMode mode, TimeSpan timeout) => ExpireInternal(key, region, mode, timeout); private void ExpireInternal(string key, string region, ExpirationMode mode, TimeSpan timeout) @@ -56,7 +57,7 @@ private void ExpireInternal(string key, string region, ExpirationMode mode, Time } /// - public void Expire(string key, DateTimeOffset absoluteExpiration) + public virtual void Expire(string key, DateTimeOffset absoluteExpiration) { var timeout = absoluteExpiration.UtcDateTime - DateTime.UtcNow; if (timeout <= TimeSpan.Zero) @@ -68,7 +69,7 @@ public void Expire(string key, DateTimeOffset absoluteExpiration) } /// - public void Expire(string key, string region, DateTimeOffset absoluteExpiration) + public virtual void Expire(string key, string region, DateTimeOffset absoluteExpiration) { var timeout = absoluteExpiration.UtcDateTime - DateTime.UtcNow; if (timeout <= TimeSpan.Zero) @@ -80,7 +81,7 @@ public void Expire(string key, string region, DateTimeOffset absoluteExpiration) } /// - public void Expire(string key, TimeSpan slidingExpiration) + public virtual void Expire(string key, TimeSpan slidingExpiration) { if (slidingExpiration <= TimeSpan.Zero) { @@ -91,7 +92,7 @@ public void Expire(string key, TimeSpan slidingExpiration) } /// - public void Expire(string key, string region, TimeSpan slidingExpiration) + public virtual void Expire(string key, string region, TimeSpan slidingExpiration) { if (slidingExpiration <= TimeSpan.Zero) { @@ -102,13 +103,13 @@ public void Expire(string key, string region, TimeSpan slidingExpiration) } /// - public void RemoveExpiration(string key) + public virtual void RemoveExpiration(string key) { Expire(key, ExpirationMode.None, default(TimeSpan)); } /// - public void RemoveExpiration(string key, string region) + public virtual void RemoveExpiration(string key, string region) { Expire(key, region, ExpirationMode.None, default(TimeSpan)); } diff --git a/src/CacheManager.Core/BaseCacheManager.GetOrAdd.cs b/src/CacheManager.Core/BaseCacheManager.GetOrAdd.cs index 6c023c34..1ae2e56b 100644 --- a/src/CacheManager.Core/BaseCacheManager.GetOrAdd.cs +++ b/src/CacheManager.Core/BaseCacheManager.GetOrAdd.cs @@ -6,16 +6,18 @@ namespace CacheManager.Core { public partial class BaseCacheManager { + private readonly object _tryAddLock = new object(); + /// - public TCacheValue GetOrAdd(string key, TCacheValue value) + public virtual TCacheValue GetOrAdd(string key, TCacheValue value) => GetOrAdd(key, (k) => value); /// - public TCacheValue GetOrAdd(string key, string region, TCacheValue value) + public virtual TCacheValue GetOrAdd(string key, string region, TCacheValue value) => GetOrAdd(key, region, (k, r) => value); /// - public TCacheValue GetOrAdd(string key, Func valueFactory) + public virtual TCacheValue GetOrAdd(string key, Func valueFactory) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(valueFactory, nameof(valueFactory)); @@ -24,7 +26,7 @@ public TCacheValue GetOrAdd(string key, Func valueFactory) } /// - public TCacheValue GetOrAdd(string key, string region, Func valueFactory) + public virtual TCacheValue GetOrAdd(string key, string region, Func valueFactory) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); @@ -34,7 +36,7 @@ public TCacheValue GetOrAdd(string key, string region, Func - public CacheItem GetOrAdd(string key, Func> valueFactory) + public virtual CacheItem GetOrAddCacheItem(string key, Func> valueFactory) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(valueFactory, nameof(valueFactory)); @@ -43,7 +45,7 @@ public CacheItem GetOrAdd(string key, Func - public CacheItem GetOrAdd(string key, string region, Func> valueFactory) + public virtual CacheItem GetOrAddCacheItem(string key, string region, Func> valueFactory) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); @@ -53,7 +55,7 @@ public CacheItem GetOrAdd(string key, string region, Func - public bool TryGetOrAdd(string key, Func valueFactory, out TCacheValue value) + public virtual bool TryGetOrAdd(string key, Func valueFactory, out TCacheValue value) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(valueFactory, nameof(valueFactory)); @@ -66,7 +68,7 @@ public bool TryGetOrAdd(string key, Func valueFactory, out var newValue = valueFactory(k); return newValue == null ? null : new CacheItem(k, newValue); }, - out CacheItem item)) + out var item)) { value = item.Value; return true; @@ -77,7 +79,7 @@ public bool TryGetOrAdd(string key, Func valueFactory, out } /// - public bool TryGetOrAdd(string key, string region, Func valueFactory, out TCacheValue value) + public virtual bool TryGetOrAdd(string key, string region, Func valueFactory, out TCacheValue value) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); @@ -91,7 +93,7 @@ public bool TryGetOrAdd(string key, string region, Func(k, r, newValue); }, - out CacheItem item)) + out var item)) { value = item.Value; return true; @@ -102,7 +104,7 @@ public bool TryGetOrAdd(string key, string region, Func - public bool TryGetOrAdd(string key, Func> valueFactory, out CacheItem item) + public virtual bool TryGetOrAddCacheItem(string key, Func> valueFactory, out CacheItem item) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(valueFactory, nameof(valueFactory)); @@ -111,7 +113,7 @@ public bool TryGetOrAdd(string key, Func> valueFa } /// - public bool TryGetOrAdd(string key, string region, Func> valueFactory, out CacheItem item) + public virtual bool TryGetOrAddCacheItem(string key, string region, Func> valueFactory, out CacheItem item) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); @@ -133,21 +135,24 @@ private bool TryGetOrAddInternal(string key, string region, Func GetOrAddInternal(string key, string region, Func< return item; } - // changed logic to invoke the factory only once in case of retries - if (newItem == null) - { - newItem = valueFactory(key, region); - } - - // Throw explicit to me more consistent. Otherwise it would throw later eventually... - if (newItem == null) - { - throw new InvalidOperationException("The CacheItem which should be added must not be null."); - } - - if (AddInternal(newItem)) + lock (_tryAddLock) { - return newItem; + // changed logic to invoke the factory only once in case of retries + if (newItem == null) + { + newItem = valueFactory(key, region); + } + + // Throw explicit to me more consistent. Otherwise it would throw later eventually... + if (newItem == null) + { + throw new InvalidOperationException("The CacheItem which should be added must not be null."); + } + + if (AddInternal(newItem)) + { + return newItem; + } } } while (tries <= Configuration.MaxRetries); diff --git a/src/CacheManager.Core/BaseCacheManager.Update.cs b/src/CacheManager.Core/BaseCacheManager.Update.cs index 5c57ee00..c05f25b8 100644 --- a/src/CacheManager.Core/BaseCacheManager.Update.cs +++ b/src/CacheManager.Core/BaseCacheManager.Update.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; +using System.Globalization; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core @@ -9,27 +9,27 @@ namespace CacheManager.Core public partial class BaseCacheManager { /// - public TCacheValue AddOrUpdate(string key, TCacheValue addValue, Func updateValue) => + public virtual TCacheValue AddOrUpdate(string key, TCacheValue addValue, Func updateValue) => AddOrUpdate(key, addValue, updateValue, Configuration.MaxRetries); /// - public TCacheValue AddOrUpdate(string key, string region, TCacheValue addValue, Func updateValue) => + public virtual TCacheValue AddOrUpdate(string key, string region, TCacheValue addValue, Func updateValue) => AddOrUpdate(key, region, addValue, updateValue, Configuration.MaxRetries); /// - public TCacheValue AddOrUpdate(string key, TCacheValue addValue, Func updateValue, int maxRetries) => + public virtual TCacheValue AddOrUpdate(string key, TCacheValue addValue, Func updateValue, int maxRetries) => AddOrUpdate(new CacheItem(key, addValue), updateValue, maxRetries); /// - public TCacheValue AddOrUpdate(string key, string region, TCacheValue addValue, Func updateValue, int maxRetries) => + public virtual TCacheValue AddOrUpdate(string key, string region, TCacheValue addValue, Func updateValue, int maxRetries) => AddOrUpdate(new CacheItem(key, region, addValue), updateValue, maxRetries); /// - public TCacheValue AddOrUpdate(CacheItem addItem, Func updateValue) => + public virtual TCacheValue AddOrUpdate(CacheItem addItem, Func updateValue) => AddOrUpdate(addItem, updateValue, Configuration.MaxRetries); /// - public TCacheValue AddOrUpdate(CacheItem addItem, Func updateValue, int maxRetries) + public virtual TCacheValue AddOrUpdate(CacheItem addItem, Func updateValue, int maxRetries) { NotNull(addItem, nameof(addItem)); NotNull(updateValue, nameof(updateValue)); @@ -97,19 +97,20 @@ private TCacheValue AddOrUpdateInternal(CacheItem item, Func - public bool TryUpdate(string key, Func updateValue, out TCacheValue value) => + public virtual bool TryUpdate(string key, Func updateValue, out TCacheValue value) => TryUpdate(key, updateValue, Configuration.MaxRetries, out value); /// - public bool TryUpdate(string key, string region, Func updateValue, out TCacheValue value) => + public virtual bool TryUpdate(string key, string region, Func updateValue, out TCacheValue value) => TryUpdate(key, region, updateValue, Configuration.MaxRetries, out value); /// - public bool TryUpdate(string key, Func updateValue, int maxRetries, out TCacheValue value) + public virtual bool TryUpdate(string key, Func updateValue, int maxRetries, out TCacheValue value) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(updateValue, nameof(updateValue)); @@ -119,7 +120,7 @@ public bool TryUpdate(string key, Func updateValue, in } /// - public bool TryUpdate(string key, string region, Func updateValue, int maxRetries, out TCacheValue value) + public virtual bool TryUpdate(string key, string region, Func updateValue, int maxRetries, out TCacheValue value) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); @@ -130,36 +131,40 @@ public bool TryUpdate(string key, string region, Func } /// - public TCacheValue Update(string key, Func updateValue) => + public virtual TCacheValue Update(string key, Func updateValue) => Update(key, updateValue, Configuration.MaxRetries); /// - public TCacheValue Update(string key, string region, Func updateValue) => + public virtual TCacheValue Update(string key, string region, Func updateValue) => Update(key, region, updateValue, Configuration.MaxRetries); /// - public TCacheValue Update(string key, Func updateValue, int maxRetries) + public virtual TCacheValue Update(string key, Func updateValue, int maxRetries) { NotNullOrWhiteSpace(key, nameof(key)); NotNull(updateValue, nameof(updateValue)); Ensure(maxRetries >= 0, "Maximum number of retries must be greater than or equal to zero."); - var value = default(TCacheValue); - UpdateInternal(_cacheHandles, key, updateValue, maxRetries, true, out value); + if (!UpdateInternal(_cacheHandles, key, updateValue, maxRetries, true, out var value)) + { + throw new InvalidOperationException($"Update failed for key '{key}'."); + } return value; } /// - public TCacheValue Update(string key, string region, Func updateValue, int maxRetries) + public virtual TCacheValue Update(string key, string region, Func updateValue, int maxRetries) { NotNullOrWhiteSpace(key, nameof(key)); NotNullOrWhiteSpace(region, nameof(region)); NotNull(updateValue, nameof(updateValue)); Ensure(maxRetries >= 0, "Maximum number of retries must be greater than or equal to zero."); - var value = default(TCacheValue); - UpdateInternal(_cacheHandles, key, region, updateValue, maxRetries, true, out value); + if (!UpdateInternal(_cacheHandles, key, region, updateValue, maxRetries, true, out var value)) + { + throw new InvalidOperationException($"Update failed for key '{region}:{key}'."); + } return value; } @@ -235,7 +240,7 @@ private bool UpdateInternal( } else if (result.UpdateState == UpdateItemResultState.FactoryReturnedNull) { - Logger.LogWarn($"Update failed on '{region}:{key}' because value factory returned null."); + Logger.LogWarning($"Update failed on '{region}:{key}' because value factory returned null."); if (throwOnFailure) { @@ -247,7 +252,7 @@ private bool UpdateInternal( // if we had too many retries, this basically indicates an // invalid state of the cache: The item is there, but we couldn't update it and // it most likely has a different version - Logger.LogWarn($"Update failed on '{region}:{key}' because of too many retries."); + Logger.LogWarning($"Update failed on '{region}:{key}' because of too many retries."); EvictFromOtherHandles(key, region, handleIndex); @@ -261,7 +266,7 @@ private bool UpdateInternal( // If update fails because item doesn't exist AND the current handle is backplane source or the lowest cache handle level, // remove the item from other handles (if exists). // Otherwise, if we do not exit here, calling update on the next handle might succeed and would return a misleading result. - Logger.LogInfo($"Update failed on '{region}:{key}' because the region/key did not exist."); + Logger.LogInformation($"Update failed on '{region}:{key}' because the region/key did not exist."); EvictFromOtherHandles(key, region, handleIndex); diff --git a/src/CacheManager.Core/BaseCacheManager.cs b/src/CacheManager.Core/BaseCacheManager.cs index 353f11bc..0455d38a 100644 --- a/src/CacheManager.Core/BaseCacheManager.cs +++ b/src/CacheManager.Core/BaseCacheManager.cs @@ -4,7 +4,7 @@ using System.Globalization; using System.Linq; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core @@ -18,6 +18,34 @@ namespace CacheManager.Core /// The type of the cache value. public partial class BaseCacheManager : BaseCache, ICacheManager, IDisposable { + private class NullLoggerFactory : ILoggerFactory + { + public void AddProvider(ILoggerProvider provider) + { + } + + public ILogger CreateLogger(string categoryName) + { + return new NullLogger(); + } + + public void Dispose() + { + } + } + + private class NullLogger : ILogger> + { + public IDisposable BeginScope(TState state) => null; + + public bool IsEnabled(LogLevel logLevel) => false; + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + // do nothing; + } + } + private readonly bool _logTrace = false; private readonly BaseCacheHandle[] _cacheHandles; private readonly CacheBackplane _cacheBackplane; @@ -31,49 +59,35 @@ public partial class BaseCacheManager : BaseCache, ICa /// /// The configuration which defines the structure and complexity of the cache manager. /// + /// Optional logger factory. /// /// When is null. /// /// - /// + /// /// - public BaseCacheManager(ICacheManagerConfiguration configuration) - : this(configuration?.Name ?? Guid.NewGuid().ToString(), configuration) + public BaseCacheManager(ICacheManagerConfiguration configuration, ILoggerFactory loggerFactory = null) + : this(configuration?.Name ?? Guid.NewGuid().ToString(), configuration, loggerFactory ?? new NullLoggerFactory()) { } - /// - /// Initializes a new instance of the class - /// using the specified and . - /// - /// The cache name. - /// - /// The configuration which defines the structure and complexity of the cache manager. - /// - /// - /// When or is null. - /// - /// - /// - /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2200:RethrowToPreserveStackDetails", Justification = "fine for now")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "nope")] - private BaseCacheManager(string name, ICacheManagerConfiguration configuration) + private BaseCacheManager(string name, ICacheManagerConfiguration configuration, ILoggerFactory loggerFactory) { NotNullOrWhiteSpace(name, nameof(name)); NotNull(configuration, nameof(configuration)); + NotNull(loggerFactory, nameof(loggerFactory)); Name = name; Configuration = configuration; - - var loggerFactory = CacheReflectionHelper.CreateLoggerFactory(configuration); var serializer = CacheReflectionHelper.CreateSerializer(configuration, loggerFactory); - Logger = loggerFactory.CreateLogger(this); + Logger = loggerFactory.CreateLogger(this.GetType()); _logTrace = Logger.IsEnabled(LogLevel.Trace); - Logger.LogInfo("Cache manager: adding cache handles..."); + Logger.LogInformation("Cache manager: adding cache handles..."); try { @@ -86,7 +100,7 @@ private BaseCacheManager(string name, ICacheManagerConfiguration configuration) handle.OnCacheSpecificRemove += (sender, args) => { // added sync for using backplane with in-memory caches on cache specific removal - // but commented for now, this is not really needed if all instances use the same expiration etc, would just cause dublicated events + // but commented for now, this is not really needed if all instances use the same expiration etc, would just cause duplicated events ////if (_cacheBackplane != null && handle.Configuration.IsBackplaneSource && !handle.IsDistributedCache) ////{ //// if (string.IsNullOrEmpty(args.Region)) @@ -111,7 +125,7 @@ private BaseCacheManager(string name, ICacheManagerConfiguration configuration) EvictFromHandlesAbove(args.Key, args.Region, handleIndex); } - // moving down below cleanup, optherwise the item could still be in memory + // moving down below cleanup, otherwise the item could still be in memory TriggerOnRemoveByHandle(args.Key, args.Region, args.Reason, handleIndex + 1, args.Value); }; @@ -521,7 +535,10 @@ protected override bool RemoveInternal(string key, string region) } } - if (result) + // See #311, send remove events anyways if the backlane is configured but no distributed cache is used. + var inProcOnly = _cacheHandles.Any(p => !p.IsDistributedCache); + + if (result || inProcOnly) { // update backplane if (_cacheBackplane != null) @@ -541,8 +558,11 @@ protected override bool RemoveInternal(string key, string region) } } - // trigger only once and not per handle - TriggerOnRemove(key, region); + if (result) + { + // trigger only once and not per handle + TriggerOnRemove(key, region); + } } return result; @@ -719,16 +739,16 @@ private void RegisterCacheBackplane(CacheBackplane backplane) if (_cacheHandles.Any(p => p.Configuration.IsBackplaneSource)) { // added includeSource param to get the handles which need to be synced. - // in case the backplane source is non-distributed (in-memory), only remotly triggered remove and clear should also - // trigger a sync locally. For distribtued caches, we expect that the distributed cache is already the source and in sync - // as that's the layer which triggered the event. In this case, only other in-memory handles above the distribtued, would be synced. - var handles = new Func[]>((includSource) => + // in case the backplane source is non-distributed (in-memory), only remotely triggered remove and clear should also + // trigger a sync locally. For distributed caches, we expect that the distributed cache is already the source and in sync + // as that's the layer which triggered the event. In this case, only other in-memory handles above the distributed, would be synced. + var handles = new Func[]>((includeSource) => { var handleList = new List>(); foreach (var handle in _cacheHandles) { if (!handle.Configuration.IsBackplaneSource || - (includSource && handle.Configuration.IsBackplaneSource && !handle.IsDistributedCache)) + (includeSource && handle.Configuration.IsBackplaneSource && !handle.IsDistributedCache)) { handleList.Add(handle); } diff --git a/src/CacheManager.Core/CacheFactory.cs b/src/CacheManager.Core/CacheFactory.cs index eae952ec..45784664 100644 --- a/src/CacheManager.Core/CacheFactory.cs +++ b/src/CacheManager.Core/CacheFactory.cs @@ -1,7 +1,7 @@ using System; using System.Linq; using System.Reflection; -using CacheManager.Core.Configuration; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core @@ -25,7 +25,6 @@ public static class CacheFactory /// settings /// .WithUpdateMode(CacheUpdateMode.Up) /// .WithDictionaryHandle() - /// .EnablePerformanceCounters() /// .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); /// }); /// @@ -38,6 +37,7 @@ public static class CacheFactory /// The configuration. Use the settings element to configure the cache manager instance, add /// cache handles and also to configure the cache handles in a fluent way. /// + /// Optional logger factory. /// The cache manager instance with cache item type being System.Object. /// /// @@ -46,8 +46,8 @@ public static class CacheFactory /// /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager Build(string cacheName, Action settings) => - Build(cacheName, settings); + public static ICacheManager Build(string cacheName, Action settings, ILoggerFactory loggerFactory = null) => + Build(cacheName, settings, loggerFactory); /// /// Instantiates a cache manager using the inline configuration defined by . @@ -63,7 +63,6 @@ public static ICacheManager Build(string cacheName, Action Build(string cacheName, Action + /// Optional logger factory. /// The cache manager instance. /// /// @@ -83,8 +83,8 @@ public static ICacheManager Build(string cacheName, Action /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager Build(Action settings) => - Build(Guid.NewGuid().ToString("N"), settings); + public static ICacheManager Build(Action settings, ILoggerFactory loggerFactory = null) => + Build(Guid.NewGuid().ToString("N"), settings, loggerFactory); /// /// Instantiates a cache manager using the inline configuration defined by . @@ -99,7 +99,6 @@ public static ICacheManager Build(Action /// settings /// .WithUpdateMode(CacheUpdateMode.Up) /// .WithDictionaryHandle() - /// .EnablePerformanceCounters() /// .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); /// }); /// @@ -112,6 +111,7 @@ public static ICacheManager Build(Action /// The configuration. Use the settings element to configure the cache manager instance, add /// cache handles and also to configure the cache handles in a fluent way. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance with cache item type being TCacheValue. /// @@ -121,14 +121,17 @@ public static ICacheManager Build(Action /// /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager Build(string cacheName, Action settings) + public static ICacheManager Build( + string cacheName, + Action settings, + ILoggerFactory loggerFactory = null) { NotNull(settings, nameof(settings)); var part = new ConfigurationBuilderCachePart(); settings(part); part.Configuration.Name = cacheName; - return new BaseCacheManager(part.Configuration); + return new BaseCacheManager(part.Configuration, loggerFactory); } /// @@ -144,7 +147,6 @@ public static ICacheManager Build(string cacheName, Ac /// settings /// .WithUpdateMode(CacheUpdateMode.Up) /// .WithDictionaryHandle() - /// .EnablePerformanceCounters() /// .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); /// }); /// @@ -156,6 +158,7 @@ public static ICacheManager Build(string cacheName, Ac /// The configuration. Use the settings element to configure the cache manager instance, add /// cache handles and also to configure the cache handles in a fluent way. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance with cache item type being TCacheValue. /// @@ -165,8 +168,8 @@ public static ICacheManager Build(string cacheName, Ac /// /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager Build(Action settings) - => Build(Guid.NewGuid().ToString("N"), settings); + public static ICacheManager Build(Action settings, ILoggerFactory loggerFactory = null) + => Build(Guid.NewGuid().ToString("N"), settings, loggerFactory); /// /// Instantiates a cache manager using the given type and the inline configuration defined by . @@ -182,7 +185,6 @@ public static ICacheManager Build(Action Build(Action + /// Optional logger factory. /// The cache manager instance. /// /// Thrown if the or is null. @@ -202,19 +205,14 @@ public static ICacheManager Build(Action /// Thrown on certain configuration errors related to the cache handles. /// - public static object Build(Type cacheValueType, string cacheName, Action settings) + public static object Build(Type cacheValueType, string cacheName, Action settings, ILoggerFactory loggerFactory = null) { NotNull(cacheValueType, nameof(cacheValueType)); -#if !NET40 + var factoryType = typeof(CacheFactory).GetTypeInfo(); var buildMethod = factoryType.GetDeclaredMethods("Build").First(p => p.IsGenericMethod); -#else - var factoryType = typeof(CacheFactory); - var buildMethod = factoryType.GetMethods(BindingFlags.Static | BindingFlags.Public) - .First(p => p.Name == "Build" && p.IsGenericMethod); -#endif var genericMethod = buildMethod.MakeGenericMethod(cacheValueType); - return genericMethod.Invoke(null, new object[] { cacheName, settings }); + return genericMethod.Invoke(null, new object[] { cacheName, settings, loggerFactory }); } /// @@ -231,7 +229,6 @@ public static object Build(Type cacheValueType, string cacheName, Action + /// Optional logger factory. /// The cache manager instance. /// /// Thrown if is null. @@ -250,10 +248,8 @@ public static object Build(Type cacheValueType, string cacheName, Action /// Thrown on certain configuration errors related to the cache handles. /// - public static object Build(Type cacheValueType, Action settings) - => Build(cacheValueType, Guid.NewGuid().ToString("N"), settings); - -#if !NETSTANDARD + public static object Build(Type cacheValueType, Action settings, ILoggerFactory loggerFactory = null) + => Build(cacheValueType, Guid.NewGuid().ToString("N"), settings, loggerFactory); /// /// Instantiates a cache manager from app.config or web.config. @@ -275,6 +271,7 @@ public static object Build(Type cacheValueType, Action /// The name of the cache, must also match with the configured cache name. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance. /// @@ -286,11 +283,11 @@ public static object Build(Type cacheValueType, Action - public static ICacheManager FromConfiguration(string cacheName) + public static ICacheManager FromConfiguration(string cacheName, ILoggerFactory loggerFactory = null) { - var cfg = ConfigurationBuilder.LoadConfiguration(cacheName); + var cfg = CacheConfigurationBuilder.LoadConfiguration(cacheName); - return CacheFactory.FromConfiguration(cacheName, cfg); + return CacheFactory.FromConfiguration(cacheName, cfg, loggerFactory); } /// @@ -306,6 +303,7 @@ public static ICacheManager FromConfiguration(string c /// /// The name of the cache, must also match with the configured cache name. /// + /// Optional logger factory. /// The cache manager instance. /// /// Thrown if the or is null or an empty. @@ -315,11 +313,11 @@ public static ICacheManager FromConfiguration(string c /// Thrown if no cacheManager section is defined or on certain configuration errors related /// to the cache handles. /// - public static object FromConfiguration(Type cacheValueType, string cacheName) + public static object FromConfiguration(Type cacheValueType, string cacheName, ILoggerFactory loggerFactory = null) { - var cfg = ConfigurationBuilder.LoadConfiguration(cacheName); + var cfg = CacheConfigurationBuilder.LoadConfiguration(cacheName); - return CacheFactory.FromConfiguration(cacheValueType, cacheName, cfg); + return CacheFactory.FromConfiguration(cacheValueType, cacheName, cfg, loggerFactory); } /// @@ -343,6 +341,7 @@ public static object FromConfiguration(Type cacheValueType, string cacheName) /// /// The cache manager section name. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance. /// @@ -354,11 +353,11 @@ public static object FromConfiguration(Type cacheValueType, string cacheName) /// Thrown if no cacheManager section is defined or on certain configuration errors related /// to the cache handles. /// - public static ICacheManager FromConfiguration(string cacheName, string sectionName) + public static ICacheManager FromConfiguration(string cacheName, string sectionName, ILoggerFactory loggerFactory = null) { - var cfg = ConfigurationBuilder.LoadConfiguration(sectionName, cacheName); + var cfg = CacheConfigurationBuilder.LoadConfiguration(sectionName, cacheName); - return CacheFactory.FromConfiguration(cacheName, cfg); + return CacheFactory.FromConfiguration(cacheName, cfg, loggerFactory); } /// @@ -375,6 +374,7 @@ public static ICacheManager FromConfiguration(string c /// /// The cache manager section name. /// + /// Optional logger factory. /// The cache manager instance. /// /// Thrown if the , or @@ -385,15 +385,13 @@ public static ICacheManager FromConfiguration(string c /// Thrown if no cacheManager section is defined or on certain configuration errors related /// to the cache handles. /// - public static object FromConfiguration(Type cacheValueType, string cacheName, string sectionName) + public static object FromConfiguration(Type cacheValueType, string cacheName, string sectionName, ILoggerFactory loggerFactory = null) { - var cfg = ConfigurationBuilder.LoadConfiguration(sectionName, cacheName); + var cfg = CacheConfigurationBuilder.LoadConfiguration(sectionName, cacheName); - return CacheFactory.FromConfiguration(cacheValueType, cacheName, cfg); + return CacheFactory.FromConfiguration(cacheValueType, cacheName, cfg, loggerFactory); } -#endif - /// /// Instantiates a cache manager using the given . /// @@ -401,21 +399,25 @@ public static object FromConfiguration(Type cacheValueType, string cacheName, st /// /// The configured which will be used to configure the cache manager instance. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance. - /// + /// /// /// Thrown if the is null. /// /// /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager FromConfiguration(string cacheName, ICacheManagerConfiguration configuration) + public static ICacheManager FromConfiguration( + string cacheName, + ICacheManagerConfiguration configuration, + ILoggerFactory loggerFactory = null) { NotNull(configuration, nameof(configuration)); var cfg = (CacheManagerConfiguration)configuration; cfg.Name = cacheName; - return new BaseCacheManager(cfg); + return new BaseCacheManager(cfg, loggerFactory); } /// @@ -430,7 +432,6 @@ public static ICacheManager FromConfiguration(string c /// { /// settings.WithUpdateMode(CacheUpdateMode.Up) /// .WithDictionaryCacheHandle>() - /// .EnablePerformanceCounters() /// .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(10)); /// }); /// @@ -442,17 +443,20 @@ public static ICacheManager FromConfiguration(string c /// /// The configured which will be used to configure the cache manager instance. /// + /// Optional logger factory. /// The type of the cache item value. /// The cache manager instance. - /// + /// /// /// Thrown if the is null. /// /// /// Thrown on certain configuration errors related to the cache handles. /// - public static ICacheManager FromConfiguration(ICacheManagerConfiguration configuration) - => FromConfiguration(Guid.NewGuid().ToString("N"), configuration); + public static ICacheManager FromConfiguration( + ICacheManagerConfiguration configuration, + ILoggerFactory loggerFactory = null) + => FromConfiguration(Guid.NewGuid().ToString("N"), configuration, loggerFactory); /// /// Instantiates a cache manager using the given and . @@ -464,15 +468,20 @@ public static ICacheManager FromConfiguration(ICacheMa /// /// The configured which will be used to configure the cache manager instance. /// + /// Optional logger factory. /// The cache manager instance. - /// + /// /// /// Thrown if the cacheValueType, cacheName or configuration is null. /// /// /// Thrown on certain configuration errors related to the cache handles. /// - public static object FromConfiguration(Type cacheValueType, string cacheName, ICacheManagerConfiguration configuration) + public static object FromConfiguration( + Type cacheValueType, + string cacheName, + ICacheManagerConfiguration configuration, + ILoggerFactory loggerFactory = null) { NotNull(cacheValueType, nameof(cacheValueType)); NotNull(configuration, nameof(configuration)); @@ -481,7 +490,7 @@ public static object FromConfiguration(Type cacheValueType, string cacheName, IC cfg.Name = cacheName; var type = typeof(BaseCacheManager<>).MakeGenericType(new[] { cacheValueType }); - return Activator.CreateInstance(type, new object[] { cfg }); + return Activator.CreateInstance(type, new object[] { cfg, loggerFactory }); } /// @@ -493,15 +502,19 @@ public static object FromConfiguration(Type cacheValueType, string cacheName, IC /// /// The configured which will be used to configure the cache manager instance. /// + /// Optional logger factory. /// The cache manager instance. - /// + /// /// /// Thrown if the or are null. /// /// /// Thrown on certain configuration errors related to the cache handles. /// - public static object FromConfiguration(Type cacheValueType, ICacheManagerConfiguration configuration) - => FromConfiguration(cacheValueType, Guid.NewGuid().ToString("N"), configuration); + public static object FromConfiguration( + Type cacheValueType, + ICacheManagerConfiguration configuration, + ILoggerFactory loggerFactory = null) + => FromConfiguration(cacheValueType, Guid.NewGuid().ToString("N"), configuration, loggerFactory); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/CacheHandleConfiguration.cs b/src/CacheManager.Core/CacheHandleConfiguration.cs index 018cdd6e..873204c9 100644 --- a/src/CacheManager.Core/CacheHandleConfiguration.cs +++ b/src/CacheManager.Core/CacheHandleConfiguration.cs @@ -45,16 +45,6 @@ public CacheHandleConfiguration(string handleName, string configurationKey) Key = configurationKey; } - /// - /// Gets or sets a value indicating whether performance counters should be enabled or not. - /// - /// If enabled, and the initialization of performance counters doesn't work, for example - /// because of security reasons. The counters will get disabled silently. - /// - /// - /// true if performance counters should be enable; otherwise, false. - public bool EnablePerformanceCounters { get; set; } - /// /// Gets or sets a value indicating whether statistics should be enabled. /// @@ -111,4 +101,4 @@ public override string ToString() return $"{HandleType}"; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/CacheItem.cs b/src/CacheManager.Core/CacheItem.cs index d39e6df8..10750617 100644 --- a/src/CacheManager.Core/CacheItem.cs +++ b/src/CacheManager.Core/CacheItem.cs @@ -1,7 +1,7 @@ using System; using CacheManager.Core.Internal; -#if !NETSTANDARD +#if !NETSTANDARD2_0 using System.Runtime.Serialization; @@ -16,7 +16,7 @@ namespace CacheManager.Core /// information needed by the cache handles and manager. /// /// The type of the cache value. -#if !NETSTANDARD +#if !NETSTANDARD2_0 [Serializable] public class CacheItem : ISerializable, ICacheItemProperties @@ -83,7 +83,7 @@ protected CacheItem() { } -#if !NETSTANDARD +#if !NETSTANDARD2_0 /// /// Initializes a new instance of the class. @@ -226,17 +226,17 @@ public bool IsExpired /// public bool UsesExpirationDefaults { get; } = true; -#if !NETSTANDARD +#if !NETSTANDARD2_0 /// - /// Populates a with the data + /// Populates a with the data /// needed to serialize the target object. /// /// - /// The to populate with data. + /// The to populate with data. /// /// - /// The destination (see ) for + /// The destination (see ) for /// this serialization. /// /// If info is null. @@ -359,4 +359,4 @@ public CacheItem WithValue(T value) => public CacheItem WithCreated(DateTime created) => new CacheItem(Key, Region, Value, ExpirationMode, ExpirationTimeout, created, LastAccessedUtc, UsesExpirationDefaults); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/CacheManager.Core.csproj b/src/CacheManager.Core/CacheManager.Core.csproj index 0e184b17..ae67b32a 100644 --- a/src/CacheManager.Core/CacheManager.Core.csproj +++ b/src/CacheManager.Core/CacheManager.Core.csproj @@ -2,19 +2,25 @@ CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. The Core library contains all base interfaces and tools. You should install at least one other CacheManager package to get cache handle implementations. - net40;net45;netstandard1.2 + net472;netstandard2.0;netstandard2.1;net80 False - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + Caching;Cache;CacheManager;Distributed Cache;Redis; + true - - + + + + + + + + + - + - - $(DefineConstants);NETSTANDARD - - + + - \ No newline at end of file + diff --git a/src/CacheManager.Core/CacheManagerConfiguration.cs b/src/CacheManager.Core/CacheManagerConfiguration.cs index 6755fb38..6af770f1 100644 --- a/src/CacheManager.Core/CacheManagerConfiguration.cs +++ b/src/CacheManager.Core/CacheManagerConfiguration.cs @@ -17,11 +17,11 @@ public CacheManagerConfiguration() } /// - /// Gets a for the current instance + /// Gets a for the current instance /// to manipulate the configuration fluently. /// - /// The . - public ConfigurationBuilder Builder => new ConfigurationBuilder(this); + /// The . + public CacheConfigurationBuilder Builder => new CacheConfigurationBuilder(this); /// /// Gets or sets the name of the cache. diff --git a/src/CacheManager.Core/Configuration/ConfigurationBuilder.cs b/src/CacheManager.Core/Configuration/CacheConfigurationBuilder.cs similarity index 88% rename from src/CacheManager.Core/Configuration/ConfigurationBuilder.cs rename to src/CacheManager.Core/Configuration/CacheConfigurationBuilder.cs index ad2d97f9..f0f3e4fc 100644 --- a/src/CacheManager.Core/Configuration/ConfigurationBuilder.cs +++ b/src/CacheManager.Core/Configuration/CacheConfigurationBuilder.cs @@ -1,17 +1,13 @@ using System; using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using CacheManager.Core.Internal; - -#if !NETSTANDARD using System.Configuration; +using System.Globalization; using System.IO; -using System.Runtime.Serialization.Formatters.Binary; +using System.Linq; using System.Text.RegularExpressions; using CacheManager.Core.Configuration; -#endif - +using CacheManager.Core.Internal; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core @@ -25,27 +21,26 @@ namespace CacheManager.Core /// /// /// - public class ConfigurationBuilder : ConfigurationBuilderCachePart + public class CacheConfigurationBuilder : ConfigurationBuilderCachePart { private const string Hours = "h"; private const string Minutes = "m"; - private const string Seconds = "s"; /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// which provides fluent configuration methods. /// - public ConfigurationBuilder() + public CacheConfigurationBuilder() : base() { } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// which provides fluent configuration methods. /// /// The name of the cache manager. - public ConfigurationBuilder(string name) + public CacheConfigurationBuilder(string name) : base() { NotNullOrWhiteSpace(name, nameof(name)); @@ -53,25 +48,25 @@ public ConfigurationBuilder(string name) } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// which provides fluent configuration methods. /// Creates a builder which allows to modify the existing . /// /// The configuration the builder should be instantiated for. - public ConfigurationBuilder(ICacheManagerConfiguration forConfiguration) + public CacheConfigurationBuilder(ICacheManagerConfiguration forConfiguration) : base((CacheManagerConfiguration)forConfiguration) { } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// which provides fluent configuration methods. /// Creates a builder which allows to modify the existing . /// /// The name of the cache manager. /// The configuration the builder should be instantiated for. - public ConfigurationBuilder(string name, ICacheManagerConfiguration forConfiguration) - : base((CacheManagerConfiguration)forConfiguration) + public CacheConfigurationBuilder(string name, ICacheManagerConfiguration forConfiguration) + : base(NotNull((CacheManagerConfiguration)forConfiguration, nameof(forConfiguration))) { NotNullOrWhiteSpace(name, nameof(name)); Configuration.Name = name; @@ -81,7 +76,7 @@ public ConfigurationBuilder(string name, ICacheManagerConfiguration forConfigura /// Builds a which can be used to create a new cache /// manager instance. /// - /// Pass the configuration to + /// Pass the configuration to /// to create a valid cache manager. /// /// @@ -93,7 +88,7 @@ public static ICacheManagerConfiguration BuildConfiguration(Action which can be used to create a new cache /// manager instance. /// - /// Pass the configuration to + /// Pass the configuration to /// to create a valid cache manager. /// /// @@ -116,14 +111,12 @@ public static ICacheManagerConfiguration BuildConfiguration(string name, Action< NotNullOrWhiteSpace(name, nameof(name)); NotNull(settings, nameof(settings)); - var part = new ConfigurationBuilder(); + var part = new CacheConfigurationBuilder(); settings(part); part.Configuration.Name = name; return part.Configuration; } -#if !NETSTANDARD - /// /// Loads a configuration from web.config or app.config. /// @@ -318,7 +311,6 @@ internal static CacheManagerConfiguration LoadFromSection(CacheManagerSection se ExpirationMode = handleDef.ExpirationMode, ExpirationTimeout = handleDef.ExpirationTimeout, EnableStatistics = managerCfg.EnableStatistics, - EnablePerformanceCounters = managerCfg.EnablePerformanceCounters, IsBackplaneSource = handleItem.IsBackplaneSource }; @@ -397,8 +389,6 @@ private static TimeSpan GetTimeSpan(string timespanCfgValue, string propName) // last option would be seconds return TimeSpan.FromSeconds(timeoutValue); } - -#endif } /// @@ -433,16 +423,6 @@ public ICacheManagerConfiguration Build() return _parent.Build(); } - /// - /// Disables performance counters for this cache handle. - /// - /// The builder part. - public ConfigurationBuilderCacheHandlePart DisablePerformanceCounters() - { - Configuration.EnablePerformanceCounters = false; - return this; - } - /// /// Disables statistic gathering for this cache handle. /// This also disables performance counters as statistics are required for the counters. @@ -451,19 +431,6 @@ public ConfigurationBuilderCacheHandlePart DisablePerformanceCounters() public ConfigurationBuilderCacheHandlePart DisableStatistics() { Configuration.EnableStatistics = false; - Configuration.EnablePerformanceCounters = false; - return this; - } - - /// - /// Enables performance counters for this cache handle. - /// This also enables statistics, as this is required for performance counters. - /// - /// The builder part. - public ConfigurationBuilderCacheHandlePart EnablePerformanceCounters() - { - Configuration.EnablePerformanceCounters = true; - Configuration.EnableStatistics = true; return this; } @@ -596,9 +563,10 @@ public ConfigurationBuilderCachePart WithBackplane(Type backplaneType, string co /// Set this to true if this cache handle should be the source of the backplane. /// This setting will be ignored if no backplane is configured. /// + /// Optional settings for the cache instance. /// The builder part. - public ConfigurationBuilderCacheHandlePart WithDictionaryHandle(bool isBackplaneSource = false) => - WithHandle(typeof(DictionaryCacheHandle<>), Guid.NewGuid().ToString("N"), isBackplaneSource); + public ConfigurationBuilderCacheHandlePart WithDictionaryHandle(bool isBackplaneSource = false, DictionaryCacheOptions options = null) => + WithHandle(typeof(DictionaryCacheHandle<>), Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture), isBackplaneSource, options == null ? new object[0] : new[] { options }); /// /// Adds a cache dictionary cache handle to the cache manager. @@ -609,9 +577,10 @@ public ConfigurationBuilderCacheHandlePart WithDictionaryHandle(bool isBackplane /// Set this to true if this cache handle should be the source of the backplane. /// This setting will be ignored if no backplane is configured. /// + /// Optional settings for the cache instance. /// Thrown if is null. - public ConfigurationBuilderCacheHandlePart WithDictionaryHandle(string handleName, bool isBackplaneSource = false) => - WithHandle(typeof(DictionaryCacheHandle<>), handleName, isBackplaneSource); + public ConfigurationBuilderCacheHandlePart WithDictionaryHandle(string handleName, bool isBackplaneSource = false, DictionaryCacheOptions options = null) => + WithHandle(typeof(DictionaryCacheHandle<>), handleName, isBackplaneSource, options == null ? new object[0] : new[] { options }); /// /// Adds a cache handle with the given Type and name. @@ -748,47 +717,20 @@ public ConfigurationBuilderCachePart WithSerializer(Type serializerType, params return this; } -#if !NETSTANDARD - - /// - /// Configures a to be used for serialization and deserialization. - /// - /// The builder part. - public ConfigurationBuilderCachePart WithBinarySerializer() - { - Configuration.SerializerType = typeof(BinaryCacheSerializer); - return this; - } - - /// - /// Configures a to be used for serialization and deserialization. - /// - /// The for serialization. - /// The for deserialization. - /// The builder part. - public ConfigurationBuilderCachePart WithBinarySerializer(BinaryFormatter serializationFormatter, BinaryFormatter deserializationFormatter) - { - Configuration.SerializerType = typeof(BinaryCacheSerializer); - Configuration.SerializerTypeArguments = new object[] { serializationFormatter, deserializationFormatter }; - return this; - } - -#endif - - /// - /// Enables logging by setting the for the cache manager instance. - /// - /// The type of the logger factory. - /// Additional arguments the type might need to get initialized. - /// The builder part. - public ConfigurationBuilderCachePart WithLogging(Type loggerFactoryType, params object[] args) - { - NotNull(loggerFactoryType, nameof(loggerFactoryType)); - - Configuration.LoggerFactoryType = loggerFactoryType; - Configuration.LoggerFactoryTypeArguments = args; - return this; - } + /////// + /////// Enables logging by setting the for the cache manager instance. + /////// + /////// The type of the logger factory. + /////// Additional arguments the type might need to get initialized. + /////// The builder part. + ////public ConfigurationBuilderCachePart WithLogging(Type loggerFactoryType, params object[] args) + ////{ + //// NotNull(loggerFactoryType, nameof(loggerFactoryType)); + + //// Configuration.LoggerFactoryType = loggerFactoryType; + //// Configuration.LoggerFactoryTypeArguments = args; + //// return this; + ////} /// /// Hands back the new instance. diff --git a/src/CacheManager.Core/Configuration/CacheManagerSection.cs b/src/CacheManager.Core/Configuration/CacheManagerSection.cs index 2a6d6912..bcef8c12 100644 --- a/src/CacheManager.Core/Configuration/CacheManagerSection.cs +++ b/src/CacheManager.Core/Configuration/CacheManagerSection.cs @@ -1,7 +1,5 @@ namespace CacheManager.Core.Configuration { -#if !NETSTANDARD - using System; using System.Collections.Generic; using System.ComponentModel; @@ -19,7 +17,6 @@ public sealed class CacheManagerSection : ConfigurationSection private const string HandlesName = "cacheHandles"; private const string ManagersName = "managers"; - private const string RedisName = "redis"; /// /// Gets the cache handle definitions. @@ -143,7 +140,7 @@ public CacheHandleDefinitionCollection() /// Returns an enumerator that iterates through the collection. /// /// - /// A that can be used to iterate + /// A that can be used to iterate /// through the collection. /// public new IEnumerator GetEnumerator() @@ -157,21 +154,21 @@ public CacheHandleDefinitionCollection() } /// - /// When overridden in a derived class, creates a new . + /// When overridden in a derived class, creates a new . /// - /// A new . + /// A new . protected override ConfigurationElement CreateNewElement() => new CacheHandleDefinition(); /// /// Gets the element key for a specified configuration element when overridden in a derived class. /// /// - /// The to return the key for. + /// The to return the key for. /// /// - /// An that acts as the key for the specified . + /// An that acts as the key for the specified . /// - protected override object GetElementKey(ConfigurationElement element) => ((CacheHandleDefinition)element).Id; + protected override object GetElementKey(ConfigurationElement element) => ((CacheHandleDefinition)element)?.Id; } /// @@ -183,7 +180,7 @@ public sealed class CacheManagerCollection : ConfigurationElementCollection, IEn /// Returns an enumerator that iterates through the collection. /// /// - /// A that can be used to iterate + /// A that can be used to iterate /// through the collection. /// public new IEnumerator GetEnumerator() @@ -197,21 +194,21 @@ public sealed class CacheManagerCollection : ConfigurationElementCollection, IEn } /// - /// When overridden in a derived class, creates a new . + /// When overridden in a derived class, creates a new . /// - /// A new . + /// A new . protected override ConfigurationElement CreateNewElement() => new CacheManagerHandleCollection(); /// /// Gets the element key for a specified configuration element when overridden in a derived class. /// /// - /// The to return the key for. + /// The to return the key for. /// /// - /// An that acts as the key for the specified . + /// An that acts as the key for the specified . /// - protected override object GetElementKey(ConfigurationElement element) => ((CacheManagerHandleCollection)element).Name; + protected override object GetElementKey(ConfigurationElement element) => ((CacheManagerHandleCollection)element)?.Name; } /// @@ -321,7 +318,6 @@ public sealed class CacheManagerHandleCollection : ConfigurationElementCollectio private const string BackplaneNameKey = "backplaneName"; private const string BackplaneTypeKey = "backplaneType"; private const string SerializerTypeKey = "serializerType"; - private const string EnablePerformanceCountersKey = "enablePerformanceCounters"; private const string EnableStatisticsKey = "enableStatistics"; private const string MaxRetriesKey = "maxRetries"; private const string NameKey = "name"; @@ -387,23 +383,6 @@ public string SerializerType } } - /// - /// Gets or sets a value indicating whether performance counters should be enabled. - /// - /// true if performance counters should be enabled; otherwise, false. - [ConfigurationProperty(EnablePerformanceCountersKey, IsRequired = false, DefaultValue = false)] - public bool EnablePerformanceCounters - { - get - { - return (bool)this[EnablePerformanceCountersKey]; - } - set - { - this[EnablePerformanceCountersKey] = value; - } - } - /// /// Gets or sets a value indicating whether statistics should be enabled. /// @@ -493,7 +472,7 @@ public CacheUpdateMode UpdateMode /// Returns an enumerator that iterates through the collection. /// /// - /// A that can be used to iterate + /// A that can be used to iterate /// through the collection. /// public new IEnumerator GetEnumerator() @@ -507,22 +486,20 @@ public CacheUpdateMode UpdateMode } /// - /// When overridden in a derived class, creates a new . + /// When overridden in a derived class, creates a new . /// - /// A new . + /// A new . protected override ConfigurationElement CreateNewElement() => new CacheManagerHandle(); /// /// Gets the element key for a specified configuration element when overridden in a derived class. /// /// - /// The to return the key for. + /// The to return the key for. /// /// - /// An that acts as the key for the specified . + /// An that acts as the key for the specified . /// - protected override object GetElementKey(ConfigurationElement element) => ((CacheManagerHandle)element).Name; + protected override object GetElementKey(ConfigurationElement element) => ((CacheManagerHandle)element)?.Name; } - -#endif -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/ExpirationMode.cs b/src/CacheManager.Core/ExpirationMode.cs index c7b46146..e05c2ca9 100644 --- a/src/CacheManager.Core/ExpirationMode.cs +++ b/src/CacheManager.Core/ExpirationMode.cs @@ -7,7 +7,7 @@ public enum ExpirationMode { /// - /// Default value for the expircation mode enum. + /// Default value for the expiration mode enum. /// CacheManager will default to None. The Default entry in the enum is used as separation from the other values /// and to make it possible to explicitly set the expiration to None. /// @@ -28,4 +28,4 @@ public enum ExpirationMode /// Absolute = 3 } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/ICacheManager.cs b/src/CacheManager.Core/ICacheManager.cs index f8e4665c..0492276a 100644 --- a/src/CacheManager.Core/ICacheManager.cs +++ b/src/CacheManager.Core/ICacheManager.cs @@ -347,7 +347,7 @@ public interface ICacheManager : ICache /// /// If either or is null. /// - CacheItem GetOrAdd(string key, Func> valueFactory); + CacheItem GetOrAddCacheItem(string key, Func> valueFactory); /// /// Returns an existing item or adds the item to the cache if it does not exist. @@ -360,7 +360,7 @@ public interface ICacheManager : ICache /// /// If either or is null. /// - CacheItem GetOrAdd(string key, string region, Func> valueFactory); + CacheItem GetOrAddCacheItem(string key, string region, Func> valueFactory); /// /// Tries to either retrieve an existing item or add the item to the cache if it does not exist. @@ -399,7 +399,7 @@ public interface ICacheManager : ICache /// /// If either or is null. /// - bool TryGetOrAdd(string key, Func> valueFactory, out CacheItem item); + bool TryGetOrAddCacheItem(string key, Func> valueFactory, out CacheItem item); /// /// Tries to either retrieve an existing item or add the item to the cache if it does not exist. @@ -412,7 +412,7 @@ public interface ICacheManager : ICache /// /// If either or is null. /// - bool TryGetOrAdd(string key, string region, Func> valueFactory, out CacheItem item); + bool TryGetOrAddCacheItem(string key, string region, Func> valueFactory, out CacheItem item); /// /// Updates an existing key in the cache. diff --git a/src/CacheManager.Core/ICacheManagerConfiguration.cs b/src/CacheManager.Core/ICacheManagerConfiguration.cs index 97573ce7..241e9700 100644 --- a/src/CacheManager.Core/ICacheManagerConfiguration.cs +++ b/src/CacheManager.Core/ICacheManagerConfiguration.cs @@ -4,7 +4,7 @@ namespace CacheManager.Core { /// - /// The writable configuration contract used primarrily internal only + /// The writable configuration contract used primarily internal only /// public interface ICacheManagerConfiguration : IReadOnlyCacheManagerConfiguration { @@ -15,11 +15,11 @@ public interface ICacheManagerConfiguration : IReadOnlyCacheManagerConfiguration IList CacheHandleConfigurations { get; } /// - /// Gets a for the current instance + /// Gets a for the current instance /// to manipulate the configuration fluently. /// - /// The . - ConfigurationBuilder Builder { get; } + /// The . + CacheConfigurationBuilder Builder { get; } } /// @@ -92,6 +92,10 @@ public interface IReadOnlyCacheManagerConfiguration /// Gets the number of milliseconds the cache should wait before it will retry an action. /// Default is 100. /// + /// + /// This does not have any effect in synchronous context. + /// Will be brought back if CacheManager has async overloads. + /// /// The retry timeout. int RetryTimeout { get; } @@ -119,4 +123,4 @@ public interface IReadOnlyCacheManagerConfiguration /// CacheUpdateMode UpdateMode { get; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/BackplaneMessage.cs b/src/CacheManager.Core/Internal/BackplaneMessage.cs index 936c8559..af5c3a86 100644 --- a/src/CacheManager.Core/Internal/BackplaneMessage.cs +++ b/src/CacheManager.Core/Internal/BackplaneMessage.cs @@ -529,7 +529,7 @@ public byte[] ReadBytes(int length) throw new IndexOutOfRangeException("Cannot read bytes, no additional bytes available."); } - // fix: length check before aloc + // fix: length check before alloc var result = new byte[length]; Buffer.BlockCopy(_data, pos - length, result, 0, length); return result; @@ -553,4 +553,4 @@ public string ReadString() } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/BaseCache.cs b/src/CacheManager.Core/Internal/BaseCache.cs index afee1e4e..0de563ba 100644 --- a/src/CacheManager.Core/Internal/BaseCache.cs +++ b/src/CacheManager.Core/Internal/BaseCache.cs @@ -1,6 +1,6 @@ using System; using System.Globalization; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core.Internal @@ -58,14 +58,8 @@ protected internal BaseCache() /// If the is null. public virtual TCacheValue this[string key] { - get - { - return Get(key); - } - set - { - Put(key, value); - } + get => Get(key); + set => Put(key, value); } /// @@ -84,17 +78,10 @@ public virtual TCacheValue this[string key] /// /// If the or is null. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1023:IndexersShouldNotBeMultidimensional", Justification = "We need both overloads.")] public virtual TCacheValue this[string key, string region] { - get - { - return Get(key, region); - } - set - { - Put(key, value, region); - } + get => Get(key, region); + set => Put(key, value, region); } /// @@ -204,17 +191,16 @@ public void Dispose() /// The key being used to identify the item within the cache. /// The value being stored in the cache for the given . /// If the is null. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Maybe at some point.")] public virtual TCacheValue Get(string key) { var item = GetCacheItem(key); - if (item != null && item.Key.Equals(key)) + if (item != null && item.Key.Equals(key, StringComparison.OrdinalIgnoreCase)) { return item.Value; } - return default(TCacheValue); + return default; } /// @@ -228,17 +214,19 @@ public virtual TCacheValue Get(string key) /// /// If the or is null. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Maybe at some point.")] public virtual TCacheValue Get(string key, string region) { var item = GetCacheItem(key, region); - if (item != null && item.Key.Equals(key) && item.Region != null && item.Region.Equals(region)) + if (item != null + && item.Key.Equals(key, StringComparison.OrdinalIgnoreCase) + && item.Region != null + && item.Region.Equals(region, StringComparison.OrdinalIgnoreCase)) { return item.Value; } - return default(TCacheValue); + return default; } /// @@ -251,7 +239,6 @@ public virtual TCacheValue Get(string key, string region) /// /// If no explicit cast is defined from TCacheValue to TOut. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Maybe at some point.")] public virtual TOut Get(string key) { object value = Get(key); @@ -273,7 +260,6 @@ public virtual TOut Get(string key) /// /// If no explicit cast is defined from TCacheValue to TOut. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Maybe at some point.")] public virtual TOut Get(string key, string region) { object value = Get(key, region); @@ -500,7 +486,7 @@ protected static TOut GetCasted(object value) { if (value == null) { - return default(TOut); + return default; } try @@ -514,4 +500,4 @@ protected static TOut GetCasted(object value) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/BaseCacheHandle.cs b/src/CacheManager.Core/Internal/BaseCacheHandle.cs index 1f1c77d2..ed0f3c50 100644 --- a/src/CacheManager.Core/Internal/BaseCacheHandle.cs +++ b/src/CacheManager.Core/Internal/BaseCacheHandle.cs @@ -1,5 +1,5 @@ using System; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core.Internal @@ -11,7 +11,7 @@ namespace CacheManager.Core.Internal /// Actually it is not advisable to not use . /// /// The type of the cache value. - public abstract class BaseCacheHandle : BaseCache, IDisposable + public abstract class BaseCacheHandle : BaseCache { private readonly object _updateLock = new object(); @@ -35,8 +35,7 @@ protected BaseCacheHandle(ICacheManagerConfiguration managerConfiguration, Cache Stats = new CacheStats( managerConfiguration.Name, Configuration.Name, - Configuration.EnableStatistics, - Configuration.EnablePerformanceCounters); + Configuration.EnableStatistics); } /// @@ -45,7 +44,7 @@ protected BaseCacheHandle(ICacheManagerConfiguration managerConfiguration, Cache /// /// The value will be evaluated by the backplane logic to figure out what to do if remote events are received. /// - /// If the cache handle is distributed, a remote remove event for example does not cause another Remove call. + /// If the cache handle is distributed, a remote remove event for example does not cause another Remove call. /// For in-memory cache handles which are backplane source though, it would trigger a Remove. /// /// @@ -244,7 +243,6 @@ protected override void Dispose(bool disposeManaged) { if (disposeManaged) { - Stats.Dispose(); } base.Dispose(disposeManaged); @@ -301,4 +299,4 @@ protected virtual CacheItem GetItemExpiration(CacheItemThe CacheItem to be added to the cache. protected abstract void PutInternalPrepared(CacheItem item); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/BinaryCacheSerializer.cs b/src/CacheManager.Core/Internal/BinaryCacheSerializer.cs deleted file mode 100644 index e190b587..00000000 --- a/src/CacheManager.Core/Internal/BinaryCacheSerializer.cs +++ /dev/null @@ -1,96 +0,0 @@ -#if !NETSTANDARD -using System; -using System.IO; -using System.Runtime.Serialization.Formatters; -using System.Runtime.Serialization.Formatters.Binary; -using CacheManager.Core.Utility; - -namespace CacheManager.Core.Internal -{ - /// - /// Basic binary serialization implementation of the . - /// This implementation will be used in case no other serializer is configured for the cache manager - /// and serialization is needed (only distributed caches will have to serialize the cache value). - /// Binary serialization will not be available in some environments. - /// - public class BinaryCacheSerializer : ICacheSerializer - { - /// - /// Initializes a new instance of the class. - /// - /// The formatter to use to do the serialization. - /// The formatter to use to do the deserialization. - public BinaryCacheSerializer(BinaryFormatter serializationFormatter, BinaryFormatter deserializationFormatter) - { - Guard.NotNull(serializationFormatter, nameof(serializationFormatter)); - Guard.NotNull(deserializationFormatter, nameof(deserializationFormatter)); - - SerializationFormatter = serializationFormatter; - DeserializationFormatter = deserializationFormatter; - } - - /// - /// Initializes a new instance of the class. - /// - public BinaryCacheSerializer() - { - DeserializationFormatter = SerializationFormatter = new BinaryFormatter() - { - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - } - - /// - /// Gets the formatter which should be used during deserialization. - /// If nothing is specified the default will be used. - /// - /// The deserialization formatter. - public BinaryFormatter DeserializationFormatter { get; } - - /// - /// Gets the formatter which should be used during serialization. - /// If nothing is specified the default will be used. - /// - /// The serialization formatter. - public BinaryFormatter SerializationFormatter { get; } - - /// - public object Deserialize(byte[] data, Type target) - { - if (data == null) - { - return null; - } - - using (var memoryStream = new MemoryStream(data)) - { - return DeserializationFormatter.Deserialize(memoryStream); - } - } - - /// - public CacheItem DeserializeCacheItem(byte[] value, Type valueType) - => (CacheItem)Deserialize(value, valueType); - - /// - public byte[] Serialize(T value) - { - if (value == null) - { - return null; - } - - using (var memoryStream = new MemoryStream()) - { - SerializationFormatter.Serialize(memoryStream, value); - var objectDataAsStream = memoryStream.ToArray(); - return objectDataAsStream; - } - } - - /// - public byte[] SerializeCacheItem(CacheItem value) - => Serialize(value); - } -} -#endif \ No newline at end of file diff --git a/src/CacheManager.Core/Internal/CacheEventArgs.cs b/src/CacheManager.Core/Internal/CacheEventArgs.cs index 73756ada..ee442f40 100644 --- a/src/CacheManager.Core/Internal/CacheEventArgs.cs +++ b/src/CacheManager.Core/Internal/CacheEventArgs.cs @@ -39,7 +39,7 @@ public enum CacheItemRemovedReason /// A was removed manually, without using CacheManager APIs (like using del via redis-cli). /// /// - /// This will eventually trigger a for the responsible cache layer and + /// This will eventually trigger a for the responsible cache layer and /// as the item has been removed. /// ExternalDelete = 99 @@ -95,7 +95,7 @@ public CacheItemRemovedEventArgs(string key, string region, CacheItemRemovedReas /// /// Gets the original cached value which was removed by this event. /// - /// The property might return Null if the underlying cache system doesn't + /// The property might return Null if the underlying cache system doesn't /// support returning the value on eviction (for example Redis). /// /// @@ -132,7 +132,7 @@ public CacheActionEventArgs(string key, string region) /// /// The key. /// The region. - /// The origin the event ocured. If remote, the event got triggered by the backplane and was not actually excecuted locally. + /// The origin the event occurred. If remote, the event got triggered by the backplane and was not actually executed locally. /// If key is null. public CacheActionEventArgs(string key, string region, CacheActionEventArgOrigin origin) : this(key, region) @@ -153,7 +153,7 @@ public CacheActionEventArgs(string key, string region, CacheActionEventArgOrigin public string Region { get; } /// - /// Gets the event origin indicating if the event was triggered by a local action or remotly, through the backplane. + /// Gets the event origin indicating if the event was triggered by a local action or remotely, through the backplane. /// public CacheActionEventArgOrigin Origin { get; } = CacheActionEventArgOrigin.Local; @@ -172,14 +172,14 @@ public sealed class CacheClearEventArgs : EventArgs /// /// Initializes a new instance of the class. /// - /// The origin the event ocured. If remote, the event got triggered by the backplane and was not actually excecuted locally. + /// The origin the event occurred. If remote, the event got triggered by the backplane and was not actually executed locally. public CacheClearEventArgs(CacheActionEventArgOrigin origin = CacheActionEventArgOrigin.Local) { Origin = origin; } /// - /// Gets the event origin indicating if the event was triggered by a local action or remotly, through the backplane. + /// Gets the event origin indicating if the event was triggered by a local action or remotely, through the backplane. /// public CacheActionEventArgOrigin Origin { get; } @@ -199,7 +199,7 @@ public sealed class CacheClearRegionEventArgs : EventArgs /// Initializes a new instance of the class. /// /// The region. - /// The origin the event ocured. If remote, the event got triggered by the backplane and was not actually excecuted locally. + /// The origin the event occurred. If remote, the event got triggered by the backplane and was not actually executed locally. /// If region is null. public CacheClearRegionEventArgs(string region, CacheActionEventArgOrigin origin = CacheActionEventArgOrigin.Local) { @@ -216,7 +216,7 @@ public CacheClearRegionEventArgs(string region, CacheActionEventArgOrigin origin public string Region { get; } /// - /// Gets the event origin indicating if the event was triggered by a local action or remotly, through the backplane. + /// Gets the event origin indicating if the event was triggered by a local action or remotely, through the backplane. /// public CacheActionEventArgOrigin Origin { get; } @@ -226,4 +226,4 @@ public override string ToString() return $"CacheClearRegionEventArgs {Region} - {Origin}"; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/CachePerformanceCounterType.cs b/src/CacheManager.Core/Internal/CachePerformanceCounterType.cs deleted file mode 100644 index 6756be13..00000000 --- a/src/CacheManager.Core/Internal/CachePerformanceCounterType.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace CacheManager.Core.Internal -{ - /// - /// Supported performance counter types. - /// - internal enum CachePerformanceCounterType - { - /// - /// The number of items. - /// - Items, - - /// - /// The hit ratio. - /// - HitRatio, - - /// - /// The hit ratio base. - /// - HitRatioBase, - - /// - /// The total hits. - /// - TotalHits, - - /// - /// The total misses. - /// - TotalMisses, - - /// - /// The total writes. - /// - TotalWrites, - - /// - /// The reads per second. - /// - ReadsPerSecond, - - /// - /// The writes per second. - /// - WritesPerSecond, - - /// - /// The hits per second. - /// - HitsPerSecond, - } -} \ No newline at end of file diff --git a/src/CacheManager.Core/Internal/CachePerformanceCounters.cs b/src/CacheManager.Core/Internal/CachePerformanceCounters.cs deleted file mode 100644 index 42bce0b2..00000000 --- a/src/CacheManager.Core/Internal/CachePerformanceCounters.cs +++ /dev/null @@ -1,271 +0,0 @@ -namespace CacheManager.Core.Internal -{ -#if !NETSTANDARD - using System; - using System.Diagnostics; - using System.Threading; - using static CacheManager.Core.Utility.Guard; - - internal class CachePerformanceCounters : IDisposable - { - private const string Category = ".NET CacheManager"; - private const string Entries = "Total cache items"; - private const string HitRatio = "Hit ratio"; - private const string HitRatioBase = "Cache hit ratio Base"; - private const string Hits = "Total hits"; - private const string HitsPerSecond = "Avg hits per second"; - private const string Misses = "Total misses"; - private const string ReadsPerSecond = "Avg gets per second"; - private const string Writes = "Total cache writes"; - private const string WritesPerSecond = "Avg writes per second"; - private static readonly int _numStatsCounters = Enum.GetValues(typeof(CacheStatsCounterType)).Length; - - private readonly Timer _counterTimer; - private readonly string _instanceName = string.Empty; - private readonly CacheStats _stats; - private readonly long[] _statsCounts; - private PerformanceCounter[] _counters; - private bool _enabled = true; - private object _updateLock = new object(); - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Mobility", "CA1601:DoNotUseTimersThatPreventPowerStateChanges", Justification = "If perfCounters are enabled, we can live with the power consumption...")] - public CachePerformanceCounters(string cacheName, string handleName, CacheStats stats) - { - NotNullOrWhiteSpace(cacheName, nameof(cacheName)); - - NotNullOrWhiteSpace(handleName, nameof(handleName)); - - var processName = Process.GetCurrentProcess().ProcessName; - - _instanceName = string.Concat(processName + ":" + cacheName + ":" + handleName); - - var invalidInstanceChars = new string[] { "(", ")", "#", "\\", "/" }; - - foreach (var ichar in invalidInstanceChars) - { - _instanceName = _instanceName.Replace(ichar, string.Empty); - } - - if (_instanceName.Length > 128) - { - _instanceName = _instanceName.Substring(0, 128); - } - - InitializeCounters(); - _stats = stats; - _statsCounts = new long[_numStatsCounters]; - - if (_enabled) - { - _counterTimer = new Timer(new TimerCallback(PerformanceCounterWorker), null, 450L, 450L); - } - } - - ~CachePerformanceCounters() - { - Dispose(false); - } - - public void Decrement(CachePerformanceCounterType type) - { - GetCounter(type).Decrement(); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public void Increment(CachePerformanceCounterType type) - { - GetCounter(type).Increment(); - } - - public void IncrementBy(CachePerformanceCounterType type, long value) - { - GetCounter(type).IncrementBy(value); - } - - public void SetValue(CachePerformanceCounterType type, long value) - { - GetCounter(type).RawValue = value < 0 ? 0 : value; - } - - private static void InitializeCategory() - { - if (PerformanceCounterCategory.Exists(Category)) - { - return; - } - - PerformanceCounterCategory.Create( - Category, - "CacheManager counters per handle", - PerformanceCounterCategoryType.MultiInstance, - new CounterCreationDataCollection - { - new CounterCreationData - { - CounterName = Entries, - CounterHelp = "Current number of cache items stored within the cache handle", - CounterType = PerformanceCounterType.NumberOfItems64 - }, - new CounterCreationData - { - CounterName = HitRatio, - CounterHelp = "Cache hit ratio of the cache handle", - CounterType = PerformanceCounterType.AverageCount64 - }, - new CounterCreationData - { - CounterName = HitRatioBase, - CounterHelp = HitRatioBase, - CounterType = PerformanceCounterType.AverageBase - }, - new CounterCreationData - { - CounterName = Hits, - CounterHelp = "Total number of cache hits of the cache handle", - CounterType = PerformanceCounterType.NumberOfItems64 - }, - new CounterCreationData - { - CounterName = Misses, - CounterHelp = "Total number of cache misses of the cache handle", - CounterType = PerformanceCounterType.NumberOfItems64 - }, - new CounterCreationData - { - CounterName = Writes, - CounterHelp = "Total number of cache writes (add,put,remove) of the cache handle", - CounterType = PerformanceCounterType.NumberOfItems64 - }, - new CounterCreationData - { - CounterName = WritesPerSecond, - CounterHelp = WritesPerSecond, - CounterType = PerformanceCounterType.RateOfCountsPerSecond64 - }, - new CounterCreationData - { - CounterName = ReadsPerSecond, - CounterHelp = ReadsPerSecond, - CounterType = PerformanceCounterType.RateOfCountsPerSecond64 - }, - new CounterCreationData - { - CounterName = HitsPerSecond, - CounterHelp = HitsPerSecond, - CounterType = PerformanceCounterType.RateOfCountsPerSecond64 - }, - }); - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "On Dispose the catch is just for safety...")] - private void Dispose(bool disposeManaged) - { - if (disposeManaged) - { - try - { - ResetCounters(); - - if (_counterTimer != null) - { - _counterTimer.Dispose(); - } - - foreach (var counter in _counters) - { - counter.Dispose(); - } - } - catch - { - } - } - } - - private PerformanceCounter GetCounter(CachePerformanceCounterType type) => _counters[(int)type]; - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "At this point its fine")] - private void InitializeCounters() - { - try - { - InitializeCategory(); - - _counters = new PerformanceCounter[9]; - _counters[0] = new PerformanceCounter(Category, Entries, _instanceName, false); - _counters[1] = new PerformanceCounter(Category, HitRatio, _instanceName, false); - _counters[2] = new PerformanceCounter(Category, HitRatioBase, _instanceName, false); - _counters[3] = new PerformanceCounter(Category, Hits, _instanceName, false); - _counters[4] = new PerformanceCounter(Category, Misses, _instanceName, false); - _counters[5] = new PerformanceCounter(Category, Writes, _instanceName, false); - _counters[6] = new PerformanceCounter(Category, ReadsPerSecond, _instanceName, false); - _counters[7] = new PerformanceCounter(Category, WritesPerSecond, _instanceName, false); - _counters[8] = new PerformanceCounter(Category, HitsPerSecond, _instanceName, false); - - // resetting them cleans up previous runs on the same category, which will otherwise - // stay in perfmon forever - ResetCounters(); - } - catch - { - _enabled = false; - } - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Is just fine at that point.")] - private void PerformanceCounterWorker(object state) - { - if (_enabled && Monitor.TryEnter(_updateLock)) - { - try - { - var previousCounts = new long[_numStatsCounters]; - Array.Copy(_statsCounts, previousCounts, _numStatsCounters); - - for (var i = 0; i < _numStatsCounters; i++) - { - _statsCounts[i] = _stats.GetStatistic((CacheStatsCounterType)i); - } - - var writes = _statsCounts[4] + _statsCounts[5] + _statsCounts[7] + _statsCounts[8]; - var previousWrites = previousCounts[4] + previousCounts[5] + previousCounts[7] + previousCounts[8]; - var hits = _statsCounts[0] - previousCounts[0]; - - SetValue(CachePerformanceCounterType.Items, _statsCounts[2]); - - IncrementBy(CachePerformanceCounterType.HitRatioBase, _statsCounts[6] - previousCounts[6]); - IncrementBy(CachePerformanceCounterType.HitRatio, hits); - IncrementBy(CachePerformanceCounterType.TotalHits, hits); - IncrementBy(CachePerformanceCounterType.TotalMisses, _statsCounts[1] - previousCounts[1]); - IncrementBy(CachePerformanceCounterType.TotalWrites, writes - previousWrites); - IncrementBy(CachePerformanceCounterType.ReadsPerSecond, _statsCounts[6] - previousCounts[6]); - IncrementBy(CachePerformanceCounterType.WritesPerSecond, writes - previousWrites); - IncrementBy(CachePerformanceCounterType.HitsPerSecond, hits); - } - catch (Exception e) - { - _enabled = false; - Trace.TraceError(e.Message + "\n" + e.StackTrace); - } - finally - { - Monitor.Exit(_updateLock); - } - } - } - - private void ResetCounters() - { - for (var i = 0; i < Enum.GetValues(typeof(CachePerformanceCounterType)).Length; i++) - { - SetValue((CachePerformanceCounterType)i, 0L); - } - } - } -#endif -} \ No newline at end of file diff --git a/src/CacheManager.Core/Internal/CacheReflectionHelper.cs b/src/CacheManager.Core/Internal/CacheReflectionHelper.cs index 65ababe1..2ea35431 100644 --- a/src/CacheManager.Core/Internal/CacheReflectionHelper.cs +++ b/src/CacheManager.Core/Internal/CacheReflectionHelper.cs @@ -3,44 +3,38 @@ using System.Globalization; using System.Linq; using System.Reflection; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core.Internal { internal static class CacheReflectionHelper { - internal static ILoggerFactory CreateLoggerFactory(ICacheManagerConfiguration configuration) - { - NotNull(configuration, nameof(configuration)); + ////internal static ILoggerFactory CreateLoggerFactory(ICacheManagerConfiguration configuration) + ////{ + //// NotNull(configuration, nameof(configuration)); - if (configuration.LoggerFactoryType == null) - { - return new NullLoggerFactory(); - } + //// if (configuration.LoggerFactoryType == null) + //// { + //// return new NullLoggerFactory(); + //// } - CheckImplements(configuration.LoggerFactoryType); + //// CheckImplements(configuration.LoggerFactoryType); - var args = new object[] { configuration }; - if (configuration.LoggerFactoryTypeArguments != null) - { - args = configuration.LoggerFactoryTypeArguments.Concat(args).ToArray(); - } + //// var args = new object[] { configuration }; + //// if (configuration.LoggerFactoryTypeArguments != null) + //// { + //// args = configuration.LoggerFactoryTypeArguments.Concat(args).ToArray(); + //// } - return (ILoggerFactory)CreateInstance(configuration.LoggerFactoryType, args); - } + //// return (ILoggerFactory)CreateInstance(configuration.LoggerFactoryType, args); + ////} internal static ICacheSerializer CreateSerializer(ICacheManagerConfiguration configuration, ILoggerFactory loggerFactory) { NotNull(configuration, nameof(configuration)); NotNull(loggerFactory, nameof(loggerFactory)); -#if !NETSTANDARD - if (configuration.SerializerType == null) - { - return new BinaryCacheSerializer(); - } -#endif if (configuration.SerializerType != null) { CheckImplements(configuration.SerializerType); @@ -93,19 +87,16 @@ internal static ICollection> CreateCacheHandles>(); foreach (var handleConfiguration in managerConfiguration.CacheHandleConfigurations) { - logger.LogInfo("Creating handle {0} of type {1}.", handleConfiguration.Name, handleConfiguration.HandleType); + logger.LogInformation("Creating handle {0} of type {1}.", handleConfiguration.Name, handleConfiguration.HandleType); var handleType = handleConfiguration.HandleType; var requiresSerializer = false; -#if !NETSTANDARD - requiresSerializer = handleType.GetCustomAttributes(typeof(RequiresSerializerAttribute), false).Any(); -#else + requiresSerializer = handleType.GetTypeInfo().CustomAttributes.Any(p => p.AttributeType == typeof(RequiresSerializerAttribute)); -#endif if (requiresSerializer && serializer == null) { @@ -118,11 +109,9 @@ internal static ICollection> CreateCacheHandles is not // defined ) -#if NET40 - if (handleType.IsGenericTypeDefinition) -#else + if (handleType.GetTypeInfo().IsGenericTypeDefinition) -#endif + { instanceType = handleType.MakeGenericType(new Type[] { typeof(TCacheValue) }); } @@ -171,18 +160,14 @@ internal static ICollection> CreateCacheHandles !p.IsStatic && p.IsPublic) .OrderByDescending(p => p.GetParameters().Length) .ToArray(); - if (constructors.Count() == 0) + if (!constructors.Any()) { throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "No matching public non static constructor found for type {0}.", instanceType.FullName)); @@ -229,15 +214,10 @@ private static object[] MatchArguments(IEnumerable constructors foreach (var param in parameters) { -#if NET40 - var paramValue = instancesCopy - .Where(p => p != null) - .FirstOrDefault(p => param.ParameterType.IsAssignableFrom(p.GetType())); -#else var paramValue = instancesCopy .Where(p => p != null) .FirstOrDefault(p => param.ParameterType.GetTypeInfo().IsAssignableFrom(p.GetType().GetTypeInfo())); -#endif + if (paramValue == null) { lastParamMiss = param; @@ -258,7 +238,7 @@ private static object[] MatchArguments(IEnumerable constructors if (constructors.Any(p => p.GetParameters().Length == 0)) { // no match found, will try empty ctor - return new object[] { }; + return new object[0]; } // give more detailed error of what failed @@ -267,35 +247,24 @@ private static object[] MatchArguments(IEnumerable constructors var ctorTypes = string.Join(", ", lastCtor.GetParameters().Select(p => p.ParameterType.Name).ToArray()); throw new InvalidOperationException( - $"Could not find a matching constructor for type '{lastCtor.DeclaringType.Name}'. Trying to match [{ctorTypes}] but missing {lastParamMiss.ParameterType.Name}"); + $"Could not find a matching constructor for type '{lastCtor.DeclaringType?.Name}'. Trying to match [{ctorTypes}] but missing {lastParamMiss.ParameterType?.Name}"); } throw new InvalidOperationException( - $"Could not find a matching or empty constructor for type '{lastCtor.DeclaringType.Name}'."); + $"Could not find a matching or empty constructor for type '{lastCtor.DeclaringType?.Name}'."); } private static IEnumerable GetGenericBaseTypes(this Type type) { -#if NET40 - var baseType = type.BaseType; - if (baseType == null || !baseType.IsGenericType) -#else var baseType = type.GetTypeInfo().BaseType; if (baseType == null || !baseType.GetTypeInfo().IsGenericType) -#endif { return Enumerable.Empty(); } -#if NET40 - var genericBaseType = baseType.IsGenericTypeDefinition ? baseType : baseType.GetGenericTypeDefinition(); - return Enumerable.Repeat(genericBaseType, 1) - .Concat(baseType.GetGenericBaseTypes()); -#else var genericBaseType = baseType.GetTypeInfo().IsGenericTypeDefinition ? baseType : baseType.GetGenericTypeDefinition(); return Enumerable.Repeat(genericBaseType, 1) .Concat(baseType.GetGenericBaseTypes()); -#endif } private static void ValidateCacheHandleGenericTypeArguments(Type handle) @@ -310,12 +279,7 @@ private static void ValidateCacheHandleGenericTypeArguments(Type handle) handle.ToString())); } -#if NETSTANDARD - var handleInfo = handle.GetTypeInfo(); - if (handleInfo.IsGenericType && !handleInfo.IsGenericTypeDefinition) -#else if (handle.IsGenericType && !handle.IsGenericTypeDefinition) -#endif { throw new InvalidOperationException( string.Format( @@ -327,12 +291,8 @@ private static void ValidateCacheHandleGenericTypeArguments(Type handle) private static void CheckImplements(Type type) { -#if NETSTANDARD - var typeInfo = type.GetTypeInfo(); - var interfaces = typeInfo.ImplementedInterfaces; -#else var interfaces = type.GetInterfaces(); -#endif + Ensure( interfaces.Any(p => p == typeof(TValid)), "Type must implement {0}, but {1} does not.", @@ -342,11 +302,7 @@ private static void CheckImplements(Type type) private static void CheckExtends(Type type) { -#if NETSTANDARD - var baseType = type.GetTypeInfo().BaseType; -#else var baseType = type.BaseType; -#endif while (baseType != typeof(object)) { @@ -354,11 +310,8 @@ private static void CheckExtends(Type type) { return; } -#if NETSTANDARD - baseType = type.GetTypeInfo().BaseType; -#else - baseType = type.BaseType; -#endif + + baseType = baseType.BaseType; } throw new InvalidOperationException( @@ -368,4 +321,4 @@ private static void CheckExtends(Type type) typeof(TValid).Name)); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/CacheSerializer.cs b/src/CacheManager.Core/Internal/CacheSerializer.cs index 083842b9..ac4a55f9 100644 --- a/src/CacheManager.Core/Internal/CacheSerializer.cs +++ b/src/CacheManager.Core/Internal/CacheSerializer.cs @@ -46,7 +46,7 @@ public virtual CacheItem DeserializeCacheItem(byte[] value, Type valueType var targetType = GetOpenGeneric().MakeGenericType(valueType); var item = (ICacheItemConverter)Deserialize(value, targetType); - return item.ToCacheItem(); + return item?.ToCacheItem(); } private object CreateFromCacheItem(CacheItem source) @@ -64,4 +64,4 @@ private object CreateFromCacheItem(CacheItem source) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/CacheStats.cs b/src/CacheManager.Core/Internal/CacheStats.cs index 34f06b8e..45aa9ac4 100644 --- a/src/CacheManager.Core/Internal/CacheStats.cs +++ b/src/CacheManager.Core/Internal/CacheStats.cs @@ -20,16 +20,13 @@ namespace CacheManager.Core.Internal /// class is sealed. /// /// Inherited object type of the owning cache handle. - public sealed class CacheStats : IDisposable + public sealed class CacheStats { private static readonly string _nullRegionKey = Guid.NewGuid().ToString(); private readonly ConcurrentDictionary _counters; - private readonly bool _isPerformanceCounterEnabled; private readonly bool _isStatsEnabled; -#if !NETSTANDARD - private readonly CachePerformanceCounters _performanceCounters; -#endif + // TODO: remove parameter. /// /// Initializes a new instance of the class. /// @@ -39,46 +36,17 @@ public sealed class CacheStats : IDisposable /// If set to true the stats are enabled. Otherwise any statistics and performance /// counters will be disabled. /// - /// - /// If set to true performance counters and statistics will be enabled. - /// /// /// If cacheName or handleName are null. /// - public CacheStats(string cacheName, string handleName, bool enabled = true, bool enablePerformanceCounters = false) + public CacheStats(string cacheName, string handleName, bool enabled = true) { NotNullOrWhiteSpace(cacheName, nameof(cacheName)); NotNullOrWhiteSpace(handleName, nameof(handleName)); // if performance counters are enabled, stats must be enabled, too. - _isStatsEnabled = enablePerformanceCounters ? true : enabled; - _isPerformanceCounterEnabled = enablePerformanceCounters; + _isStatsEnabled = enabled; _counters = new ConcurrentDictionary(); - -#if !NETSTANDARD - if (_isPerformanceCounterEnabled) - { - _performanceCounters = new CachePerformanceCounters(cacheName, handleName, this); - } -#endif - } - - /// - /// Finalizes an instance of the class. - /// - ~CacheStats() - { - Dispose(false); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting - /// unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); } /// @@ -215,8 +183,7 @@ public void OnClear() // clear needs a lock, otherwise we might mess up the overall counts foreach (var key in _counters.Keys) { - CacheStatsCounter counter = null; - if (_counters.TryGetValue(key, out counter)) + if (_counters.TryGetValue(key, out var counter)) { counter.Set(CacheStatsCounterType.Items, 0L); counter.Increment(CacheStatsCounterType.ClearCalls); @@ -369,25 +336,11 @@ public void OnUpdate(string key, string region, UpdateItemResult re } } - private void Dispose(bool disposeManaged) - { - if (disposeManaged) - { -#if !NETSTANDARD - if (_isPerformanceCounterEnabled) - { - _performanceCounters.Dispose(); - } -#endif - } - } - private CacheStatsCounter GetCounter(string key) { NotNullOrWhiteSpace(key, nameof(key)); - CacheStatsCounter counter = null; - if (!_counters.TryGetValue(key, out counter)) + if (!_counters.TryGetValue(key, out var counter)) { counter = new CacheStatsCounter(); if (_counters.TryAdd(key, counter)) @@ -405,7 +358,7 @@ private IEnumerable GetWorkingCounters(string region) { yield return GetCounter(_nullRegionKey); - if (!string.IsNullOrWhiteSpace(region)) + if (!string.IsNullOrEmpty(region)) { var counter = GetCounter(region); if (counter != null) @@ -415,4 +368,4 @@ private IEnumerable GetWorkingCounters(string region) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/DictionaryCacheHandle.cs b/src/CacheManager.Core/Internal/DictionaryCacheHandle.cs index 8587aa44..0c880217 100644 --- a/src/CacheManager.Core/Internal/DictionaryCacheHandle.cs +++ b/src/CacheManager.Core/Internal/DictionaryCacheHandle.cs @@ -2,26 +2,33 @@ using System.Collections.Concurrent; using System.Linq; using System.Threading; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core.Internal { + /// + /// Custom settings for . + /// + public class DictionaryCacheOptions + { + /// + /// Gets or sets the interval at which the cache should scan for expired keys. + /// + public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1); + } + /// /// This handle is for internal use and testing. It does not implement any expiration. /// /// The type of the cache value. public class DictionaryCacheHandle : BaseCacheHandle { - private const int ScanInterval = 5000; private readonly static Random _random = new Random(); private readonly ConcurrentDictionary> _cache; private readonly Timer _timer; - - //private long _lastScan = 0L; private int _scanRunning; - - //private object _startScanLock = new object(); + private readonly TimeSpan _scanInterval; /// /// Initializes a new instance of the class. @@ -30,12 +37,30 @@ public class DictionaryCacheHandle : BaseCacheHandle /// The cache handle configuration. /// The logger factory. public DictionaryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) + : this(managerConfiguration, configuration, loggerFactory, options: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The manager configuration. + /// The cache handle configuration. + /// The logger factory. + /// Optional settings for this instance. + public DictionaryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory, DictionaryCacheOptions options) : base(managerConfiguration, configuration) { NotNull(loggerFactory, nameof(loggerFactory)); - Logger = loggerFactory.CreateLogger(this); + Logger = loggerFactory.CreateLogger(this.GetType()); _cache = new ConcurrentDictionary>(); - _timer = new Timer(TimerLoop, null, _random.Next(1000, ScanInterval), ScanInterval); + + options = options ?? new DictionaryCacheOptions(); + _scanInterval = options.ExpirationScanFrequency; + + var interval = (int)(_scanInterval.TotalMilliseconds < 100 ? 100 : _scanInterval.TotalMilliseconds); + + _timer = new Timer(TimerLoop, null, _random.Next(0, interval), interval); } /// @@ -253,10 +278,10 @@ private int ScanForExpiredItems() if (removed > 0 && Logger.IsEnabled(LogLevel.Information)) { - Logger.LogInfo("'{0}' removed '{1}' expired items during eviction run.", Configuration.Name, removed); + Logger.LogInformation("'{0}' removed '{1}' expired items during eviction run.", Configuration.Name, removed); } return removed; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/ICacheSerializer.cs b/src/CacheManager.Core/Internal/ICacheSerializer.cs index ed881712..fb81b7de 100644 --- a/src/CacheManager.Core/Internal/ICacheSerializer.cs +++ b/src/CacheManager.Core/Internal/ICacheSerializer.cs @@ -46,4 +46,4 @@ public interface ICacheSerializer /// The deserialized cache item. CacheItem DeserializeCacheItem(byte[] value, Type valueType); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/SerializerCacheItem.cs b/src/CacheManager.Core/Internal/SerializerCacheItem.cs index c248439b..622530d0 100644 --- a/src/CacheManager.Core/Internal/SerializerCacheItem.cs +++ b/src/CacheManager.Core/Internal/SerializerCacheItem.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Runtime.Serialization; using CacheManager.Core.Utility; namespace CacheManager.Core.Internal @@ -12,7 +13,7 @@ public interface ICacheItemConverter { /// /// Converts the current instance to a . - /// The returned item must return the orignial created and last accessed date! + /// The returned item must return the original created and last accessed date! /// /// The type. /// The cache item. @@ -23,6 +24,9 @@ public interface ICacheItemConverter /// Basic abstraction for serializers to work with cache items. /// /// The type. + + [Serializable] + [DataContract] public abstract class SerializerCacheItem : ICacheItemConverter { /// @@ -58,48 +62,57 @@ public SerializerCacheItem(ICacheItemProperties properties, object value) /// Gets or sets the created utc date in ticks. /// Can be converted from and to . /// + [DataMember] public abstract long CreatedUtc { get; set; } /// /// Gets or sets the expiration mode. /// + [DataMember] public abstract ExpirationMode ExpirationMode { get; set; } /// /// Gets or sets the expiration timeout in milliseconds. - /// Can be coverted from and to . + /// Can be converted from and to . /// + [DataMember] public abstract double ExpirationTimeout { get; set; } /// /// Gets or sets the key. /// + [DataMember] public abstract string Key { get; set; } /// /// Gets or sets the last accessed utc date in ticks. /// Can be converted from and to . /// + [DataMember] public abstract long LastAccessedUtc { get; set; } /// /// Gets or sets the region. /// + [DataMember] public abstract string Region { get; set; } /// /// Gets or sets a value indicating whether the default expiration should be used. /// + [DataMember] public abstract bool UsesExpirationDefaults { get; set; } /// /// Gets or sets the value type. /// + [DataMember] public abstract string ValueType { get; set; } /// /// Gets or sets the value. /// + [DataMember] public abstract T Value { get; set; } /// @@ -135,4 +148,4 @@ public CacheItem ToCacheItem() return item.WithCreated(new DateTime(CreatedUtc, DateTimeKind.Utc)); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Internal/TypeCache.cs b/src/CacheManager.Core/Internal/TypeCache.cs index 2098339d..d45f0562 100644 --- a/src/CacheManager.Core/Internal/TypeCache.cs +++ b/src/CacheManager.Core/Internal/TypeCache.cs @@ -82,7 +82,7 @@ public static Type GetType(string type) // try remove version from the type string and resolve it (should work even for signed assemblies). try { - var withoutVersion = Regex.Replace(type, @", Version=\d+.\d+.\d+.\d+", string.Empty); + var withoutVersion = Regex.Replace(type, @"(,.?)Version=\d+.\d+.\d+.\d+", string.Empty); typeResult = Type.GetType(withoutVersion, false); } catch @@ -92,13 +92,12 @@ public static Type GetType(string type) if (typeResult == null) { - // fixing an issue for corlib types if mixing net core clr and full clr calls + // Fixing an issue for corlib types from older full framework vs .NET Core, if deserializing a type serialized with a different framework. // (e.g. typeof(string) is different for those two, either System.String, System.Private.CoreLib or System.String, mscorlib) - var typeName = type.Split(',').FirstOrDefault(); - try { - typeResult = Type.GetType(typeName, false); + var allReplaced = Regex.Replace(type, @",(?:[^,]*).?(mscorlib|System.Private.CoreLib).(?:(?!\]|$).)*", string.Empty); + typeResult = Type.GetType(allReplaced, false); } catch { @@ -119,4 +118,4 @@ public static Type GetType(string type) return _types[type]; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Logging/ILogger.cs b/src/CacheManager.Core/Logging/ILogger.cs deleted file mode 100644 index 89f96a58..00000000 --- a/src/CacheManager.Core/Logging/ILogger.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; - -namespace CacheManager.Core.Logging -{ - /// - /// Represents a type used to perform logging. - /// - public interface ILogger - { - /// - /// Logs a message for the given . - /// - /// The log level. - /// The optional even id. - /// The log message. - /// The optional exception. - void Log(LogLevel logLevel, int eventId, object message, Exception exception); - - /// - /// Checks if the given LogLevel is enabled. - /// - /// The log level. - /// True if the is enabled, False otherwise. - bool IsEnabled(LogLevel logLevel); - - /// - /// Begins a logical operation scope. - /// - /// The identifier for the scope. - /// An IDisposable that ends the logical operation scope on dispose. - IDisposable BeginScope(object state); - } - - internal class NullLogger : ILogger - { - public IDisposable BeginScope(object state) => null; - - public bool IsEnabled(LogLevel logLevel) => false; - - public void Log(LogLevel logLevel, int eventId, object message, Exception exception) - { - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Core/Logging/ILoggerFactory.cs b/src/CacheManager.Core/Logging/ILoggerFactory.cs deleted file mode 100644 index 611aa1ca..00000000 --- a/src/CacheManager.Core/Logging/ILoggerFactory.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace CacheManager.Core.Logging -{ -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member -#pragma warning disable SA1600 - public interface ILoggerFactory - { - ILogger CreateLogger(string categoryName); - - ILogger CreateLogger(T instance); - } - - public class NullLoggerFactory : ILoggerFactory - { - public ILogger CreateLogger(string categoryName) => new NullLogger(); - - public ILogger CreateLogger(T instance) => new NullLogger(); - } -#pragma warning restore SA1600 -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member -} \ No newline at end of file diff --git a/src/CacheManager.Core/Logging/LogLevel.cs b/src/CacheManager.Core/Logging/LogLevel.cs deleted file mode 100644 index 651c9b84..00000000 --- a/src/CacheManager.Core/Logging/LogLevel.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace CacheManager.Core.Logging -{ -#pragma warning disable SA1600 -#pragma warning disable SA1602 // Enumeration items must be documented -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - - public enum LogLevel - { - Trace, - Debug, - Information, - Warning, - Error, - Critical - } - -#pragma warning restore CS1591 -#pragma warning restore SA1602 -#pragma warning restore SA1600 -} \ No newline at end of file diff --git a/src/CacheManager.Core/Logging/LoggerExtensions.cs b/src/CacheManager.Core/Logging/LoggerExtensions.cs deleted file mode 100644 index cb352d35..00000000 --- a/src/CacheManager.Core/Logging/LoggerExtensions.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Globalization; - -namespace CacheManager.Core.Logging -{ -#pragma warning disable SA1600 -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - - public static class LoggerExtensions - { - //// Critical - - public static void LogCritical(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Critical, 0, new FormatMessage(message, args), null); - } - - public static void LogCritical(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Critical, eventId, new FormatMessage(message, args), null); - } - - public static void LogCritical(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Critical, 0, new FormatMessage(message, args), exception); - } - - public static void LogCritical(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Critical, eventId, new FormatMessage(message, args), exception); - } - - //// DEBUG - - public static void LogDebug(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Debug, 0, new FormatMessage(message, args), null); - } - - public static void LogDebug(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Debug, eventId, new FormatMessage(message, args), null); - } - - public static void LogDebug(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Debug, 0, new FormatMessage(message, args), exception); - } - - public static void LogDebug(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Debug, eventId, new FormatMessage(message, args), exception); - } - - //// Error - - public static void LogError(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Error, 0, new FormatMessage(message, args), null); - } - - public static void LogError(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Error, eventId, new FormatMessage(message, args), null); - } - - public static void LogError(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Error, 0, new FormatMessage(message, args), exception); - } - - public static void LogError(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Error, eventId, new FormatMessage(message, args), exception); - } - - //// Information - - public static void LogInfo(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Information, 0, new FormatMessage(message, args), null); - } - - public static void LogInfo(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Information, eventId, new FormatMessage(message, args), null); - } - - public static void LogInfo(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Information, 0, new FormatMessage(message, args), exception); - } - - public static void LogInfo(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Information, eventId, new FormatMessage(message, args), exception); - } - - //// Trace - - public static void LogTrace(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Trace, 0, new FormatMessage(message, args), null); - } - - public static void LogTrace(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Trace, eventId, new FormatMessage(message, args), null); - } - - public static void LogTrace(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Trace, 0, new FormatMessage(message, args), exception); - } - - public static void LogTrace(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Trace, eventId, new FormatMessage(message, args), exception); - } - - //// Warning - - public static void LogWarn(this ILogger logger, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Warning, 0, new FormatMessage(message, args), null); - } - - public static void LogWarn(this ILogger logger, int eventId, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Warning, eventId, new FormatMessage(message, args), null); - } - - public static void LogWarn(this ILogger logger, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Warning, 0, new FormatMessage(message, args), exception); - } - - public static void LogWarn(this ILogger logger, int eventId, Exception exception, string message, params object[] args) - { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } - - logger.Log(LogLevel.Warning, eventId, new FormatMessage(message, args), exception); - } - - private class FormatMessage - { - private readonly string _format; - private readonly object[] _args; - - public FormatMessage(string format, params object[] args) - { - _format = format; - _args = args; - } - - public override string ToString() - { - if (_args == null || _args.Length == 0) - { - return _format; - } - - try - { - return string.Format(CultureInfo.CurrentCulture, _format, _args); - } - catch - { - return "Failed to format string"; - } - } - } - } -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member -#pragma warning restore SA1600 -} \ No newline at end of file diff --git a/src/CacheManager.Core/Properties/AssemblyInfo.cs b/src/CacheManager.Core/Properties/AssemblyInfo.cs index 9f3d2ab6..253d258d 100644 --- a/src/CacheManager.Core/Properties/AssemblyInfo.cs +++ b/src/CacheManager.Core/Properties/AssemblyInfo.cs @@ -1,5 +1,2 @@ using System; -using System.Runtime.CompilerServices; - [assembly: CLSCompliant(true)] -[assembly: InternalsVisibleTo("CacheManager.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051a13aa6dd4e78f62051f0d2608ba1e1e50f7038dad1e72f6a2233ec77ec58d49eec5ba13b0f7508d11fbbcd79ee39b0322b58873962771396ec08096f5d4bd2d1622ed9cad79016c154397390336a4a5a619aeec126f8d54b9ea884c510267d1d413ab5afc3c1aea86c199e57ecb23bd39458528328d2de90050e11d4649ec3")] \ No newline at end of file diff --git a/src/CacheManager.Core/Utility/Clock.cs b/src/CacheManager.Core/Utility/Clock.cs index cddcf2c5..337a2f16 100644 --- a/src/CacheManager.Core/Utility/Clock.cs +++ b/src/CacheManager.Core/Utility/Clock.cs @@ -1,79 +1,72 @@ -using System; -using System.Linq; -using System.Runtime.CompilerServices; +////using System; +////using System.Runtime.CompilerServices; -namespace CacheManager.Core.Utility -{ - /// - /// Time related helper. - /// - public static class Clock - { - /// - /// Number of ticks per millisecond. - /// - public const long TicksPerMillisecond = 10000; +////namespace CacheManager.Core.Utility +////{ +//// /// +//// /// Time related helper. +//// /// +//// internal static class Clock +//// { +//// /// +//// /// Number of ticks per millisecond. +//// /// +//// public const long TicksPerMillisecond = 10000; - /// - /// Ticks since 1970. - /// - public const long UnixEpochTicks = TimeSpan.TicksPerDay * DaysTo1970; +//// /// +//// /// Ticks since 1970. +//// /// +//// public const long UnixEpochTicks = TimeSpan.TicksPerDay * DaysTo1970; - /// - /// Seconds since 1970. - /// - public const long UnixEpochSeconds = UnixEpochTicks / TimeSpan.TicksPerSecond; +//// /// +//// /// Seconds since 1970. +//// /// +//// public const long UnixEpochSeconds = UnixEpochTicks / TimeSpan.TicksPerSecond; - // Number of days in a non-leap year - private const int DaysPerYear = 365; +//// // Number of days in a non-leap year +//// private const int DaysPerYear = 365; - // Number of days in 4 years - private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461 +//// // Number of days in 4 years +//// private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461 - // Number of days in 100 years - private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524 +//// // Number of days in 100 years +//// private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524 - // Number of days in 400 years - private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097 +//// // Number of days in 400 years +//// private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097 - // Number of days from 1/1/0001 to 12/31/1969 - private const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162 +//// // Number of days from 1/1/0001 to 12/31/1969 +//// private const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162 - /// - /// Computes a timestamp representing milliseconds since 1970. - /// - /// The milliseconds. -#if !NET40 - [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] -#endif - public static long GetUnixTimestampMillis() - { - return (DateTime.UtcNow.Ticks - UnixEpochTicks) / TicksPerMillisecond; - } +//// /// +//// /// Computes a timestamp representing milliseconds since 1970. +//// /// +//// /// The milliseconds. +//// [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] +//// public static long GetUnixTimestampMillis() +//// { +//// return (DateTime.UtcNow.Ticks - UnixEpochTicks) / TicksPerMillisecond; +//// } - /// - /// Computes a timestamp representing ticks since 1970. - /// - /// The ticks. -#if !NET40 - [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] -#endif - public static long GetUnixTimestampTicks() - { - return DateTime.UtcNow.Ticks - UnixEpochTicks; - } +//// /// +//// /// Computes a timestamp representing ticks since 1970. +//// /// +//// /// The ticks. +//// [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] +//// public static long GetUnixTimestampTicks() +//// { +//// return DateTime.UtcNow.Ticks - UnixEpochTicks; +//// } - /// - /// Computes the milliseconds since 1970 up to the given . - /// - /// The base. - /// The milliseconds since 1970. -#if !NET40 - [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] -#endif - public static long ToUnixTimestampMillis(DateTime date) - { - return (date.Ticks - UnixEpochTicks) / TicksPerMillisecond; - } - } -} \ No newline at end of file +//// /// +//// /// Computes the milliseconds since 1970 up to the given . +//// /// +//// /// The base. +//// /// The milliseconds since 1970. +//// [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] +//// public static long ToUnixTimestampMillis(DateTime date) +//// { +//// return (date.Ticks - UnixEpochTicks) / TicksPerMillisecond; +//// } +//// } +////} diff --git a/src/CacheManager.Core/Utility/Guard.cs b/src/CacheManager.Core/Utility/Guard.cs index 8cefe464..8f48a087 100644 --- a/src/CacheManager.Core/Utility/Guard.cs +++ b/src/CacheManager.Core/Utility/Guard.cs @@ -1,16 +1,14 @@ using System; using System.Collections.Generic; using System.Globalization; -#if !PORTABLE using System.Diagnostics; -#endif namespace CacheManager.Core.Utility { /// /// Utility class to do null and other checks. /// - public static class Guard + internal static class Guard { /// /// Validates that is not null and otherwise throws an exception. @@ -21,9 +19,7 @@ public static class Guard /// The parameter name. /// The , if not null. /// Thrown if is null. -#if !PORTABLE [DebuggerStepThrough] -#endif public static T NotNull([ValidatedNotNull]T value, string parameterName) { if (value == null) @@ -42,9 +38,7 @@ public static T NotNull([ValidatedNotNull]T value, string parameterName) /// The , if not null or empty. /// Thrown if is null. /// Thrown if is empty. -#if !PORTABLE [DebuggerStepThrough] -#endif public static string NotNullOrEmpty([ValidatedNotNull]string value, string name) { if (value == null) @@ -69,9 +63,7 @@ public static string NotNullOrEmpty([ValidatedNotNull]string value, string name) /// Thrown if is null. /// Thrown if is empty. /// Type of the collection. -#if !PORTABLE [DebuggerStepThrough] -#endif public static ICollection NotNullOrEmpty([ValidatedNotNull]ICollection value, string name) { if (value == null) @@ -96,9 +88,7 @@ public static ICollection NotNullOrEmpty([ValidatedNotNull]ICollection /// The if not null or empty. /// Thrown if is null. /// Thrown if is empty. -#if !PORTABLE [DebuggerStepThrough] -#endif public static string NotNullOrWhiteSpace([ValidatedNotNull]string value, string name) { NotNullOrEmpty(value, name); @@ -119,9 +109,7 @@ public static string NotNullOrWhiteSpace([ValidatedNotNull]string value, string /// and args to create the exception message. /// true if the is valid. /// Thrown if is false. -#if !PORTABLE [DebuggerStepThrough] -#endif public static bool Ensure(bool condition, string message, params object[] args) { if (!condition) @@ -144,11 +132,8 @@ public static bool Ensure(bool condition, string message, params object[] args) /// and args to create the exception message. /// The if not null. /// Thrown if is null. -#if !PORTABLE [DebuggerStepThrough] -#endif public static T EnsureNotNull([ValidatedNotNull]T value, string message, params object[] args) - where T : class { if (value == null) { @@ -173,4 +158,4 @@ public ValidatedNotNullAttribute() { } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Core/Utility/ObjectPool.cs b/src/CacheManager.Core/Utility/ObjectPool.cs index f5c005be..d3ebacf7 100644 --- a/src/CacheManager.Core/Utility/ObjectPool.cs +++ b/src/CacheManager.Core/Utility/ObjectPool.cs @@ -1,96 +1,96 @@ -using System; -using System.Linq; -using System.Threading; +////using System; +////using System.Linq; +////using System.Threading; -namespace CacheManager.Core.Utility -{ - /// - /// Contract used by to define how to create and return instances to a pool. - /// - /// The type of objects of the pool. - public interface IObjectPoolPolicy - { - /// - /// Creates a new instance of . - /// - /// The new instance. - T CreateNew(); +////namespace CacheManager.Core.Utility +////{ +//// /// +//// /// Contract used by to define how to create and return instances to a pool. +//// /// +//// /// The type of objects of the pool. +//// public interface IObjectPoolPolicy +//// { +//// /// +//// /// Creates a new instance of . +//// /// +//// /// The new instance. +//// T CreateNew(); - /// - /// Checks if the instance can be returned and may reset the instance to a state which can be reused. - /// - /// The instance which should be returned. - /// True if the instance can be returned, False otherwise. - bool Return(T value); - } +//// /// +//// /// Checks if the instance can be returned and may reset the instance to a state which can be reused. +//// /// +//// /// The instance which should be returned. +//// /// True if the instance can be returned, False otherwise. +//// bool Return(T value); +//// } - /// - /// Simple policy based pool for objects. - /// - /// The object type to pool. - public class ObjectPool where T : class - { - private readonly T[] _items; - private readonly IObjectPoolPolicy _policy; +//// /// +//// /// Simple policy based pool for objects. +//// /// +//// /// The object type to pool. +//// public class ObjectPool where T : class +//// { +//// private readonly T[] _items; +//// private readonly IObjectPoolPolicy _policy; - /// - /// Initializes a new instance of the class. - /// - /// The object pool policy. - /// Number of items to keep, defaults to number of processors * 2. - public ObjectPool(IObjectPoolPolicy policy, int? maxItems = null) - { - if (policy == null) - { - throw new ArgumentNullException(nameof(policy)); - } +//// /// +//// /// Initializes a new instance of the class. +//// /// +//// /// The object pool policy. +//// /// Number of items to keep, defaults to number of processors * 2. +//// public ObjectPool(IObjectPoolPolicy policy, int? maxItems = null) +//// { +//// if (policy == null) +//// { +//// throw new ArgumentNullException(nameof(policy)); +//// } - if (maxItems == null || maxItems <= 0) - { - maxItems = Environment.ProcessorCount * 2; - } +//// if (maxItems == null || maxItems <= 0) +//// { +//// maxItems = Environment.ProcessorCount * 2; +//// } - _policy = policy; - _items = new T[maxItems.Value]; - } +//// _policy = policy; +//// _items = new T[maxItems.Value]; +//// } - /// - /// Returns either a pooled or new instance of . - /// - /// The pooled or new instance. - public T Lease() - { - for (var i = 0; i < _items.Length; i++) - { - var item = _items[i]; - if (item != null && Interlocked.CompareExchange(ref _items[i], null, item) == item) - { - return item; - } - } +//// /// +//// /// Returns either a pooled or new instance of . +//// /// +//// /// The pooled or new instance. +//// public T Lease() +//// { +//// for (var i = 0; i < _items.Length; i++) +//// { +//// var item = _items[i]; +//// if (item != null && Interlocked.CompareExchange(ref _items[i], null, item) == item) +//// { +//// return item; +//// } +//// } - return _policy.CreateNew(); - } +//// return _policy.CreateNew(); +//// } - /// - /// Returns the instance to the pool (if possible). - /// - /// The instance to return to the pool. - public void Return(T value) - { - if (!_policy.Return(value)) - { - return; - } +//// /// +//// /// Returns the instance to the pool (if possible). +//// /// +//// /// The instance to return to the pool. +//// public void Return(T value) +//// { +//// if (!_policy.Return(value)) +//// { +//// return; +//// } - for (var i = 0; i < _items.Length; i++) - { - if (_items[i] == null) - { - _items[i] = value; - return; - } - } - } - } -} \ No newline at end of file +//// for (var i = 0; i < _items.Length; i++) +//// { +//// if (_items[i] == null) +//// { +//// _items[i] = value; +//// return; +//// } +//// } +//// } +//// } +////} diff --git a/src/CacheManager.Couchbase/BucketCacheHandle.cs b/src/CacheManager.Couchbase/BucketCacheHandle.cs deleted file mode 100644 index db10593a..00000000 --- a/src/CacheManager.Couchbase/BucketCacheHandle.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Text; -using CacheManager.Core; -using CacheManager.Core.Internal; -using CacheManager.Core.Logging; -using Newtonsoft.Json.Linq; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Couchbase -{ - /// - /// Definition for what bucket should be used and optionally a bucket password. - /// - /// - public class BucketCacheHandleAdditionalConfiguration - { - /// - /// Gets or sets the name of the bucket. - /// - /// - /// The name of the bucket. - /// - public string BucketName { get; set; } = CouchbaseConfigurationManager.DefaultBucketName; - - /// - /// Gets or sets the bucket password. - /// - /// - /// The bucket password. - /// - public string BucketPassword { get; set; } - } - - /// - /// Cache handle implementation based on the couchbase .net client. - /// - /// The type of the cache value. - public class BucketCacheHandle : BaseCacheHandle - { - private readonly CouchbaseConfigurationManager _bucketManager; - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - /// If configuration.HandleName is not valid. - public BucketCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) - : this(managerConfiguration, configuration, loggerFactory, new BucketCacheHandleAdditionalConfiguration()) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - /// The additional settings. - /// If configuration.HandleName is not valid. - public BucketCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory, BucketCacheHandleAdditionalConfiguration additionalSettings) - : base(managerConfiguration, configuration) - { - NotNull(configuration, nameof(configuration)); - NotNull(loggerFactory, nameof(loggerFactory)); - - Logger = loggerFactory.CreateLogger(this); - - if (additionalSettings == null) - { - additionalSettings = new BucketCacheHandleAdditionalConfiguration(); - } - - // we can configure the bucket name by having ":" as handle's - // this should only be used in 100% by app/web.config based configuration - var nameParts = configuration.Key.Split(new[] { ":" }, StringSplitOptions.RemoveEmptyEntries); - - var configurationName = nameParts.Length > 0 ? nameParts[0] : Guid.NewGuid().ToString(); - - if (nameParts.Length == 2) - { - additionalSettings.BucketName = nameParts[1]; - } - - _bucketManager = new CouchbaseConfigurationManager(configurationName, additionalSettings.BucketName, additionalSettings.BucketPassword); - } - - /// - public override bool IsDistributedCache => true; - - /// - /// Gets the number of items the cache handle currently maintains. - /// - /// The count. - public override int Count => (int)Stats.GetStatistic(CacheStatsCounterType.Items); - - /// - protected override ILogger Logger { get; } - - /// - /// Clears this cache, removing all items in the base cache and all regions. - /// - public override void Clear() - { - // warning: takes ~20seconds to flush the bucket... - var manager = _bucketManager.GetManager(); - if (manager != null) - { - using (manager) - { - manager.Flush(); - } - } - } - - /// - /// Clears the cache region, removing all items from the specified only. - /// - /// The cache region. - /// Not supported in this version. - public override void ClearRegion(string region) - { - // TODO: not supported? - throw new NotImplementedException(); - } - - /// - public override bool Exists(string key) - { - var fullKey = GetKey(key); - return _bucketManager.Bucket.Exists(fullKey); - } - - /// - public override bool Exists(string key, string region) - { - NotNullOrWhiteSpace(region, nameof(region)); - - var fullKey = GetKey(key, region); - return _bucketManager.Bucket.Exists(fullKey); - } - - /// - /// Adds a value to the cache. - /// - /// The CacheItem to be added to the cache. - /// - /// true if the key was not already added to the cache, false otherwise. - /// - protected override bool AddInternalPrepared(CacheItem item) - { - NotNull(item, nameof(item)); - - var fullKey = GetKey(item.Key, item.Region); - if (item.ExpirationMode != ExpirationMode.None) - { - return _bucketManager.Bucket.Insert(fullKey, item, item.ExpirationTimeout).Success; - } - - return _bucketManager.Bucket.Insert(fullKey, item).Success; - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting - /// unmanaged resources. - /// - /// Indicator if managed resources should be released. - protected override void Dispose(bool disposeManaged) - { - if (disposeManaged) - { - } - - base.Dispose(disposeManaged); - } - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key) => - GetCacheItemInternal(key, null); - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key, string region) - { - var fullkey = GetKey(key, region); - var result = _bucketManager.Bucket.Get>(fullkey); - - if (!result.Success) - { - return null; - } - - var cacheItem = result.Value; - if (cacheItem.Value is JToken) - { - var value = cacheItem.Value as JToken; - cacheItem = cacheItem.WithValue((TCacheValue)value.ToObject(cacheItem.ValueType)); - } - - if (cacheItem.IsExpired) - { - return null; - } - - // extend sliding expiration - if (cacheItem.ExpirationMode == ExpirationMode.Sliding) - { - cacheItem.LastAccessedUtc = DateTime.UtcNow; - PutInternalPrepared(cacheItem); - } - - return cacheItem; - } - - /// - /// Puts the into the cache. If the item exists it will get updated - /// with the new value. If the item doesn't exist, the item will be added to the cache. - /// - /// The CacheItem to be added to the cache. - protected override void PutInternalPrepared(CacheItem item) - { - NotNull(item, nameof(item)); - - var fullKey = GetKey(item.Key, item.Region); - if (item.ExpirationMode == ExpirationMode.Absolute || item.ExpirationMode == ExpirationMode.Sliding) - { - _bucketManager.Bucket.Upsert(fullKey, item, item.ExpirationTimeout); - } - else - { - _bucketManager.Bucket.Upsert(fullKey, item); - } - } - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key) => RemoveInternal(key, null); - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key, string region) - { - var fullKey = GetKey(key, region); - var result = _bucketManager.Bucket.Remove(fullKey); - return result.Success; - } - - private static string GetSHA256Key(string key) - { - using (var sha = SHA256.Create()) - { - var hashBytes = sha.ComputeHash(Encoding.UTF8.GetBytes(key)); - return Convert.ToBase64String(hashBytes); - } - } - - private static string GetKey(string key, string region = null) - { - if (string.IsNullOrWhiteSpace(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - var fullKey = key; - - if (!string.IsNullOrWhiteSpace(region)) - { - fullKey = string.Concat(region, ":", key); - } - - // Memcached still has a 250 character limit - if (fullKey.Length >= 250) - { - return GetSHA256Key(fullKey); - } - - return fullKey; - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Couchbase/CacheManager.Couchbase.csproj b/src/CacheManager.Couchbase/CacheManager.Couchbase.csproj deleted file mode 100644 index 9f1f4501..00000000 --- a/src/CacheManager.Couchbase/CacheManager.Couchbase.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - CacheManager extension package to work with Couchbase as a distributed cache. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. - net45;netstandard1.5 - true - true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached - - - - - - - - - - - \ No newline at end of file diff --git a/src/CacheManager.Couchbase/CouchbaseConfigurationBuilderExtensions.cs b/src/CacheManager.Couchbase/CouchbaseConfigurationBuilderExtensions.cs deleted file mode 100644 index 9a642023..00000000 --- a/src/CacheManager.Couchbase/CouchbaseConfigurationBuilderExtensions.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using CacheManager.Couchbase; -using Couchbase; -using Couchbase.Configuration.Client; -using Couchbase.Core; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Core -{ - /// - /// Extensions for the configuration builder specific to the Couchbase cache handle. - /// - public static class CouchbaseConfigurationBuilderExtensions - { - /// - /// Adds a for the given key. - /// The key will be matched with the Couchbase cache handle name. - /// - /// The part. - /// The key which has to match with the cache handle name. - /// The Couchbase configuration object. - /// - /// The configuration builder. - /// - /// If or is null. - public static ConfigurationBuilderCachePart WithCouchbaseConfiguration(this ConfigurationBuilderCachePart part, string configurationKey, ClientConfiguration config) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - NotNull(config, nameof(config)); - - CouchbaseConfigurationManager.AddConfiguration(configurationKey, config); - return part; - } - - /// - /// Adds a for the given key. - /// The key will be matched with the Couchbase cache handle name. - /// - /// The part. - /// The key which has to match with the cache handle name. - /// The Couchbase configuration object. - /// - /// The configuration builder. - /// - /// If or is null. - public static ConfigurationBuilderCachePart WithCouchbaseConfiguration(this ConfigurationBuilderCachePart part, string configurationKey, ICouchbaseClientDefinition definition) - { - return WithCouchbaseConfiguration(part, configurationKey, new ClientConfiguration(definition)); - } - - /// - /// Adds an already configured for the given key. Use this in case you want to use the outside of CacheManager, too - /// and you want to share this instance. - /// - /// Use in (or similar overloads) - /// to have the cache handle use this configuration. - /// - /// If your cluster requires authentication, you might have to configure cluster.Authenticate(...). - /// - /// - /// The part. - /// The configuration key. - /// The . - /// - /// The configuration builder. - /// If or is null. - /// - public static ConfigurationBuilderCachePart WithCouchbaseCluster(this ConfigurationBuilderCachePart part, string configurationKey, ICluster cluster) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - NotNull(cluster, nameof(cluster)); - - CouchbaseConfigurationManager.AddCluster(configurationKey, cluster); - return part; - } - - /// - /// Adds a using the configuration referenced via . - /// - /// The cache handle needs configuration specific to Couchbase, see remarks for details. - /// - /// - /// The builder part. - /// The configuration identifier. - /// The name of the Couchbase bucket which should be used by the cache handle. - /// Set this to true if this cache handle should be the source of the backplane. This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if or is null. - /// - /// The Couchbase cache handle requires configuration which can be defined via: - /// - /// - /// A configuration with a matching being added via . - /// - /// - /// A cluster with a matching being added via . - /// - /// - /// A CouchbaseClientSection configured in App/Web.config (only available on full .NET Framework). - /// - /// - /// Or, the cluster has been configured via and CacheManager will use the cluster returned by . - /// Anyways, this will be the last fallback which, if nothing has been configured at all, will fall back to the default server endpoint on 127.0.0.1:8091. - /// - /// - /// - /// If your cluster requires authentication, use either the or add a with valid authentication via cluster.Authenticate(...). - /// - /// - public static ConfigurationBuilderCacheHandlePart WithCouchbaseCacheHandle( - this ConfigurationBuilderCachePart part, - string couchbaseConfigurationKey, - string bucketName = CouchbaseConfigurationManager.DefaultBucketName, - bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - NotNullOrWhiteSpace(bucketName, nameof(bucketName)); - - return part.WithHandle(typeof(BucketCacheHandle<>), couchbaseConfigurationKey, isBackplaneSource, new BucketCacheHandleAdditionalConfiguration() - { - BucketName = bucketName - }); - } - - /// - /// Adds a using the configuration referenced via . - /// - /// The cache handle needs configuration specific to Couchbase, see remarks for details. - /// - /// - /// The builder part. - /// The configuration identifier. - /// The name of the Couchbase bucket which should be used by the cache handle. - /// The bucket password. - /// Set this to true if this cache handle should be the source of the backplane. This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if or is null. - /// - /// The Couchbase cache handle requires configuration which can be defined via: - /// - /// - /// A configuration with a matching being added via . - /// - /// - /// A cluster with a matching being added via . - /// - /// - /// A CouchbaseClientSection configured in App/Web.config (only available on full .NET Framework). - /// - /// - /// Or, the cluster has been configured via and CacheManager will use the cluster returned by . - /// Anyways, this will be the last fallback which, if nothing has been configured at all, will fall back to the default server endpoint on 127.0.0.1:8091. - /// - /// - /// - /// If your cluster requires authentication, use either the or add a with valid authentication via cluster.Authenticate(...). - /// - /// - public static ConfigurationBuilderCacheHandlePart WithCouchbaseCacheHandle( - this ConfigurationBuilderCachePart part, - string couchbaseConfigurationKey, - string bucketName, - string bucketPassword, - bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - NotNullOrWhiteSpace(bucketName, nameof(bucketName)); - - return part.WithHandle(typeof(BucketCacheHandle<>), couchbaseConfigurationKey, isBackplaneSource, new BucketCacheHandleAdditionalConfiguration() - { - BucketName = bucketName, - BucketPassword = bucketPassword - }); - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Couchbase/CouchbaseConfigurationManager.cs b/src/CacheManager.Couchbase/CouchbaseConfigurationManager.cs deleted file mode 100644 index 71e227ee..00000000 --- a/src/CacheManager.Couchbase/CouchbaseConfigurationManager.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System; -using System.Linq; -using Couchbase; -using Couchbase.Configuration.Client; -using Couchbase.Core; -using static CacheManager.Core.Utility.Guard; -using Couchbase.Management; -using System.Collections.Concurrent; -using CacheManager.Core; - -#if NET45 -using System.Configuration; -using Couchbase.Configuration.Client.Providers; -#endif - -namespace CacheManager.Couchbase -{ - /// - /// Manages configurations for the couchbase cache handle. - /// - /// As of version 1.0.2, changed the management of s as those instances are already - /// managed by the of the couchbase client libraray. No need to have additional collections of stuff in here. - /// - /// - /// We keep track of added configurations via - /// and eventually added predefined . - /// Referencing still works via configuration key, although, if nothing in particular is defined, the fallback should always at least go to the couchbase default cluster settings. - /// - /// - /// Also new, fallback to which can be used to initialize settings of a cluster statically. - /// - /// - public class CouchbaseConfigurationManager - { - /// - /// The default bucket name - /// - public const string DefaultBucketName = "default"; - -#if NET45 - - /// - /// The section name usually used for couchbase in app/web.config. - /// - public const string DefaultCouchbaseConfigurationSection = "couchbaseClients/couchbase"; - -#endif - - private static object _configLock = new object(); - private static ConcurrentDictionary _configurations = new ConcurrentDictionary(); - private static ConcurrentDictionary _clusters = new ConcurrentDictionary(); - private readonly string _configurationName; - private readonly string _bucketName; - private readonly string _bucketPassword; - - /// - /// Initializes a new instance of the class. - /// - /// The configuration name. - /// The bucket name. - /// The bucket password. - public CouchbaseConfigurationManager(string configurationKey, string bucketName = DefaultBucketName, string bucketPassword = null) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - NotNullOrWhiteSpace(bucketName, nameof(bucketName)); - _configurationName = configurationKey; - _bucketName = bucketName; - _bucketPassword = bucketPassword; - } - - /// - /// Gets a bucket for configuration name and bucket name. - /// - /// - /// The bucket. - /// - public IBucket Bucket => GetBucket(_configurationName, _bucketName, _bucketPassword); - - /// - /// Gets a instance. - /// If username and password have been defined in the bucket's configuration, those will be used to create the manager. - /// - /// The manager instance or null. - public IBucketManager GetManager() - { - var bucket = Bucket; - return string.IsNullOrWhiteSpace(bucket.Configuration.Username) ? - bucket.CreateManager() : - bucket.CreateManager(bucket.Configuration.Username, bucket.Configuration.Password); - } - - /// - /// Adds a already configured to the named collection of buckets. - /// This can be referenced by the via configuration key and . - /// - /// The configuration key. - /// The bucket. - public static void AddCluster(string configurationKey, ICluster cluster) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - NotNull(cluster, nameof(cluster)); - - // not sure if we even need this, but eventually we have to create a new instance of that bucket - _configurations.TryAdd(configurationKey, cluster.Configuration); - _clusters.TryAdd(configurationKey, cluster); - } - - /// - /// Adds a for a . - /// - /// The name. - /// The configuration. - /// If name or configuration are null. - public static void AddConfiguration(string configurationKey, ClientConfiguration configuration) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - NotNull(configuration, nameof(configuration)); - _configurations.TryAdd(configurationKey, configuration); - } - - /// - /// Gets a for the given . - /// - /// If the configuration is not already present and the target framework supports ConfigurationManager, the method tries to resolve the configuration from the - /// section with the given name. - /// - /// - /// The name. - /// The configuration. - /// If name is null. - /// - /// If no configuration or section can be found for configuration. - /// - public static ClientConfiguration GetConfiguration(string configurationKeyOrSectionName) - { - NotNullOrWhiteSpace(configurationKeyOrSectionName, nameof(configurationKeyOrSectionName)); - - if (_configurations.TryGetValue(configurationKeyOrSectionName, out ClientConfiguration configuration)) - { - return configuration; - } - -#if NET45 - var section = ConfigurationManager.GetSection(configurationKeyOrSectionName) as CouchbaseClientSection; - - if (section == null) - { - return null; - } - - var config = new ClientConfiguration(section); - AddConfiguration(configurationKeyOrSectionName, config); - return config; -#else - - return null; -#endif - } - - private static ICluster GetCluster(string configurationKey) - { - NotNullOrWhiteSpace(configurationKey, nameof(configurationKey)); - - if (!_clusters.TryGetValue(configurationKey, out ICluster cluster)) - { - var config = GetConfiguration(configurationKey); - if (config != null) - { - cluster = new Cluster(config); - } - else - { - // fallback to ClusterHelper as that's also a way ppl can configure this stuff... - try - { - cluster = ClusterHelper.Get(); - } - catch (InitializationException) - { - // last fallback has also not been initialized yet - // this will use the development settings on localhost without any auth (might not work and blow up later). - cluster = new Cluster(); - } - - // update our configuration cache just in case - AddConfiguration(configurationKey, cluster.Configuration); - } - - _clusters.TryAdd(configurationKey, cluster); - } - - return cluster; - } - - private static IBucket GetBucket(string configurationKey, string bucketName, string bucketPassword) - { - NotNullOrWhiteSpace(bucketName, nameof(bucketName)); - var cluster = GetCluster(configurationKey); - if (cluster == null) - { - // should probably never occur. - throw new InvalidOperationException("Cluster is not configured although we should fall back to ClusterHelper at least."); - } - - return string.IsNullOrEmpty(bucketPassword) ? cluster.OpenBucket(bucketName) : cluster.OpenBucket(bucketName, bucketPassword); - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Memcached/CacheManager.Memcached.csproj b/src/CacheManager.Memcached/CacheManager.Memcached.csproj deleted file mode 100644 index 88e7e6e7..00000000 --- a/src/CacheManager.Memcached/CacheManager.Memcached.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - CacheManager extension package to work with Memcached as a distributed cache. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. This package contains the specific Memcached handles. - net40;net45 - true - true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/CacheManager.Memcached/MemcachedCacheHandle.cs b/src/CacheManager.Memcached/MemcachedCacheHandle.cs deleted file mode 100644 index fbaaa901..00000000 --- a/src/CacheManager.Memcached/MemcachedCacheHandle.cs +++ /dev/null @@ -1,770 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Security.Cryptography; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using CacheManager.Core; -using CacheManager.Core.Internal; -using CacheManager.Core.Logging; -using CacheManager.Core.Utility; -using Enyim.Caching; -using Enyim.Caching.Configuration; -using Enyim.Caching.Memcached; -using Enyim.Caching.Memcached.Results; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Memcached -{ - /// - /// Cache handle implementation based on the Enyim memcached client. - /// - /// The type of the cache value. - [RequiresSerializer] - public class MemcachedCacheHandle : BaseCacheHandle - { - private static readonly string _defaultEnyimSectionName = "enyim.com/memcached"; - private static readonly string _defaultSectionName = "default"; - private static readonly TimeSpan _maximumTimeout = TimeSpan.FromDays(30); - private readonly ICacheManagerConfiguration _managerConfiguration; - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - /// The serializer. - /// - /// If or is null. - /// - /// - /// The cache value type is not serializable or if the enyim configuration section could not - /// be initialized. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Cache gets disposed correctly when the owner gets disposed.")] - public MemcachedCacheHandle( - ICacheManagerConfiguration managerConfiguration, - CacheHandleConfiguration configuration, - ILoggerFactory loggerFactory, - ICacheSerializer serializer) - : this(configuration, managerConfiguration, loggerFactory) - { - try - { - NotNull(configuration, nameof(configuration)); - var sectionName = GetEnyimSectionName(configuration.Key); - var section = GetSection(sectionName); - - Cache = new MemcachedClient(section); - } - catch (ConfigurationErrorsException ex) - { - throw new InvalidOperationException("Failed to initialize " + GetType().Name + ". " + ex.BareMessage, ex); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - /// The serializer. - /// The to use. - public MemcachedCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory, ICacheSerializer serializer, MemcachedClient client) - : this(configuration, managerConfiguration, loggerFactory) - { - // serializer gets ignored, just added to the ctor to satisfy the ctor finder in our custom DI to actually hit this ctor if the client is specified. - NotNull(client, nameof(client)); - Cache = client; - } - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - /// The serializer. - /// The to use to create the . - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Cache gets disposed correctly when the owner gets disposed.")] - public MemcachedCacheHandle( - ICacheManagerConfiguration managerConfiguration, - CacheHandleConfiguration configuration, - ILoggerFactory loggerFactory, - ICacheSerializer serializer, - MemcachedClientConfiguration clientConfiguration) - : this(configuration, managerConfiguration, loggerFactory) - { - NotNull(clientConfiguration, nameof(clientConfiguration)); - if (clientConfiguration.Transcoder.GetType() == typeof(DefaultTranscoder)) - { - clientConfiguration.Transcoder = new CacheManagerTanscoder(serializer); - - // default is 10, that might be too long as it can take up to 10sec to recover during retries - clientConfiguration.SocketPool.DeadTimeout = TimeSpan.FromSeconds(2); - } - - Cache = new MemcachedClient(clientConfiguration); - } - - private MemcachedCacheHandle( - CacheHandleConfiguration configuration, - ICacheManagerConfiguration managerConfiguration, - ILoggerFactory loggerFactory) - : base(managerConfiguration, configuration) - { - NotNull(configuration, nameof(configuration)); - NotNull(loggerFactory, nameof(loggerFactory)); - NotNull(managerConfiguration, nameof(managerConfiguration)); - - _managerConfiguration = managerConfiguration; - Logger = loggerFactory.CreateLogger(this); - } - - /// - public override bool IsDistributedCache - { - get - { - return true; - } - } - - /// - /// Gets the number of items the cache handle currently maintains. - /// - /// The count. - public override int Count => int.Parse(Cache.Stats().GetRaw("curr_items").First().Value); - - /// - /// Gets the get memcached client configuration. - /// - /// The get memcached client configuration. - public IMemcachedClientConfiguration GetMemcachedClientConfiguration => GetSection(); - - /// - /// Gets the total number of items per server. - /// - /// The total number of items per server. - public IEnumerable ServerItemCount - { - get - { - foreach (var count in Cache.Stats().GetRaw("total_items")) - { - yield return long.Parse(count.Value, CultureInfo.InvariantCulture); - } - } - } - - /// - /// Gets the servers. - /// - /// The servers. - public IList Servers => GetServers(); - - /// - /// Gets the cache. - /// - /// The cache. - public MemcachedClient Cache { get; } - - /// - protected override ILogger Logger { get; } - - /// - /// Clears this cache, removing all items in the base cache and all regions. - /// - public override void Clear() => Cache.FlushAll(); - - /// - /// Clears the cache region, removing all items from the specified only. - /// - /// Not supported for memcached. - /// The cache region. - public override void ClearRegion(string region) - { - var regionPrefix = StoreNewRegionPrefix(region); - - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("Cleared region {0}, new region key is {1}.", region, regionPrefix); - } - } - - /// - public override bool Exists(string key) - { - var result = Cache.ExecuteAppend(GetKey(key, null, false), default(ArraySegment)); - return result.StatusCode.HasValue && result.StatusCode.Value != (int)StatusCode.KeyNotFound; - } - - /// - public override bool Exists(string key, string region) - { - NotNullOrWhiteSpace(region, nameof(region)); - - var result = Cache.ExecuteAppend(GetKey(key, region, false), default(ArraySegment)); - return result.StatusCode.HasValue && result.StatusCode.Value != (int)StatusCode.KeyNotFound; - } - - /// - public override UpdateItemResult Update(string key, Func updateValue, int maxRetries) => - Update(key, null, updateValue, maxRetries); - - /// - public override UpdateItemResult Update(string key, string region, Func updateValue, int maxRetries) => - Set(key, region, updateValue, maxRetries); - - /// - /// Adds a value to the cache. - /// - /// The CacheItem to be added to the cache. - /// - /// true if the key was not already added to the cache, false otherwise. - /// - protected override bool AddInternalPrepared(CacheItem item) - { - IOperationResult result; - var shouldRetry = false; - var tries = 0; - do - { - tries++; - result = Store(StoreMode.Add, item, out shouldRetry); - if (!shouldRetry) - { - return result.Success; - } - - WaitRetry(tries); - } - while (shouldRetry && tries < _managerConfiguration.MaxRetries); - - throw new InvalidOperationException($"Add failed after {tries} tries for [{item.ToString()}]. {result.InnerResult?.Message ?? result.Message}"); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting - /// unmanaged resources. - /// - /// Indicator if managed resources should be released. - protected override void Dispose(bool disposeManaged) - { - if (disposeManaged) - { - Cache.Dispose(); - } - - base.Dispose(disposeManaged); - } - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key) => - GetCacheItemInternal(key, null); - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key, string region) - { - var item = Cache.Get(GetKey(key, region)) as CacheItem; - if (item != null) - { - if (item.IsExpired) - { - return null; - } - else if (item.ExpirationMode == ExpirationMode.Sliding) - { - // the only way I see to update sliding expiration for keys - // is to store them again with updated TTL... What a b...t - item.LastAccessedUtc = DateTime.UtcNow; - bool shouldRetry; - Store(StoreMode.Set, item, out shouldRetry); - } - } - - return item; - } - - /// - /// Puts the into the cache. If the item exists it will get updated - /// with the new value. If the item doesn't exist, the item will be added to the cache. - /// - /// The CacheItem to be added to the cache. - protected override void PutInternalPrepared(CacheItem item) - { - IOperationResult result; - var shouldRetry = false; - var tries = 0; - do - { - tries++; - result = Store(StoreMode.Set, item, out shouldRetry); - if (!shouldRetry) - { - return; - } - - WaitRetry(tries); - } - while (shouldRetry && tries < _managerConfiguration.MaxRetries); - - throw new InvalidOperationException($"Put failed after {tries} tries for [{item.ToString()}]. {result.InnerResult?.Message ?? result.Message}"); - } - - private void WaitRetry(int currentTry) - { - var delay = _managerConfiguration.RetryTimeout == 0 ? 10 : _managerConfiguration.RetryTimeout; - - var adjusted = delay * currentTry; - if (adjusted > 10000) - { - adjusted = 10000; - } - -#if !NET40 - Task.Delay(adjusted).ConfigureAwait(false).GetAwaiter().GetResult(); -#else - Thread.Sleep(adjusted); -#endif - } - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key) => RemoveInternal(key, null); - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key, string region) - { - var result = Cache.ExecuteRemove(GetKey(key, region, false)); - var statusCode = result.StatusCode ?? result.InnerResult?.StatusCode ?? -1; - if (result.Success && statusCode != (int)StatusCode.KeyNotFound) - { - LogOperationResult(LogLevel.Debug, result, "Removed {0} {1}", region, key); - } - else - { - if (statusCode == (int)StatusCode.KeyNotFound) - { - LogOperationResult(LogLevel.Information, result, "Remove Failed, key not found: {0} {1}", region, key); - } - else - { - LogOperationResult(LogLevel.Error, result, "Remove Failed for {0} {1}", region, key); - //// throw new InvalidOperationException($"Remove failed for {region} {key}; statusCode:{statusCode}, message:{result.InnerResult?.Message ?? result.Message}"); - } - } - - return result.Success; - } - - /// - /// Stores the item with the specified mode. - /// - /// - /// Memcached only supports expiration of seconds, meaning anything less than one second will mean zero, which means it expires right after adding it. - /// - /// The mode. - /// The item. - /// Flag indicating if the operation should be retried. Returnd succssess code will be false anyways. - /// The result. - protected virtual IStoreOperationResult Store(StoreMode mode, CacheItem item, out bool shouldRetry) - { - NotNull(item, nameof(item)); - shouldRetry = false; - - var key = GetKey(item.Key, item.Region); - IStoreOperationResult result; - - if (item.ExpirationMode == ExpirationMode.Absolute || item.ExpirationMode == ExpirationMode.Sliding) - { - if (item.ExpirationTimeout > _maximumTimeout) - { - throw new InvalidOperationException($"Timeout must not exceed {_maximumTimeout.TotalDays} days."); - } - - result = Cache.ExecuteStore(mode, key, item, item.ExpirationTimeout); - } - else - { - result = Cache.ExecuteStore(mode, key, item); - } - - if (mode == StoreMode.Add && result.StatusCode == (int?)StatusCode.KeyExists) - { - LogOperationResult(LogLevel.Information, result, "Failed to add item [{0}] because it exists.", item); - } - else if (result.Success) - { - LogOperationResult(LogLevel.Debug, result, "Stored [{0}]", item); - } - else - { - shouldRetry = true; - LogOperationResult(LogLevel.Error, result, "Store failed for [{0}]", item); - } - - return result; - } - - private void LogOperationResult(LogLevel level, IOperationResult result, string message, params object[] args) - { - if (Logger.IsEnabled(level)) - { - var msg = $"{string.Format(message, args)}; Result Success:'{result.Success}' Code:'{result.InnerResult?.StatusCode ?? result.StatusCode}' Message:'{result.InnerResult?.Message ?? result.Message}'."; - Logger.Log(level, 0, msg, result.Exception); - } - } - - private string StoreNewRegionPrefix(string region) - { - var regionKey = ComputeRegionLookupKey(region); - var oldRegionPredix = GetRegionPrefix(region); - var tries = 0; - var created = false; - while (!created && tries <= _managerConfiguration.MaxRetries) - { - var timestamp = Clock.GetUnixTimestampMillis(); - if (timestamp.ToString() == oldRegionPredix) - { - // we are too fast in creating new keys it seems, try again... - continue; - } - - tries++; - - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("Trying to store new region prefix '{0}', for region key '{1}'.", timestamp, regionKey); - } - - created = Cache.Store(StoreMode.Set, regionKey, timestamp); - - if (created) - { - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("Successfully stored new region prefix '{0}', for region key '{1}'.", timestamp, regionKey); - } - - return timestamp.ToString(); - } - } - - Logger.LogError("Failed to store prefix for region key '{0}'", regionKey); - - throw new InvalidOperationException($"Could not store new cache region prefix."); - } - - private string GetRegionPrefix(string region) - { - var regionKey = ComputeRegionLookupKey(region); - - object val; - if (Cache.ExecuteTryGet(regionKey, out val).Success) - { - return val?.ToString(); - } - - return null; - } - - private static string ComputeRegionLookupKey(string region) - { - return GetPerhapsHashedKey("__" + region + "_rk__"); - } - - /// - /// Gets the name of the enyim section. - /// - /// Name of the handle. - /// The section name. - private static string GetEnyimSectionName(string handleName) - { - if (handleName.Equals(_defaultSectionName, StringComparison.OrdinalIgnoreCase)) - { - return _defaultEnyimSectionName; - } - else - { - return handleName; - } - } - - private string GetKey(string key, string region = null, bool eventuallyCreateNewRegion = true) - { - if (string.IsNullOrWhiteSpace(key)) - { - throw new ArgumentNullException(nameof(key)); - } - - var fullKey = key; - - if (!string.IsNullOrWhiteSpace(region)) - { - var regionKey = GetRegionPrefix(region); - if (regionKey == null) - { - if (eventuallyCreateNewRegion) - { - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("Region key for region '{0}' not present, creating a new one...", region); - } - - regionKey = StoreNewRegionPrefix(region); - } - else - { - // create a fake one (e.g. on Remove key, we don't have to create a region if it doesn't exist at all) - regionKey = (Clock.GetUnixTimestampMillis() * -1).ToString(); - } - } - - fullKey = string.Concat(regionKey, ":", key); - } - - return GetPerhapsHashedKey(fullKey); - } - - private static string GetPerhapsHashedKey(string key) - { - // Memcached still has a 250 character limit - if (key.Length >= 250) - { - return GetSHA256Key(key); - } - - return key; - } - - // TODO: test the config section ctor now with this - private static IMemcachedClientConfiguration GetSection(string sectionName) - { - var section = (MemcachedClientSection)ConfigurationManager.GetSection(sectionName); - if (section == null) - { - throw new ConfigurationErrorsException("Section " + sectionName + " is not found."); - } - - return section; - } - - private static string GetSHA256Key(string key) - { - using (var sha = SHA256Managed.Create()) - { - var hashBytes = sha.ComputeHash(Encoding.UTF8.GetBytes(key)); - return Convert.ToBase64String(hashBytes); - } - } - - private static bool ShouldRetry(StatusCode statusCode) - { - switch (statusCode) - { - case StatusCode.NodeShutdown: - case StatusCode.OperationTimeout: - case StatusCode.OutOfMemory: - case StatusCode.Busy: - case StatusCode.SocketPoolTimeout: - case StatusCode.UnableToLocateNode: - case StatusCode.VBucketBelongsToAnotherServer: - return true; - } - - return false; - } - - /// - /// Gets the section. - /// - /// The client configuration. - /// - /// If memcached client section was not found or there are no servers defined for memcached. - /// - private IMemcachedClientConfiguration GetSection() - { - var sectionName = GetEnyimSectionName(Configuration.Name); - var section = (MemcachedClientSection)ConfigurationManager.GetSection(sectionName); - - if (section == null) - { - throw new ConfigurationErrorsException("Client section " + sectionName + " is not found."); - } - - // validate - if (section.Servers.Count <= 0) - { - throw new ConfigurationErrorsException("There are no servers defined."); - } - - return section; - } - - private IList GetServers() - { - var section = GetSection(); - return section.Servers; - } - - private UpdateItemResult Set(string key, string region, Func updateValue, int maxRetries) - { - var fullyKey = GetKey(key, region); - var tries = 0; - IStoreOperationResult result; - - do - { - tries++; - var getTries = 0; - StatusCode getStatus; - IGetOperationResult> getResult; - CacheItem item; - do - { - getTries++; - getResult = Cache.ExecuteGet>(fullyKey); - - item = getResult.Value; - getStatus = (StatusCode)(getResult.StatusCode ?? getResult.InnerResult?.StatusCode ?? -1); - } - while (ShouldRetry(getStatus) && getTries <= maxRetries); - - // break operation if we cannot retrieve the object (maybe it has expired already). - if (!getResult.Success || item == null) - { - LogOperationResult(LogLevel.Warning, getResult, "Get item during update failed for '{0}'.", fullyKey); - return UpdateItemResult.ForItemDidNotExist(); - } - - if (item.IsExpired) - { - return UpdateItemResult.ForItemDidNotExist(); - } - - var newValue = updateValue(item.Value); - - // added null check, throw explicit to me more consistent. Otherwise it would throw later eventually - if (newValue == null) - { - return UpdateItemResult.ForFactoryReturnedNull(); - } - - item = item.WithValue(newValue); - item.LastAccessedUtc = DateTime.UtcNow; - - if (item.ExpirationMode == ExpirationMode.Absolute || item.ExpirationMode == ExpirationMode.Sliding) - { - if (item.ExpirationTimeout > _maximumTimeout) - { - throw new InvalidOperationException($"Timeout must not exceed {_maximumTimeout.TotalDays} days."); - } - - result = Cache.ExecuteCas(StoreMode.Set, fullyKey, item, item.ExpirationTimeout, getResult.Cas); - } - else - { - result = Cache.ExecuteCas(StoreMode.Set, fullyKey, item, getResult.Cas); - } - - if (result.Success) - { - return UpdateItemResult.ForSuccess(item, tries > 1, tries); - } - else - { - LogOperationResult(LogLevel.Warning, result, "Update failed for '{0}'.", fullyKey); - } - - WaitRetry(tries); - } - while (tries < maxRetries); - - return UpdateItemResult.ForTooManyRetries(tries); - } - - private class CacheManagerTanscoder : DefaultTranscoder - { - private readonly ICacheSerializer _serializer; - - public CacheManagerTanscoder(ICacheSerializer serializer) - { - NotNull(serializer, nameof(serializer)); - _serializer = serializer; - } - - protected override object DeserializeObject(ArraySegment value) - { - var position = value.Offset; - var typeNameLen = BitConverter.ToUInt16(value.Array, position); - position += 2; - - var typeName = Encoding.UTF8.GetString(value.Array, position, typeNameLen); - position += typeNameLen; - if (value.Array[position++] != 0) - { - throw new InvalidOperationException("Invalid data, stop bit not found in type name encoding."); - } - - var data = new byte[value.Count - position + value.Offset]; - Buffer.BlockCopy(value.Array, position, data, 0, data.Length); - return _serializer.DeserializeCacheItem(data, TypeCache.GetType(typeName)); - } - - protected override ArraySegment SerializeObject(object value) - { - var cacheItem = value as CacheItem; - if (cacheItem == null) - { - throw new ArgumentException($"Value is not {nameof(CacheItem)}.", nameof(value)); - } - - var typeName = cacheItem.Value.GetType().AssemblyQualifiedName; - var typeNameBytes = Encoding.UTF8.GetBytes(typeName); - var typeBytesLength = BitConverter.GetBytes((ushort)typeNameBytes.Length); - var data = _serializer.SerializeCacheItem(cacheItem); - - var result = new byte[typeNameBytes.Length + typeBytesLength.Length + data.Length + 1]; - - /* Encoding the actual item value Type into the cached item - * - * | 0 - 1 | 2 - len | len + 1 | ... - * | len |TypeName |0 - stop | data - */ - Buffer.BlockCopy(typeBytesLength, 0, result, 0, typeBytesLength.Length); - Buffer.BlockCopy(typeNameBytes, 0, result, typeBytesLength.Length, typeNameBytes.Length); - Buffer.BlockCopy(data, 0, result, typeBytesLength.Length + typeNameBytes.Length + 1, data.Length); - - return new ArraySegment(result); - } - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Memcached/MemcachedConfigurationBuilderExtensions.cs b/src/CacheManager.Memcached/MemcachedConfigurationBuilderExtensions.cs deleted file mode 100644 index ab779b7a..00000000 --- a/src/CacheManager.Memcached/MemcachedConfigurationBuilderExtensions.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using CacheManager.Memcached; -using Enyim.Caching; -using Enyim.Caching.Configuration; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Core -{ - /// - /// Extensions for the configuration builder specific to the Memcached cache handle. - /// - public static class MemcachedConfigurationBuilderExtensions - { - /// - /// Adds a . The must match with cache configured via enyim configuration section. - /// - /// The builder part. - /// The configuration name. - /// - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if handleName or handleType are null. - /// - public static ConfigurationBuilderCacheHandlePart WithMemcachedCacheHandle(this ConfigurationBuilderCachePart part, string configurationName, bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - - return part.WithHandle(typeof(MemcachedCacheHandle<>), configurationName, isBackplaneSource); - } - - /// - /// Adds a with a preconfigured instance. - /// - /// The builder part. - /// The to use for this cache handle. - /// - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if is null. - /// - public static ConfigurationBuilderCacheHandlePart WithMemcachedCacheHandle(this ConfigurationBuilderCachePart part, MemcachedClient client, bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - NotNull(client, nameof(client)); - - return part.WithHandle(typeof(MemcachedCacheHandle<>), Guid.NewGuid().ToString(), isBackplaneSource, client); - } - - /// - /// Adds a . The must match with cache configured via enyim configuration section. - /// - /// The builder part. - /// The configuration name. - /// The to use for this cache handle. - /// - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if is null. - /// - public static ConfigurationBuilderCacheHandlePart WithMemcachedCacheHandle(this ConfigurationBuilderCachePart part, string configurationName, MemcachedClient client, bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - - return part.WithHandle(typeof(MemcachedCacheHandle<>), configurationName, isBackplaneSource, client); - } - - /// - /// Adds a using the to setup a instance. - /// - /// The builder part. - /// The to use to create the for this cache handle. - /// - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if is null. - /// - public static ConfigurationBuilderCacheHandlePart WithMemcachedCacheHandle(this ConfigurationBuilderCachePart part, MemcachedClientConfiguration clientConfiguration, bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - NotNull(clientConfiguration, nameof(clientConfiguration)); - - return part.WithHandle(typeof(MemcachedCacheHandle<>), Guid.NewGuid().ToString(), isBackplaneSource, clientConfiguration); - } - - /// - /// Adds a using the to setup a instance. - /// - /// The builder part. - /// The configuration name. - /// The to use to create the for this cache handle. - /// - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The part. - /// - /// Thrown if is null. - /// - public static ConfigurationBuilderCacheHandlePart WithMemcachedCacheHandle(this ConfigurationBuilderCachePart part, string configurationName, MemcachedClientConfiguration clientConfiguration, bool isBackplaneSource = true) - { - NotNull(part, nameof(part)); - - return part.WithHandle(typeof(MemcachedCacheHandle<>), configurationName, isBackplaneSource, clientConfiguration); - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Memcached/StatusCode.cs b/src/CacheManager.Memcached/StatusCode.cs deleted file mode 100644 index 2ed73cbf..00000000 --- a/src/CacheManager.Memcached/StatusCode.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace CacheManager.Memcached -{ - internal enum StatusCode - { - Success = 0x0000, - KeyNotFound = 0x0001, - KeyExists = 0x0002, - ValueTooLarge = 0x0003, - InvalidArguments = 0x0004, - ItemNotStored = 0x0005, - IncrDecrOnNonNumericValue = 0x0006, - VBucketBelongsToAnotherServer = 0x0007, - AuthenticationError = 0x0020, - AuthenticationContinue = 0x0021, - InvalidRange = 0x0022, - UnknownCommand = 0x0081, - OutOfMemory = 0x0082, - NotSupported = 0x0083, - InternalError = 0x0084, - Busy = 0x0085, - TemporaryFailure = 0x0086, - - SocketPoolTimeout = 0x091, - UnableToLocateNode = 0x092, - NodeShutdown = 0x093, - OperationTimeout = 0x094 - } -} \ No newline at end of file diff --git a/src/CacheManager.Microsoft.Extensions.Caching.Memory/CacheManager.Microsoft.Extensions.Caching.Memory.csproj b/src/CacheManager.Microsoft.Extensions.Caching.Memory/CacheManager.Microsoft.Extensions.Caching.Memory.csproj index 5476e3a9..044c51c3 100644 --- a/src/CacheManager.Microsoft.Extensions.Caching.Memory/CacheManager.Microsoft.Extensions.Caching.Memory.csproj +++ b/src/CacheManager.Microsoft.Extensions.Caching.Memory/CacheManager.Microsoft.Extensions.Caching.Memory.csproj @@ -3,19 +3,19 @@ CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. This package contains the specific cache handle for Microsoft.Extensions.Caching.Memory. MichaConrad;AuroraDysis - net451;netstandard1.3 + netstandard2.0;net8.0 true true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + Caching;Cache;CacheManager;MemoryCache + true - - - - + + - + + \ No newline at end of file diff --git a/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheExtensions.cs b/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheExtensions.cs index 654d6139..5d5a8b29 100644 --- a/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheExtensions.cs +++ b/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheExtensions.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Concurrent; using Microsoft.Extensions.Caching.Memory; namespace CacheManager.MicrosoftCachingMemory @@ -24,25 +22,23 @@ public static bool Contains(this MemoryCache cache, object key) internal static void RegisterChild(this MemoryCache cache, object parentKey, object childKey) { - object temp; - if (cache.TryGetValue(parentKey, out temp)) + if (cache.TryGetValue(parentKey, out var keys)) { - var set = (HashSet)temp; - set.Add(childKey); + var keySet = (ConcurrentDictionary)keys; + keySet.TryAdd(childKey, true); } } internal static void RemoveChilds(this MemoryCache cache, object region) { - object keys; - if (cache.TryGetValue(region, out keys)) + if (cache.TryGetValue(region, out var keys)) { - var keySet = (HashSet)keys; - foreach (var key in keySet) + var keySet = (ConcurrentDictionary)keys; + foreach (var key in keySet.Keys) { cache.Remove(key); } } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheHandle`1.cs b/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheHandle`1.cs index dff819ce..7f95ad96 100644 --- a/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheHandle`1.cs +++ b/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheHandle`1.cs @@ -1,10 +1,9 @@ using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; using Microsoft.Extensions.Caching.Memory; -using static CacheManager.Core.Utility.Guard; +using Microsoft.Extensions.Logging; namespace CacheManager.MicrosoftCachingMemory { @@ -43,10 +42,17 @@ public MemoryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheH public MemoryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory, MemoryCacheOptions memoryCacheOptions) : base(managerConfiguration, configuration) { - NotNull(configuration, nameof(configuration)); - NotNull(loggerFactory, nameof(loggerFactory)); + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (loggerFactory is null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } - Logger = loggerFactory.CreateLogger(this); + Logger = loggerFactory.CreateLogger(this.GetType()); _cacheName = configuration.Name; MemoryCacheOptions = memoryCacheOptions ?? new MemoryCacheOptions(); _cache = new MemoryCache(MemoryCacheOptions); @@ -82,7 +88,10 @@ public override bool Exists(string key) /// public override bool Exists(string key, string region) { - NotNullOrWhiteSpace(region, nameof(region)); + if (string.IsNullOrWhiteSpace(region)) + { + throw new ArgumentException($"'{nameof(region)}' cannot be null or whitespace.", nameof(region)); + } return _cache.Contains(GetItemKey(key, region)); } @@ -178,7 +187,10 @@ protected override void PutInternalPrepared(CacheItem item) private string GetItemKey(string key, string region = null) { - NotNullOrWhiteSpace(key, nameof(key)); + if (string.IsNullOrWhiteSpace(key)) + { + throw new ArgumentException($"'{nameof(key)}' cannot be null or whitespace.", nameof(key)); + } if (string.IsNullOrWhiteSpace(region)) { @@ -227,7 +239,7 @@ private void CreateRegionToken(string region) SlidingExpiration = TimeSpan.MaxValue, }; - _cache.Set(region, new HashSet(), options); + _cache.Set(region, new ConcurrentDictionary(), options); } private void ItemRemoved(object key, object value, EvictionReason reason, object state) @@ -279,4 +291,4 @@ private void ItemRemoved(object key, object value, EvictionReason reason, object } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Microsoft.Extensions.Configuration/CacheManager.Microsoft.Extensions.Configuration.csproj b/src/CacheManager.Microsoft.Extensions.Configuration/CacheManager.Microsoft.Extensions.Configuration.csproj index 29524929..d68d94d5 100644 --- a/src/CacheManager.Microsoft.Extensions.Configuration/CacheManager.Microsoft.Extensions.Configuration.csproj +++ b/src/CacheManager.Microsoft.Extensions.Configuration/CacheManager.Microsoft.Extensions.Configuration.csproj @@ -2,24 +2,26 @@ CacheManager extension package to use Microsoft.Extensions.Configuration to configure the CacheManager instance. CacheManager is an open source caching abstraction layer for .NET written in C#. This is the ASP.NET Core configuration integration package. - net45;netstandard1.2 + netstandard2.0;net8.0 true true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + Caching;Cache;CacheManager;Distributed Cache;Configuration + true - - - - + + + + - - $(DefineConstants);NETSTANDARD - - + + + + + \ No newline at end of file diff --git a/src/CacheManager.Microsoft.Extensions.Configuration/MicrosoftConfigurationExtensions.cs b/src/CacheManager.Microsoft.Extensions.Configuration/MicrosoftConfigurationExtensions.cs index d625fb4a..c4faf1dd 100644 --- a/src/CacheManager.Microsoft.Extensions.Configuration/MicrosoftConfigurationExtensions.cs +++ b/src/CacheManager.Microsoft.Extensions.Configuration/MicrosoftConfigurationExtensions.cs @@ -31,14 +31,10 @@ public static class MicrosoftConfigurationExtensions private const string TypeMicrosoftLoggerFactory = "CacheManager.Logging.MicrosoftLoggerFactoryAdapter, CacheManager.Microsoft.Extensions.Logging"; private const string TypeRedisBackplane = "CacheManager.Redis.RedisCacheBackplane, CacheManager.StackExchange.Redis"; private const string TypeSystemRuntimeHandle = "CacheManager.SystemRuntimeCaching.MemoryCacheHandle`1, CacheManager.SystemRuntimeCaching"; - private const string TypeSystemWebHandle = "CacheManager.Web.SystemWebCacheHandle`1, CacheManager.Web"; private const string TypeRedisHandle = "CacheManager.Redis.RedisCacheHandle`1, CacheManager.StackExchange.Redis"; - private const string TypeCouchbaseHandle = "CacheManager.Couchbase.BucketCacheHandle`1, CacheManager.Couchbase"; - private const string TypeMemcachedHandle = "CacheManager.Memcached.MemcachedCacheHandle`1, CacheManager.Memcached"; private const string TypeMsExtensionMemoryCacheHandle = "CacheManager.MicrosoftCachingMemory.MemoryCacheHandle`1, CacheManager.Microsoft.Extensions.Caching.Memory"; private const string TypeRedisConfiguration = "CacheManager.Redis.RedisConfiguration, CacheManager.StackExchange.Redis"; private const string TypeRedisConfigurations = "CacheManager.Redis.RedisConfigurations, CacheManager.StackExchange.Redis"; - private const string KnonwSerializerBinary = "binary"; private const string KnonwSerializerJson = "json"; private const string KnonwSerializerGzJson = "gzjson"; private const string KnonwSerializerProto = "protobuf"; @@ -194,13 +190,13 @@ public static void LoadRedisConfigurations(this IConfiguration configuration) catch (FileNotFoundException ex) { throw new InvalidOperationException( - "Redis types could not be loaded. Make sure that you have the CacheManager.Redis.Stackexchange package installed.", + "Redis types could not be loaded. Make sure that you have the CacheManager.Stackexchange.Redis package installed.", ex); } catch (TypeLoadException ex) { throw new InvalidOperationException( - "Redis types could not be loaded. Make sure that you have the CacheManager.Redis.Stackexchange package installed.", + "Redis types could not be loaded. Make sure that you have the CacheManager.Stackexchange.Redis package installed.", ex); } } @@ -297,23 +293,12 @@ private static Type GetKnownHandleType(string knownTypeName, string path, out bo case "dictionary": return typeof(DictionaryCacheHandle<>); - case "systemweb": - return Type.GetType(TypeSystemWebHandle, true); - case "msmemory": return Type.GetType(TypeMsExtensionMemoryCacheHandle, true); case "redis": keyRequired = true; return Type.GetType(TypeRedisHandle, true); - - case "couchbase": - keyRequired = true; - return Type.GetType(TypeCouchbaseHandle, true); - - case "memcached": - keyRequired = true; - return Type.GetType(TypeMemcachedHandle, true); } } catch (FileNotFoundException ex) @@ -461,12 +446,6 @@ private static Type GetKnownSerializerType(string knownTypeName, string path) { switch (knownTypeName.ToLowerInvariant()) { - case KnonwSerializerBinary: -#if NETSTANDARD - throw new PlatformNotSupportedException("BinaryCacheSerializer is not available on this platform"); -#else - return typeof(BinaryCacheSerializer); -#endif case KnonwSerializerJson: return Type.GetType(TypeJsonCacheSerializer, true); @@ -497,4 +476,4 @@ private static Type GetKnownSerializerType(string knownTypeName, string path) $"Known serializer type '{knownTypeName}' is invalid. Check configuration at '{path}'."); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Microsoft.Extensions.Configuration/ServiceCollectionExtensions.cs b/src/CacheManager.Microsoft.Extensions.Configuration/ServiceCollectionExtensions.cs index c361426a..91ff34a8 100644 --- a/src/CacheManager.Microsoft.Extensions.Configuration/ServiceCollectionExtensions.cs +++ b/src/CacheManager.Microsoft.Extensions.Configuration/ServiceCollectionExtensions.cs @@ -1,8 +1,8 @@ using System; -using System.Linq; using CacheManager.Core; using CacheManager.Core.Utility; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.DependencyInjection { @@ -15,15 +15,15 @@ public static class ServiceCollectionExtensions /// Adds a new as singleton to the DI framework. /// /// The services collection. - /// The used for defining the . + /// The used for defining the . /// The (optional) name to be used for the . - public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, Action configure, string name = null) + public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, Action configure, string name = null) { Guard.NotNull(collection, nameof(collection)); Guard.NotNull(configure, nameof(configure)); var builder = string.IsNullOrWhiteSpace(name) ? - new CacheManager.Core.ConfigurationBuilder() : - new CacheManager.Core.ConfigurationBuilder(name); + new CacheManager.Core.CacheConfigurationBuilder() : + new CacheManager.Core.CacheConfigurationBuilder(name); configure(builder); collection.AddSingleton(builder.Build()); @@ -70,7 +70,7 @@ public static IServiceCollection AddCacheManagerConfiguration(this IServiceColle /// The section which contains a cacheManagers section. /// Can be used to further configure the configuration. /// The services collection - public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, IConfiguration fromConfiguration, Action configure) + public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, IConfiguration fromConfiguration, Action configure) { Guard.NotNull(collection, nameof(collection)); Guard.NotNull(fromConfiguration, nameof(fromConfiguration)); @@ -90,7 +90,7 @@ public static IServiceCollection AddCacheManagerConfiguration(this IServiceColle /// The name used in the configuration. /// Can be used to further configure the configuration. /// The services collection - public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, IConfiguration fromConfiguration, string name, Action configure) + public static IServiceCollection AddCacheManagerConfiguration(this IServiceCollection collection, IConfiguration fromConfiguration, string name, Action configure) { Guard.NotNull(collection, nameof(collection)); Guard.NotNull(fromConfiguration, nameof(fromConfiguration)); @@ -133,18 +133,19 @@ public static IServiceCollection AddCacheManager(this IServiceCollection collect /// The name of the to use. /// Can be used to further configure the . /// The services collection. - public static IServiceCollection AddCacheManager(this IServiceCollection collection, IConfiguration fromConfiguration, string configurationName = null, Action configure = null) + public static IServiceCollection AddCacheManager(this IServiceCollection collection, IConfiguration fromConfiguration, string configurationName = null, Action configure = null) { Guard.NotNull(collection, nameof(collection)); Guard.NotNull(fromConfiguration, nameof(fromConfiguration)); collection.AddSingleton, BaseCacheManager>((provider) => { + var loggerFactory = provider.GetService(); var configuration = string.IsNullOrWhiteSpace(configurationName) ? fromConfiguration.GetCacheConfiguration() : fromConfiguration.GetCacheConfiguration(configurationName); configure?.Invoke(configuration.Builder); - return new BaseCacheManager(configuration); + return new BaseCacheManager(configuration, loggerFactory); }); return collection; @@ -158,7 +159,7 @@ public static IServiceCollection AddCacheManager(this IServiceCollection coll /// Used to configure the instance of . /// The (optional) name for the . /// The services collection. - public static IServiceCollection AddCacheManager(this IServiceCollection collection, Action configure, string name = null) + public static IServiceCollection AddCacheManager(this IServiceCollection collection, Action configure, string name = null) { Guard.NotNull(collection, nameof(collection)); Guard.NotNull(configure, nameof(configure)); @@ -167,15 +168,16 @@ public static IServiceCollection AddCacheManager(this IServiceCollection coll { Guard.NotNull(configure, nameof(configure)); var builder = string.IsNullOrWhiteSpace(name) ? - new CacheManager.Core.ConfigurationBuilder() : - new CacheManager.Core.ConfigurationBuilder(name); + new CacheManager.Core.CacheConfigurationBuilder() : + new CacheManager.Core.CacheConfigurationBuilder(name); configure(builder); - - return new BaseCacheManager(builder.Build()); + + var loggerFactory = provider.GetService(); + return new BaseCacheManager(builder.Build(), loggerFactory); }); return collection; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Microsoft.Extensions.Logging/CacheManager.Microsoft.Extensions.Logging.csproj b/src/CacheManager.Microsoft.Extensions.Logging/CacheManager.Microsoft.Extensions.Logging.csproj deleted file mode 100644 index 98826d92..00000000 --- a/src/CacheManager.Microsoft.Extensions.Logging/CacheManager.Microsoft.Extensions.Logging.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - CacheManager extension package to work with Microsoft.Extensions.Logging as logging provider. CacheManager is an open source caching abstraction layer for .NET written in C#. The ASP.NET Core logging provides a bridge to the Microsoft.Extensions.Logging framework. - net45;netstandard1.2 - true - true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached - - - - - - - - - - - - \ No newline at end of file diff --git a/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggerFactory.cs b/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggerFactory.cs deleted file mode 100644 index b15a1a95..00000000 --- a/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggerFactory.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Globalization; -using CacheManager.Core.Utility; -using Microsoft.Extensions.Logging; -using ILogger = CacheManager.Core.Logging.ILogger; -using LogLevel = CacheManager.Core.Logging.LogLevel; - -namespace CacheManager.Logging -{ -#pragma warning disable SA1600 -#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member - public class MicrosoftLoggerFactoryAdapter : Core.Logging.ILoggerFactory, IDisposable - { - private readonly ILoggerFactory _parentFactory; - - public MicrosoftLoggerFactoryAdapter() - { - _parentFactory = new LoggerFactory(); - } - - public MicrosoftLoggerFactoryAdapter(ILoggerFactory parentFactory) - { - Guard.NotNull(parentFactory, nameof(parentFactory)); - _parentFactory = parentFactory; - } - - ~MicrosoftLoggerFactoryAdapter() - { - // Do not change this code. Put cleanup code in Dispose(bool disposing) above. - Dispose(false); - } - - public ILogger CreateLogger(string categoryName) - { - return new MicrosoftLoggerAdapter(_parentFactory.CreateLogger(categoryName)); - } - - public ILogger CreateLogger(T instance) - { - return new MicrosoftLoggerAdapter(new Logger(_parentFactory)); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - _parentFactory.Dispose(); - } - } - } - - internal class MicrosoftLoggerAdapter : ILogger - { - private static readonly Func _formatter = MessageFormatter; - private readonly Microsoft.Extensions.Logging.ILogger _logger; - - public MicrosoftLoggerAdapter(Microsoft.Extensions.Logging.ILogger logger) - { - Guard.NotNull(logger, nameof(logger)); - - _logger = logger; - } - - public IDisposable BeginScope(object state) - { - return _logger.BeginScope(state); - } - - public bool IsEnabled(LogLevel logLevel) - { - return _logger.IsEnabled(GetExternalLogLevel(logLevel)); - } - - public void Log(LogLevel logLevel, int eventId, object message, Exception exception) - { - _logger.Log(GetExternalLogLevel(logLevel), eventId, message, exception, _formatter); - } - - private static string MessageFormatter(object state, Exception error) - { - if (state == null && error == null) - { - throw new InvalidOperationException("No message or exception details were found to create a message for the log."); - } - - if (state == null) - { - return error.ToString(); - } - - if (error == null) - { - return state.ToString(); - } - - return string.Format(CultureInfo.CurrentCulture, "{0}{1}{2}", state, Environment.NewLine, error); - } - - private static Microsoft.Extensions.Logging.LogLevel GetExternalLogLevel(LogLevel level) - { - switch (level) - { - case LogLevel.Debug: - return Microsoft.Extensions.Logging.LogLevel.Debug; - case LogLevel.Trace: - return Microsoft.Extensions.Logging.LogLevel.Trace; - case LogLevel.Information: - return Microsoft.Extensions.Logging.LogLevel.Information; - case LogLevel.Warning: - return Microsoft.Extensions.Logging.LogLevel.Warning; - case LogLevel.Error: - return Microsoft.Extensions.Logging.LogLevel.Error; - case LogLevel.Critical: - return Microsoft.Extensions.Logging.LogLevel.Critical; - } - - return Microsoft.Extensions.Logging.LogLevel.None; - } - } -#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member -#pragma warning restore SA1600 -} diff --git a/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggingBuilderExtensions.cs b/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggingBuilderExtensions.cs deleted file mode 100644 index 6b0a70bf..00000000 --- a/src/CacheManager.Microsoft.Extensions.Logging/MicrosoftLoggingBuilderExtensions.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Linq; -using CacheManager.Logging; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Core -{ - /// - /// Extensions for the configuration builder for logging. - /// - public static class MicrosoftLoggingBuilderExtensions - { - /// - /// Enables logging for the cache manager instance. - /// Using this extension will create a NEW instance of Microsoft.Extensions.Logging.ILoggerFactory. - /// - /// If you use the standard Micorosft AspNetCore DI, you might want to use the other extensions which make CacheManager use - /// the already injected/shared instance of . - /// - /// - /// Use the to configure the logger factory and add s as needed. - /// - /// - /// The builder part. - /// The logger factory used for configuring logging. - /// The builder. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "not owning it")] - public static ConfigurationBuilderCachePart WithMicrosoftLogging(this ConfigurationBuilderCachePart part, Action factory) - { - NotNull(part, nameof(part)); - NotNull(factory, nameof(factory)); - var externalFactory = new LoggerFactory(); - factory(externalFactory); - return part.WithLogging(typeof(MicrosoftLoggerFactoryAdapter), externalFactory); - } - - /// - /// Enables logging for the cache manager instance using an existion Microsoft.Extensions.Logging.ILoggerFactory as target. - /// - /// The builder part. - /// The logger factory which should be used. - /// The builder. - public static ConfigurationBuilderCachePart WithMicrosoftLogging(this ConfigurationBuilderCachePart part, ILoggerFactory loggerFactory) - { - NotNull(part, nameof(part)); - NotNull(loggerFactory, nameof(loggerFactory)); - return part.WithLogging(typeof(MicrosoftLoggerFactoryAdapter), loggerFactory); - } - - /// - /// Configures cache manager logging to use a Microsoft.Extensions.Logging.ILoggerFactory - /// which gets resolved from the . - /// - /// The builder part. - /// The services collection. - /// The builder. - public static ConfigurationBuilderCachePart WithMicrosoftLogging(this ConfigurationBuilderCachePart part, IServiceCollection serviceCollection) - { - NotNull(part, nameof(part)); - NotNull(serviceCollection, nameof(serviceCollection)); - - var loggerFactory = GetLoggerFactory(serviceCollection); - EnsureNotNull(loggerFactory, "No instance of ILoggerFactory found in {0}.", nameof(serviceCollection)); - - return WithMicrosoftLogging(part, loggerFactory); - } - - private static ILoggerFactory GetLoggerFactory(IServiceCollection serviceCollection) - { - var loggerFactoryDescriptor = serviceCollection.FirstOrDefault(p => p.ServiceType.Equals(typeof(ILoggerFactory))); - - // relying on singleton here, which should be fine ~~ still hacked - return loggerFactoryDescriptor?.ImplementationInstance as ILoggerFactory; - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Serialization.Bond/BondCompactBinaryCacheSerializer.cs b/src/CacheManager.Serialization.Bond/BondCompactBinaryCacheSerializer.cs index b9e8dcb2..751eab83 100644 --- a/src/CacheManager.Serialization.Bond/BondCompactBinaryCacheSerializer.cs +++ b/src/CacheManager.Serialization.Bond/BondCompactBinaryCacheSerializer.cs @@ -1,11 +1,7 @@ using System; using System.Linq; using Bond; -#if !NOUNSAFE using Bond.IO.Unsafe; -#else -using Bond.IO.Safe; -#endif using Bond.Protocols; using CacheManager.Core.Internal; @@ -39,7 +35,7 @@ public BondCompactBinaryCacheSerializer(int defaultBufferSize) : base(defaultBuf public override byte[] Serialize(T value) { var serializer = _cache.GetSerializer(value.GetType()); - var buffer = OutputBufferPool.Lease(); + var buffer = OutputBufferPool.Get(); var writer = _cache.CreateWriter(buffer); serializer.Serialize(value, writer); @@ -83,4 +79,4 @@ protected override Serializer> CreateSerialize } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Bond/BondConfigurationBuilderExtensions.cs b/src/CacheManager.Serialization.Bond/BondConfigurationBuilderExtensions.cs index 536db904..05e7aabd 100644 --- a/src/CacheManager.Serialization.Bond/BondConfigurationBuilderExtensions.cs +++ b/src/CacheManager.Serialization.Bond/BondConfigurationBuilderExtensions.cs @@ -1,5 +1,5 @@ -using CacheManager.Serialization.Bond; -using static CacheManager.Core.Utility.Guard; +using System; +using CacheManager.Serialization.Bond; namespace CacheManager.Core { @@ -17,7 +17,10 @@ public static class BondConfigurationBuilderExtensions /// The builder instance. public static ConfigurationBuilderCachePart WithBondCompactBinarySerializer(this ConfigurationBuilderCachePart part, int defaultWriteBufferSize = 1024) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(BondCompactBinaryCacheSerializer), defaultWriteBufferSize); } @@ -31,7 +34,10 @@ public static ConfigurationBuilderCachePart WithBondCompactBinarySerializer(this /// The builder instance. public static ConfigurationBuilderCachePart WithBondFastBinarySerializer(this ConfigurationBuilderCachePart part, int defaultWriteBufferSize = 1024) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(BondFastBinaryCacheSerializer), defaultWriteBufferSize); } @@ -44,9 +50,12 @@ public static ConfigurationBuilderCachePart WithBondFastBinarySerializer(this Co /// The builder instance. public static ConfigurationBuilderCachePart WithBondSimpleJsonSerializer(this ConfigurationBuilderCachePart part) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(BondSimpleJsonCacheSerializer)); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Bond/BondFastBinaryCacheSerializer.cs b/src/CacheManager.Serialization.Bond/BondFastBinaryCacheSerializer.cs index b596c5fa..1de861a4 100644 --- a/src/CacheManager.Serialization.Bond/BondFastBinaryCacheSerializer.cs +++ b/src/CacheManager.Serialization.Bond/BondFastBinaryCacheSerializer.cs @@ -1,11 +1,7 @@ using System; using System.Linq; using Bond; -#if !NOUNSAFE using Bond.IO.Unsafe; -#else -using Bond.IO.Safe; -#endif using Bond.Protocols; using CacheManager.Core.Internal; @@ -39,7 +35,7 @@ public BondFastBinaryCacheSerializer(int defaultWriteBufferSize) : base(defaultW public override byte[] Serialize(T value) { var serializer = _cache.GetSerializer(value.GetType()); - var buffer = OutputBufferPool.Lease(); + var buffer = OutputBufferPool.Get(); var writer = _cache.CreateWriter(buffer); serializer.Serialize(value, writer); @@ -83,4 +79,4 @@ protected override Serializer> CreateSerializer(T } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Bond/BondSerializerBase.cs b/src/CacheManager.Serialization.Bond/BondSerializerBase.cs index 3825cc49..5a456373 100644 --- a/src/CacheManager.Serialization.Bond/BondSerializerBase.cs +++ b/src/CacheManager.Serialization.Bond/BondSerializerBase.cs @@ -1,13 +1,8 @@ using System; -using System.Linq; using System.Text; -#if !NOUNSAFE using Bond.IO.Unsafe; -#else -using Bond.IO.Safe; -#endif using CacheManager.Core.Internal; -using CacheManager.Core.Utility; +using Microsoft.Extensions.ObjectPool; namespace CacheManager.Serialization.Bond { @@ -32,10 +27,10 @@ public BondSerializerBase() /// The default buffer size. public BondSerializerBase(int defaultBufferSize) { - OutputBufferPool = new ObjectPool(new OutputBufferPoolPolicy(defaultBufferSize)); - StringBuilderPool = new ObjectPool(new StringBuilderPoolPolicy(defaultBufferSize)); + OutputBufferPool = new DefaultObjectPool(new OutputBufferPoolPolicy(defaultBufferSize)); + StringBuilderPool = new DefaultObjectPool(new StringBuilderPoolPolicy(defaultBufferSize)); } - + /// /// Gets a pool handling s. /// @@ -45,6 +40,7 @@ public BondSerializerBase(int defaultBufferSize) /// /// Gets a pool handling s. /// + [CLSCompliant(false)] protected ObjectPool StringBuilderPool { get; } /// @@ -59,7 +55,7 @@ protected override object CreateNewItem(ICacheItemProperties proper return new BondCacheItem(properties, value); } - private class OutputBufferPoolPolicy : IObjectPoolPolicy + private class OutputBufferPoolPolicy : IPooledObjectPolicy { private readonly int _defaultBufferSize; @@ -68,7 +64,7 @@ public OutputBufferPoolPolicy(int defaultBufferSize) _defaultBufferSize = defaultBufferSize; } - public OutputBuffer CreateNew() + public OutputBuffer Create() { return new OutputBuffer(_defaultBufferSize); } @@ -85,7 +81,7 @@ public bool Return(OutputBuffer value) } } - private class StringBuilderPoolPolicy : IObjectPoolPolicy + private class StringBuilderPoolPolicy : IPooledObjectPolicy { private readonly int _defaultBufferSize; @@ -94,7 +90,7 @@ public StringBuilderPoolPolicy(int defaultBufferSize) _defaultBufferSize = defaultBufferSize; } - public StringBuilder CreateNew() + public StringBuilder Create() { return new StringBuilder(_defaultBufferSize); } @@ -111,4 +107,4 @@ public bool Return(StringBuilder value) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Bond/BondSimpleJsonCacheSerializer.cs b/src/CacheManager.Serialization.Bond/BondSimpleJsonCacheSerializer.cs index e2898016..bd8d4ddd 100644 --- a/src/CacheManager.Serialization.Bond/BondSimpleJsonCacheSerializer.cs +++ b/src/CacheManager.Serialization.Bond/BondSimpleJsonCacheSerializer.cs @@ -3,11 +3,7 @@ using System.Linq; using System.Text; using Bond; -#if !NOUNSAFE using Bond.IO.Unsafe; -#else -using Bond.IO.Safe; -#endif using Bond.Protocols; using CacheManager.Core.Internal; @@ -41,7 +37,7 @@ public BondSimpleJsonCacheSerializer(int defaultWriteBufferSize) : base(defaultW public override byte[] Serialize(T value) { var serializer = _cache.GetSerializer(value.GetType()); - var buffer = StringBuilderPool.Lease(); + var buffer = StringBuilderPool.Get(); using (var stringWriter = new StringWriter(buffer)) { @@ -90,4 +86,4 @@ protected override Serializer CreateSerializer(Type type) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Bond/CacheManager.Serialization.Bond.csproj b/src/CacheManager.Serialization.Bond/CacheManager.Serialization.Bond.csproj index c3a0a06b..dbe0fa36 100644 --- a/src/CacheManager.Serialization.Bond/CacheManager.Serialization.Bond.csproj +++ b/src/CacheManager.Serialization.Bond/CacheManager.Serialization.Bond.csproj @@ -1,23 +1,25 @@  - CacheManager extension package providing Microsoft Bond based serialization for distributed caches. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. The Core library contains a Newtonsoft.Json based serializer implementation which can be used instead of the default binary serializer. - netstandard1.2;netstandard1.3;net40;net45 + CacheManager extension package providing Microsoft Bond based serialization for distributed caches. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. + netstandard2.0;net8.0 true true Caching;Cache;CacheManager;Serialization;Bond + true - - - - + + + + - - $(DefineConstants);NOUNSAFE - - + + + + + \ No newline at end of file diff --git a/src/CacheManager.Serialization.Bond/SerializerCache.cs b/src/CacheManager.Serialization.Bond/SerializerCache.cs index 901c0df0..d91f423d 100644 --- a/src/CacheManager.Serialization.Bond/SerializerCache.cs +++ b/src/CacheManager.Serialization.Bond/SerializerCache.cs @@ -2,11 +2,7 @@ using System.Collections.Concurrent; using System.Linq; using Bond; -#if !NOUNSAFE using Bond.IO.Unsafe; -#else -using Bond.IO.Safe; -#endif namespace CacheManager.Serialization.Bond { @@ -47,4 +43,4 @@ public Deserializer GetDeserializer(Type type) protected abstract Deserializer CreateDeserializer(Type type); } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.DataContract/CacheManager.Serialization.DataContract.csproj b/src/CacheManager.Serialization.DataContract/CacheManager.Serialization.DataContract.csproj new file mode 100644 index 00000000..1b5c7f7f --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/CacheManager.Serialization.DataContract.csproj @@ -0,0 +1,17 @@ + + + + CacheManager extension package providing DataContract serialization for distributed caches. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. + netstandard2.0 + true + true + Caching;Cache;CacheManager;Serialization;DataContract + rebulanyum, MichaConrad + true + + + + + + + diff --git a/src/CacheManager.Serialization.DataContract/DataContractBinaryCacheSerializer.cs b/src/CacheManager.Serialization.DataContract/DataContractBinaryCacheSerializer.cs new file mode 100644 index 00000000..106c2688 --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractBinaryCacheSerializer.cs @@ -0,0 +1,43 @@ +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Xml; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// This class (de)serializes objects with binary format via using DataContractSerializer. + /// + public class DataContractBinaryCacheSerializer : DataContractCacheSerializer + { + /// + /// Creates instance of DataContractBinaryCacheSerializer. + /// + public DataContractBinaryCacheSerializer() : this(new DataContractSerializerSettings()) + { + } + + /// + /// Creates instance of DataContractBinaryCacheSerializer. + /// + /// The settings for DataContractSerializer. + public DataContractBinaryCacheSerializer(DataContractSerializerSettings serializerSettings = null) : base(serializerSettings) + { + } + + /// + protected override object ReadObject(XmlObjectSerializer serializer, Stream stream) + { + var binaryDictionaryReader = XmlDictionaryReader.CreateBinaryReader(stream, new XmlDictionaryReaderQuotas()); + return serializer.ReadObject(binaryDictionaryReader); + } + + /// + protected override void WriteObject(XmlObjectSerializer serializer, Stream stream, object graph) + { + var binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream); + serializer.WriteObject(binaryDictionaryWriter, graph); + binaryDictionaryWriter.Flush(); + } + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractCacheItem.cs b/src/CacheManager.Serialization.DataContract/DataContractCacheItem.cs new file mode 100644 index 00000000..62c09ef8 --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractCacheItem.cs @@ -0,0 +1,50 @@ +using System; +using System.Runtime.Serialization; +using CacheManager.Core; +using CacheManager.Core.Internal; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// The data contract cache item will be used to serialize a . + /// A cannot be deserialized by DataContractSerializer because of the private setters. + /// + [DataContract] + internal class DataContractCacheItem : SerializerCacheItem + { + public DataContractCacheItem() + { + } + + public DataContractCacheItem(ICacheItemProperties properties, object value) : base(properties, value) + { + } + + [DataMember(Name = "createdUtc")] + public override long CreatedUtc { get; set; } + + [DataMember(Name = "expirationMode")] + public override ExpirationMode ExpirationMode { get; set; } + + [DataMember(Name = "expirationTimeout")] + public override double ExpirationTimeout { get; set; } + + [DataMember(Name = "key")] + public override string Key { get; set; } + + [DataMember(Name = "lastAccessedUtc")] + public override long LastAccessedUtc { get; set; } + + [DataMember(Name = "region")] + public override string Region { get; set; } + + [DataMember(Name = "value")] + public override T Value { get; set; } + + [DataMember(Name = "usesExpirationDefaults")] + public override bool UsesExpirationDefaults { get; set; } + + [DataMember(Name = "valueType")] + public override string ValueType { get; set; } + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractCacheSerializer.cs b/src/CacheManager.Serialization.DataContract/DataContractCacheSerializer.cs new file mode 100644 index 00000000..f85ec99c --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractCacheSerializer.cs @@ -0,0 +1,39 @@ +using System; +using System.Runtime.Serialization; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// This class uses DataContractSerializer for (de)serialization. + /// + public class DataContractCacheSerializer : DataContractCacheSerializerBase + { + /// + /// Creates instance of DataContractCacheSerializer. + /// + public DataContractCacheSerializer() : this(new DataContractSerializerSettings()) + { + } + + /// + /// Creates instance of DataContractCacheSerializer. + /// + /// The settings for DataContractSerializer. + public DataContractCacheSerializer(DataContractSerializerSettings serializerSettings = null) : base(serializerSettings) + { + } + + /// + protected override XmlObjectSerializer GetSerializer(Type target) + { + if (SerializerSettings == null) + { + return new DataContractSerializer(target); + } + else + { + return new DataContractSerializer(target, SerializerSettings); + } + } + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractCacheSerializerBase.cs b/src/CacheManager.Serialization.DataContract/DataContractCacheSerializerBase.cs new file mode 100644 index 00000000..8acc82be --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractCacheSerializerBase.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Runtime.Serialization; +using CacheManager.Core.Internal; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// Implementing the contract using System.Runtime.Serialization as a base class. + /// + /// Type of settings for the serializers in the namespace System.Runtime.Serialization + public abstract class DataContractCacheSerializerBase : CacheSerializer + { + private static readonly Type _openItemType = typeof(DataContractCacheItem<>); + + /// + /// Gets the settings which should be used during deserialization/serialization. + /// + /// The deserialization/serialization settings. + public TSettings SerializerSettings { get; private set; } + + /// + /// Base constructor for the objects that inherit DataContractCacheSerializerBase. + /// + /// Serializer's settings + protected DataContractCacheSerializerBase(TSettings serializerSettings) + { + SerializerSettings = serializerSettings; + } + + /// + protected override object CreateNewItem(ICacheItemProperties properties, object value) + { + return new DataContractCacheItem(properties, value); + } + + /// + protected override Type GetOpenGeneric() + { + return _openItemType; + } + + /// + public override byte[] Serialize(T value) + { + if (value == null) + { + return null; + } + + var serializer = GetSerializer(value.GetType()); + using (var stream = new MemoryStream()) + { + WriteObject(serializer, stream, value); + return stream.ToArray(); + } + } + + /// + public override object Deserialize(byte[] data, Type target) + { + if (data == null) + { + return null; + } + + var serializer = GetSerializer(target); + using (var stream = new MemoryStream(data)) + { + return ReadObject(serializer, stream); + } + } + + /// + /// Deserializes the given with the given . + /// + /// The serializer that's going to be used for deserialization. + /// The stream that's including the serialized data. + /// The deserialized object. + protected virtual object ReadObject(XmlObjectSerializer serializer, Stream stream) + { + return serializer.ReadObject(stream); + } + + /// + /// Serializes the given into with the given . + /// + /// The serializer that's going to be used for serialization. + /// The stream that the will be serialized into. + /// The object that will be serialized. + protected virtual void WriteObject(XmlObjectSerializer serializer, Stream stream, object graph) + { + serializer.WriteObject(stream, graph); + } + + /// + /// Gets the DataContract serializer for the target type. + /// + /// The target type for serializer. + /// Returns the serializer. + protected abstract XmlObjectSerializer GetSerializer(Type target); + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractConfigurationBuilderExtensions.cs b/src/CacheManager.Serialization.DataContract/DataContractConfigurationBuilderExtensions.cs new file mode 100644 index 00000000..d328c44b --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractConfigurationBuilderExtensions.cs @@ -0,0 +1,105 @@ +using System; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using CacheManager.Serialization.DataContract; + +namespace CacheManager.Core +{ + /// + /// Extensions for the configuration builder for the DataContract based ICacheSerializer. + /// + public static class DataContractConfigurationBuilderExtensions + { + /// + /// Configures the cache manager to use the DataContract based cache serializer. + /// + /// The configuration part. + /// Settings for the serializer. + /// The builder instance. + public static ConfigurationBuilderCachePart WithDataContractSerializer(this ConfigurationBuilderCachePart part, DataContractSerializerSettings serializerSettings = null) + { + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } + + if (serializerSettings == null) + { + return part.WithSerializer(typeof(DataContractCacheSerializer)); + } + else + { + return part.WithSerializer(typeof(DataContractCacheSerializer), serializerSettings); + } + } + + /// + /// Configures the cache manager to use the DataContract based cache serializer in Json format. + /// + /// The configuration part. + /// Settings for the serializer. + /// The builder instance. + public static ConfigurationBuilderCachePart WithDataContractJsonSerializer(this ConfigurationBuilderCachePart part, DataContractJsonSerializerSettings serializerSettings = null) + { + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } + + if (serializerSettings == null) + { + return part.WithSerializer(typeof(DataContractJsonCacheSerializer)); + } + else + { + return part.WithSerializer(typeof(DataContractJsonCacheSerializer), serializerSettings); + } + } + + /// + /// Configures the cache manager to use the DataContract based cache serializer in Json format with compression. + /// + /// The configuration part. + /// Settings for the serializer. + /// The builder instance. + public static ConfigurationBuilderCachePart WithDataContractGzJsonSerializer(this ConfigurationBuilderCachePart part, DataContractJsonSerializerSettings serializerSettings = null) + { + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } + + if (serializerSettings == null) + { + return part.WithSerializer(typeof(DataContractGzJsonCacheSerializer)); + } + else + { + return part.WithSerializer(typeof(DataContractGzJsonCacheSerializer), serializerSettings); + } + } + + /// + /// Configures the cache manager to use the DataContract based cache serializer in binary format. + /// + /// The configuration part. + /// Settings for the serializer. + /// The builder instance. + public static ConfigurationBuilderCachePart WithDataContractBinarySerializer(this ConfigurationBuilderCachePart part, DataContractSerializerSettings serializerSettings = null) + { + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } + + if (serializerSettings == null) + { + return part.WithSerializer(typeof(DataContractBinaryCacheSerializer)); + } + else + { + return part.WithSerializer(typeof(DataContractBinaryCacheSerializer), serializerSettings); + } + } + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractGzJsonCacheSerializer.cs b/src/CacheManager.Serialization.DataContract/DataContractGzJsonCacheSerializer.cs new file mode 100644 index 00000000..d320ae48 --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractGzJsonCacheSerializer.cs @@ -0,0 +1,48 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// This class (de)compresses the (de)serialized output of DataContractJsonCacheSerializer. + /// + public class DataContractGzJsonCacheSerializer : DataContractJsonCacheSerializer + { + /// + /// Creates instance of DataContractGzJsonCacheSerializer. + /// + public DataContractGzJsonCacheSerializer() : this(new DataContractJsonSerializerSettings()) + { + } + + /// + /// Creates instance of DataContractGzJsonCacheSerializer. + /// + /// Serializer's settings + public DataContractGzJsonCacheSerializer(DataContractJsonSerializerSettings serializerSettings = null) : base(serializerSettings) + { + } + + /// + protected override void WriteObject(XmlObjectSerializer serializer, Stream stream, object graph) + { + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, true)) + { + base.WriteObject(serializer, gzipStream, graph); + gzipStream.Flush(); + } + } + + /// + protected override object ReadObject(XmlObjectSerializer serializer, Stream stream) + { + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress)) + { + return base.ReadObject(serializer, gzipStream); + } + } + } +} diff --git a/src/CacheManager.Serialization.DataContract/DataContractJsonCacheSerializer.cs b/src/CacheManager.Serialization.DataContract/DataContractJsonCacheSerializer.cs new file mode 100644 index 00000000..3a0e0954 --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/DataContractJsonCacheSerializer.cs @@ -0,0 +1,40 @@ +using System; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; + +namespace CacheManager.Serialization.DataContract +{ + /// + /// This class uses DataContractJsonSerialzer for (de)serialization. + /// + public class DataContractJsonCacheSerializer : DataContractCacheSerializerBase + { + /// + /// Creates instance of DataContractJsonCacheSerializer. + /// + public DataContractJsonCacheSerializer() : this(new DataContractJsonSerializerSettings()) + { + } + + /// + /// Creates instance of DataContractJsonCacheSerializer. + /// + /// Serializer's settings + public DataContractJsonCacheSerializer(DataContractJsonSerializerSettings serializerSettings = null) : base(serializerSettings) + { + } + + /// + protected override XmlObjectSerializer GetSerializer(Type target) + { + if (SerializerSettings == null) + { + return new DataContractJsonSerializer(target); + } + else + { + return new DataContractJsonSerializer(target, SerializerSettings); + } + } + } +} diff --git a/src/CacheManager.Serialization.DataContract/Properties/AssemblyInfo.cs b/src/CacheManager.Serialization.DataContract/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..8c114539 --- /dev/null +++ b/src/CacheManager.Serialization.DataContract/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System; + +[assembly: CLSCompliant(true)] diff --git a/src/CacheManager.Serialization.Json/CacheManager.Serialization.Json.csproj b/src/CacheManager.Serialization.Json/CacheManager.Serialization.Json.csproj index f4969afe..6ce27971 100644 --- a/src/CacheManager.Serialization.Json/CacheManager.Serialization.Json.csproj +++ b/src/CacheManager.Serialization.Json/CacheManager.Serialization.Json.csproj @@ -2,19 +2,24 @@ CacheManager extension package providing JSON serialization for distributed caches. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. The Core library contains a Newtonsoft.Json based serializer implementation which can be used instead of the default binary serializer. - netstandard1.2;net40;net45 + netstandard2.0;net8.0 true true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + Caching;Cache;CacheManager;Distributed Cache;JSON;Serialization + true - - + + - + + + - + + + \ No newline at end of file diff --git a/src/CacheManager.Serialization.Json/GzJsonCacheSerializer.cs b/src/CacheManager.Serialization.Json/GzJsonCacheSerializer.cs index 6106d572..3240163c 100644 --- a/src/CacheManager.Serialization.Json/GzJsonCacheSerializer.cs +++ b/src/CacheManager.Serialization.Json/GzJsonCacheSerializer.cs @@ -1,14 +1,12 @@ using System; using System.IO; using System.IO.Compression; -using System.Linq; -using CacheManager.Core.Utility; using Newtonsoft.Json; namespace CacheManager.Serialization.Json { /// - /// Implements the ICacheSerializer contract using Newtonsoft.Json and the loseless compression. + /// Implements the ICacheSerializer contract using Newtonsoft.Json and the lossless compression. /// public class GzJsonCacheSerializer : JsonCacheSerializer { @@ -34,7 +32,11 @@ public GzJsonCacheSerializer(JsonSerializerSettings serializationSettings, JsonS /// public override object Deserialize(byte[] data, Type target) { - Guard.NotNull(data, nameof(data)); + if (data is null) + { + throw new ArgumentNullException(nameof(data)); + } + var compressedData = Decompression(data); return base.Deserialize(compressedData, target); @@ -43,7 +45,6 @@ public override object Deserialize(byte[] data, Type target) /// public override byte[] Serialize(T value) { - Guard.NotNull(value, nameof(value)); var data = base.Serialize(value); return Compression(data); @@ -58,11 +59,7 @@ protected virtual byte[] Compression(byte[] data) { using (var bytesBuilder = new MemoryStream()) { -#if NET40 - using (var gzWriter = new GZipStream(bytesBuilder, CompressionMode.Compress, true)) -#else using (var gzWriter = new GZipStream(bytesBuilder, CompressionLevel.Fastest, true)) -#endif { gzWriter.Write(data, 0, data.Length); bytesBuilder.Flush(); @@ -94,4 +91,4 @@ protected virtual byte[] Decompression(byte[] compressedData) } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Json/JsonCacheSerializer.cs b/src/CacheManager.Serialization.Json/JsonCacheSerializer.cs index 5577a0ca..4d8e57db 100644 --- a/src/CacheManager.Serialization.Json/JsonCacheSerializer.cs +++ b/src/CacheManager.Serialization.Json/JsonCacheSerializer.cs @@ -1,10 +1,9 @@ using System; using System.IO; -using System.Linq; using System.Text; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Utility; +using Microsoft.Extensions.ObjectPool; using Newtonsoft.Json; namespace CacheManager.Serialization.Json @@ -35,12 +34,19 @@ public JsonCacheSerializer() /// The settings which should be used during deserialization. public JsonCacheSerializer(JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings) { - Guard.NotNull(serializationSettings, nameof(serializationSettings)); - Guard.NotNull(deserializationSettings, nameof(deserializationSettings)); + if (serializationSettings is null) + { + throw new ArgumentNullException(nameof(serializationSettings)); + } + + if (deserializationSettings is null) + { + throw new ArgumentNullException(nameof(deserializationSettings)); + } _serializer = JsonSerializer.Create(serializationSettings); _deserializer = JsonSerializer.Create(deserializationSettings); - _stringBuilderPool = new ObjectPool(new StringBuilderPoolPolicy(100)); + _stringBuilderPool = new DefaultObjectPool(new StringBuilderPooledObjectPolicy()); SerializationSettings = serializationSettings; DeserializationSettings = deserializationSettings; } @@ -73,7 +79,12 @@ public override object Deserialize(byte[] data, Type target) /// public override byte[] Serialize(T value) { - var buffer = _stringBuilderPool.Lease(); + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + var buffer = _stringBuilderPool.Get(); using (var stringWriter = new JsonTextWriter(new StringWriter(buffer))) { @@ -96,31 +107,5 @@ protected override object CreateNewItem(ICacheItemProperties proper { return new JsonCacheItem(properties, value); } - - private class StringBuilderPoolPolicy : IObjectPoolPolicy - { - private readonly int _defaultBufferSize; - - public StringBuilderPoolPolicy(int defaultBufferSize) - { - _defaultBufferSize = defaultBufferSize; - } - - public StringBuilder CreateNew() - { - return new StringBuilder(_defaultBufferSize); - } - - public bool Return(StringBuilder value) - { - ////if (value.Data.Count > _defaultBufferSize * 1000) - ////{ - //// return false; - ////} - - value.Clear(); - return true; - } - } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.Json/JsonConfigurationBuilderExtensions.cs b/src/CacheManager.Serialization.Json/JsonConfigurationBuilderExtensions.cs index 050ff630..85c8027c 100644 --- a/src/CacheManager.Serialization.Json/JsonConfigurationBuilderExtensions.cs +++ b/src/CacheManager.Serialization.Json/JsonConfigurationBuilderExtensions.cs @@ -1,6 +1,6 @@ -using CacheManager.Serialization.Json; +using System; +using CacheManager.Serialization.Json; using Newtonsoft.Json; -using static CacheManager.Core.Utility.Guard; namespace CacheManager.Core { @@ -16,7 +16,10 @@ public static class JsonConfigurationBuilderExtensions /// The builder instance. public static ConfigurationBuilderCachePart WithJsonSerializer(this ConfigurationBuilderCachePart part) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(JsonCacheSerializer)); } @@ -30,7 +33,10 @@ public static ConfigurationBuilderCachePart WithJsonSerializer(this Configuratio /// The builder instance. public static ConfigurationBuilderCachePart WithJsonSerializer(this ConfigurationBuilderCachePart part, JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(JsonCacheSerializer), serializationSettings, deserializationSettings); } @@ -42,7 +48,10 @@ public static ConfigurationBuilderCachePart WithJsonSerializer(this Configuratio /// The builder instance. public static ConfigurationBuilderCachePart WithGzJsonSerializer(this ConfigurationBuilderCachePart part) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(GzJsonCacheSerializer)); } @@ -56,9 +65,12 @@ public static ConfigurationBuilderCachePart WithGzJsonSerializer(this Configurat /// The builder instance. public static ConfigurationBuilderCachePart WithGzJsonSerializer(this ConfigurationBuilderCachePart part, JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings) { - NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(GzJsonCacheSerializer), serializationSettings, deserializationSettings); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.Serialization.ProtoBuf/CacheManager.Serialization.ProtoBuf.csproj b/src/CacheManager.Serialization.ProtoBuf/CacheManager.Serialization.ProtoBuf.csproj index 09c61d7a..1dfec701 100644 --- a/src/CacheManager.Serialization.ProtoBuf/CacheManager.Serialization.ProtoBuf.csproj +++ b/src/CacheManager.Serialization.ProtoBuf/CacheManager.Serialization.ProtoBuf.csproj @@ -3,19 +3,16 @@ CacheManager extension package providing ProtoBuf serialization for distributed caches. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features, the ProtoBuf serializer can be used in place of the default Binary Serializer Wenisman;MichaConrad - netstandard1.3;net40;net45 + netstandard2.0;net6.0;net8.0 true true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + Caching;Cache;CacheManager;Distributed Cache;Serialization;Protobuf + true - - - - - + \ No newline at end of file diff --git a/src/CacheManager.Serialization.ProtoBuf/ProtoBufConfigurationBuilderExtensions.cs b/src/CacheManager.Serialization.ProtoBuf/ProtoBufConfigurationBuilderExtensions.cs index 2c5402dd..3566389a 100644 --- a/src/CacheManager.Serialization.ProtoBuf/ProtoBufConfigurationBuilderExtensions.cs +++ b/src/CacheManager.Serialization.ProtoBuf/ProtoBufConfigurationBuilderExtensions.cs @@ -1,4 +1,5 @@ -using CacheManager.Serialization.ProtoBuf; +using System; +using CacheManager.Serialization.ProtoBuf; namespace CacheManager.Core { @@ -14,7 +15,10 @@ public static class ProtoBufConfigurationBuilderExtensions /// The builder instance. public static ConfigurationBuilderCachePart WithProtoBufSerializer(this ConfigurationBuilderCachePart part) { - Utility.Guard.NotNull(part, nameof(part)); + if (part is null) + { + throw new ArgumentNullException(nameof(part)); + } return part.WithSerializer(typeof(ProtoBufSerializer)); } diff --git a/src/CacheManager.Serialization.ProtoBuf/ProtoBufSerializer.cs b/src/CacheManager.Serialization.ProtoBuf/ProtoBufSerializer.cs index ca8dee18..0a5c1260 100644 --- a/src/CacheManager.Serialization.ProtoBuf/ProtoBufSerializer.cs +++ b/src/CacheManager.Serialization.ProtoBuf/ProtoBufSerializer.cs @@ -1,7 +1,5 @@ using System; using System.IO; -using System.Linq; -using CacheManager.Core; using CacheManager.Core.Internal; using ProtoBuf; @@ -55,4 +53,4 @@ protected override Type GetOpenGeneric() return _openGenericItemType; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/CacheManager.StackExchange.Redis.csproj b/src/CacheManager.StackExchange.Redis/CacheManager.StackExchange.Redis.csproj index 09252326..1dd2a491 100644 --- a/src/CacheManager.StackExchange.Redis/CacheManager.StackExchange.Redis.csproj +++ b/src/CacheManager.StackExchange.Redis/CacheManager.StackExchange.Redis.csproj @@ -2,24 +2,22 @@ CacheManager extension package which adds support for Redis as a distributed cache layer. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. - net45;netstandard1.5 + net472;netstandard2.0;net80 true true Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + true - + - + - - - - - $(DefineConstants);NETSTANDARD + + $(DefineConstants);NETSTANDARD2_0 \ No newline at end of file diff --git a/src/CacheManager.StackExchange.Redis/RedisCacheBackplane.cs b/src/CacheManager.StackExchange.Redis/RedisCacheBackplane.cs index 1254d7f1..5af371e7 100644 --- a/src/CacheManager.StackExchange.Redis/RedisCacheBackplane.cs +++ b/src/CacheManager.StackExchange.Redis/RedisCacheBackplane.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using StackExchange.Redis; using static CacheManager.Core.Utility.Guard; @@ -27,7 +27,8 @@ namespace CacheManager.Redis /// public sealed class RedisCacheBackplane : CacheBackplane { - private readonly string _channelName; + private const int HardLimit = 50000; + private readonly RedisChannel _channel; private readonly byte[] _identifier; private readonly ILogger _logger; private readonly RedisConnectionManager _connection; @@ -37,6 +38,7 @@ public sealed class RedisCacheBackplane : CacheBackplane private int _skippedMessages = 0; private bool _sending = false; private CancellationTokenSource _source = new CancellationTokenSource(); + private bool loggedLimitWarningOnce = false; /// /// Initializes a new instance of the class. @@ -49,8 +51,8 @@ public RedisCacheBackplane(ICacheManagerConfiguration configuration, ILoggerFact NotNull(configuration, nameof(configuration)); NotNull(loggerFactory, nameof(loggerFactory)); - _logger = loggerFactory.CreateLogger(this); - _channelName = configuration.BackplaneChannelName ?? "CacheManagerBackplane"; + _logger = loggerFactory.CreateLogger(this.GetType()); + _channel = RedisChannel.Literal(configuration.BackplaneChannelName ?? "CacheManagerBackplane"); _identifier = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()); var cfg = RedisConfigurations.GetConfiguration(ConfigurationKey); @@ -61,7 +63,7 @@ public RedisCacheBackplane(ICacheManagerConfiguration configuration, ILoggerFact RetryHelper.Retry(() => Subscribe(), configuration.RetryTimeout, configuration.MaxRetries, _logger); // adding additional timer based send message invoke (shouldn't do anything if there are no messages, - // but in really rare race conditions, it might happen messages do not get send if SendMEssages only get invoked through "NotifyXyz" + // but in really rare race conditions, it might happen messages do not get send if SendMessages only get invoked through "NotifyXyz" _timer = new Timer(SendMessages, true, 1000, 1000); } @@ -136,7 +138,7 @@ protected override void Dispose(bool managed) try { _source.Cancel(); - _connection.Subscriber.Unsubscribe(_channelName); + _connection.Subscriber.Unsubscribe(_channel); _timer.Dispose(); } catch @@ -149,7 +151,7 @@ protected override void Dispose(bool managed) private void Publish(byte[] message) { - _connection.Subscriber.Publish(_channelName, message, CommandFlags.HighPriority); + _connection.Subscriber.Publish(_channel, message); } private void PublishMessage(BackplaneMessage message) @@ -162,7 +164,15 @@ private void PublishMessage(BackplaneMessage message) _messages.Clear(); } - if (!_messages.Add(message)) + if (_messages.Count > HardLimit) + { + if (!loggedLimitWarningOnce) + { + _logger.LogError("Exceeded hard limit of number of messages pooled to send through the backplane. Skipping new messages..."); + loggedLimitWarningOnce = true; + } + } + else if (!_messages.Add(message)) { Interlocked.Increment(ref _skippedMessages); if (_logger.IsEnabled(LogLevel.Trace)) @@ -194,11 +204,10 @@ private void SendMessages(object state) _sending = true; if (state != null && state is bool boolState && boolState == true) { - _logger.LogInfo($"Backplane is sending {_messages.Count} messages triggered by timer."); + _logger.LogInformation($"Backplane is sending {_messages.Count} messages triggered by timer."); } -#if !NET40 - await Task.Delay(10).ConfigureAwait(false); -#endif + + await Task.Delay(50).ConfigureAwait(false); byte[] msgs = null; lock (_messageLock) { @@ -211,47 +220,42 @@ private void SendMessages(object state) _logger.LogDebug("Backplane is sending {0} messages ({1} skipped).", _messages.Count, _skippedMessages); } - Interlocked.Add(ref MessagesSent, _messages.Count); - _skippedMessages = 0; - _messages.Clear(); - } - - try - { - if (msgs != null) + try { - Publish(msgs); - Interlocked.Increment(ref SentChunks); + if (msgs != null) + { + Publish(msgs); + Interlocked.Increment(ref SentChunks); + Interlocked.Add(ref MessagesSent, _messages.Count); + _skippedMessages = 0; + + // clearing up only after successfully sending. Basically retrying... + _messages.Clear(); + + // reset log limiter because we just send stuff + loggedLimitWarningOnce = false; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error occurred sending backplane messages."); } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error occurred sending backplane messages."); } _sending = false; } -#if NET40 - }, - this, - _source.Token, - TaskCreationOptions.None, - TaskScheduler.Default) - .ConfigureAwait(false); -#else }, this, _source.Token, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default) .ConfigureAwait(false); -#endif } private void Subscribe() { _connection.Subscriber.Subscribe( - _channelName, + _channel, (channel, msg) => { try @@ -270,7 +274,7 @@ private void Subscribe() if (_logger.IsEnabled(LogLevel.Information)) { - _logger.LogInfo("Backplane got notified with {0} new messages.", fullMessages.Length); + _logger.LogInformation("Backplane got notified with {0} new messages.", fullMessages.Length); } foreach (var message in fullMessages) @@ -311,10 +315,10 @@ private void Subscribe() } catch (Exception ex) { - _logger.LogWarn(ex, "Error reading backplane message(s)"); + _logger.LogWarning(ex, "Error reading backplane message(s)"); } }, CommandFlags.FireAndForget); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RedisCacheHandle.cs b/src/CacheManager.StackExchange.Redis/RedisCacheHandle.cs index 2950615d..1bbf54eb 100644 --- a/src/CacheManager.StackExchange.Redis/RedisCacheHandle.cs +++ b/src/CacheManager.StackExchange.Redis/RedisCacheHandle.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; +using System.Data.Common; using System.Linq; using System.Text; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using StackExchange.Redis; using static CacheManager.Core.Utility.Guard; @@ -29,18 +30,32 @@ public class RedisCacheHandle : BaseCacheHandle private static readonly string _scriptAdd = $@" if redis.call('HSETNX', KEYS[1], '{HashFieldValue}', ARGV[1]) == 1 then + if ARGV[7] ~= nil then + if (redis.call('HMSET', ARGV[7], KEYS[1], 'regionKey')) then + else + return -2 + end + end + local result=redis.call('HMSET', KEYS[1], '{HashFieldType}', ARGV[2], '{HashFieldExpirationMode}', ARGV[3], '{HashFieldExpirationTimeout}', ARGV[4], '{HashFieldCreated}', ARGV[5], '{HashFieldVersion}', 1, '{HashFieldUsesDefaultExp}', ARGV[6]) if ARGV[3] > '1' and ARGV[4] ~= '0' then redis.call('PEXPIRE', KEYS[1], ARGV[4]) else redis.call('PERSIST', KEYS[1]) end - return result + return 1 else return nil end"; private static readonly string _scriptPut = $@" +if ARGV[7] ~= nil then + if (redis.call('HMSET', ARGV[7], KEYS[1], 'regionKey')) then + else + return -2 + end +end + local result=redis.call('HMSET', KEYS[1], '{HashFieldValue}', ARGV[1], '{HashFieldType}', ARGV[2], '{HashFieldExpirationMode}', ARGV[3], '{HashFieldExpirationTimeout}', ARGV[4], '{HashFieldCreated}', ARGV[5], '{HashFieldUsesDefaultExp}', ARGV[6]) redis.call('HINCRBY', KEYS[1], '{HashFieldVersion}', 1) if ARGV[3] > '1' and ARGV[4] ~= '0' then @@ -48,7 +63,7 @@ public class RedisCacheHandle : BaseCacheHandle else redis.call('PERSIST', KEYS[1]) end -return result"; +return 1"; // script should also update expire now. If sliding, update the sliding window private static readonly string _scriptUpdate = $@" @@ -101,7 +116,7 @@ public RedisCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHa NotNull(configuration, nameof(configuration)); EnsureNotNull(serializer, "A serializer is required for the redis cache handle"); - Logger = loggerFactory.CreateLogger(this); + Logger = loggerFactory.CreateLogger(this.GetType()); _managerConfiguration = managerConfiguration; _valueConverter = new RedisValueConverter(serializer); _redisConfiguration = RedisConfigurations.GetConfiguration(configuration.Key); @@ -123,13 +138,13 @@ public RedisCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHa { if (!cfg.Value.Contains("E")) { - Logger.LogWarn("Server {0} is missing configuration value 'E' in notify-keyspace-events to enable keyevents.", cfg.Key); + Logger.LogWarning("Server {0} is missing configuration value 'E' in notify-keyspace-events to enable keyevents.", cfg.Key); } if (!(cfg.Value.Contains("A") || (cfg.Value.Contains("x") && cfg.Value.Contains("e")))) { - Logger.LogWarn("Server {0} is missing configuration value 'A' or 'x' and 'e' in notify-keyspace-events to enable keyevents for expired and evicted keys.", cfg.Key); + Logger.LogWarning("Server {0} is missing configuration value 'A' or 'x' and 'e' in notify-keyspace-events to enable keyevents for expired and evicted keys.", cfg.Key); } } } @@ -162,12 +177,12 @@ public override int Count { if (_redisConfiguration.TwemproxyEnabled) { - Logger.LogWarn("'Count' cannot be calculated. Twemproxy mode is enabled which does not support accessing the servers collection."); + Logger.LogWarning("'Count' cannot be calculated. Twemproxy mode is enabled which does not support accessing the servers collection."); return 0; } var count = 0; - foreach (var server in Servers.Where(p => !p.IsSlave && p.IsConnected)) + foreach (var server in Servers.Where(p => !p.IsReplica && p.IsConnected)) { count += (int)server.DatabaseSize(_redisConfiguration.Database); } @@ -210,7 +225,7 @@ public override void Clear() { try { - foreach (var server in Servers.Where(p => !p.IsSlave)) + foreach (var server in Servers.Where(p => !p.IsReplica)) { Retry(() => { @@ -497,7 +512,7 @@ private CacheItem GetCacheItemAndVersion(string key, string region, } else { - Logger.LogWarn("Expiration mode and timeout are set but are not valid '{0}', '{1}'.", expirationModeItem, timeoutItem); + Logger.LogWarning("Expiration mode and timeout are set but are not valid '{0}', '{1}'.", expirationModeItem, timeoutItem); } } @@ -580,7 +595,7 @@ protected CacheItem GetCacheItemInternalNoScript(string key, string } else { - Logger.LogWarn("Expiration mode and timeout are set but are not valid '{0}', '{1}'.", expirationModeItem, timeoutItem); + Logger.LogWarning("Expiration mode and timeout are set but are not valid '{0}', '{1}'.", expirationModeItem, timeoutItem); } } @@ -625,7 +640,7 @@ protected CacheItem GetCacheItemInternalNoScript(string key, string /// with the new value. If the item doesn't exist, the item will be added to the cache. /// /// The CacheItem to be added to the cache. - protected override void PutInternal(CacheItem item) + protected internal override void PutInternal(CacheItem item) => base.PutInternal(item); /// @@ -677,22 +692,22 @@ protected override bool RemoveInternal(string key, string region) private void SubscribeKeyspaceNotifications() { _connection.Subscriber.Subscribe( - $"__keyevent@{_redisConfiguration.Database}__:expired", - (channel, key) => - { - var tupple = ParseKey(key); - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("Got expired event for key '{0}:{1}'", tupple.Item2, tupple.Item1); - } - - // we cannot return the original value here because we don't have it - TriggerCacheSpecificRemove(tupple.Item1, tupple.Item2, CacheItemRemovedReason.Expired, null); - }); + channel: RedisChannel.Literal($"__keyevent@{_redisConfiguration.Database}__:expired"), + handler: (channel, key) => + { + var tupple = ParseKey(key); + if (Logger.IsEnabled(LogLevel.Debug)) + { + Logger.LogDebug("Got expired event for key '{0}:{1}'", tupple.Item2, tupple.Item1); + } + + // we cannot return the original value here because we don't have it + TriggerCacheSpecificRemove(tupple.Item1, tupple.Item2, CacheItemRemovedReason.Expired, null); + }); _connection.Subscriber.Subscribe( - $"__keyevent@{_redisConfiguration.Database}__:evicted", - (channel, key) => + channel: RedisChannel.Literal($"__keyevent@{_redisConfiguration.Database}__:evicted"), + handler: (channel, key) => { var tupple = ParseKey(key); if (Logger.IsEnabled(LogLevel.Debug)) @@ -705,8 +720,8 @@ private void SubscribeKeyspaceNotifications() }); _connection.Subscriber.Subscribe( - $"__keyevent@{_redisConfiguration.Database}__:del", - (channel, key) => + channel: RedisChannel.Literal($"__keyevent@{_redisConfiguration.Database}__:del"), + handler: (channel, key) => { var tupple = ParseKey(key); if (Logger.IsEnabled(LogLevel.Debug)) @@ -851,7 +866,8 @@ private bool Set(CacheItem item, When when, bool sync = false) (int)item.ExpirationMode, (long)item.ExpirationTimeout.TotalMilliseconds, item.CreatedUtc.Ticks, - item.UsesExpirationDefaults + item.UsesExpirationDefaults, + string.IsNullOrWhiteSpace(item.Region) ? string.Empty : item.Region }; RedisResult result; @@ -864,54 +880,32 @@ private bool Set(CacheItem item, When when, bool sync = false) result = Eval(ScriptType.Put, fullKey, parameters, flags); } - if (result == null) + if (result.IsNull && flags.HasFlag(CommandFlags.FireAndForget)) { - if (flags.HasFlag(CommandFlags.FireAndForget)) - { - if (!string.IsNullOrWhiteSpace(item.Region)) - { - // setting region lookup key if region is being used - _connection.Database.HashSet(item.Region, fullKey, "regionKey", When.Always, CommandFlags.FireAndForget); - } - - // put runs via fire and forget, so we don't get a result back - return true; - } - - // should never happen, something went wrong with the script - throw new InvalidOperationException("Something went wrong adding an item, result must not be null."); + // fire and forget will not return a result. + return true; } - else + + if (result.IsNull && when == When.NotExists) { - if (result.IsNull && when == When.NotExists) + // add failed because element exists already + if (Logger.IsEnabled(LogLevel.Debug)) { - // add failed because element exists already - if (Logger.IsEnabled(LogLevel.Debug)) - { - Logger.LogDebug("DB {0} | Failed to add item [{1}] because it exists.", _connection.Database.Database, item.ToString()); - } - - return false; + Logger.LogDebug("DB {0} | Failed to add item [{1}] because it exists.", _connection.Database.Database, item.ToString()); } - var resultValue = (RedisValue)result; - - if (resultValue.HasValue && resultValue.ToString().Equals("OK", StringComparison.OrdinalIgnoreCase)) - { - // Added successfully: - if (!string.IsNullOrWhiteSpace(item.Region)) - { - // setting region lookup key if region is being used - // we cannot do that within the lua because the region could be on another cluster node! - _connection.Database.HashSet(item.Region, fullKey, "regionKey", When.Always, CommandFlags.FireAndForget); - } + return false; + } - return true; - } + var resultValue = (RedisValue)result; - Logger.LogWarn("DB {0} | Failed to set item [{1}]: {2}.", _connection.Database.Database, item.ToString(), resultValue.ToString()); - return false; + if (resultValue.HasValue && resultValue == 1) + { + return true; } + + Logger.LogWarning("DB {0} | Failed to set item [{1}]: {2}.", _connection.Database.Database, item.ToString(), resultValue.ToString()); + return false; } private bool SetNoScript(CacheItem item, When when, bool sync = false) @@ -936,7 +930,7 @@ private bool SetNoScript(CacheItem item, When when, bool sync = fal var setResult = _connection.Database.HashSet(fullKey, HashFieldValue, value, when, flags); - // setResult from fire and forget is alwys false, so we have to assume it works... + // setResult from fire and forget is always false, so we have to assume it works... setResult = flags == CommandFlags.FireAndForget ? true : setResult; if (setResult) @@ -1006,7 +1000,7 @@ private RedisResult Eval(ScriptType scriptType, RedisKey redisKey, RedisValue[] } catch (RedisServerException ex) when (ex.Message.StartsWith("NOSCRIPT", StringComparison.OrdinalIgnoreCase)) { - Logger.LogInfo("Received NOSCRIPT from server. Reloading scripts..."); + Logger.LogInformation("Received NOSCRIPT from server. Reloading scripts..."); LoadScripts(); // retry @@ -1018,7 +1012,7 @@ private void LoadScripts() { lock (_lockObject) { - Logger.LogInfo("Loading scripts."); + Logger.LogInformation("Loading scripts."); var putLua = LuaScript.Prepare(_scriptPut); var addLua = LuaScript.Prepare(_scriptAdd); @@ -1054,4 +1048,4 @@ private void LoadScripts() } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RedisConfiguration.cs b/src/CacheManager.StackExchange.Redis/RedisConfiguration.cs index 97d82bd3..2e282356 100644 --- a/src/CacheManager.StackExchange.Redis/RedisConfiguration.cs +++ b/src/CacheManager.StackExchange.Redis/RedisConfiguration.cs @@ -46,7 +46,7 @@ public RedisConfiguration() /// Enables keyspace notifications to react on eviction/expiration of items. /// Enables Twemproxy mode. /// - /// Gets or sets a version number to eventually reduce the avaible features accessible by cachemanager. + /// Gets or sets a version number to eventually reduce the available features accessible by cachemanager. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed", Justification = "Using it for configuration data only.")] public RedisConfiguration( @@ -101,7 +101,7 @@ public RedisConfiguration( /// The redis database to use. /// Enables keyspace notifications to react on eviction/expiration of items. /// - /// Gets or sets a version number to eventually reduce the avaible features accessible by cachemanager. + /// Gets or sets a version number to eventually reduce the available features accessible by cachemanager. /// public RedisConfiguration( string key, @@ -146,7 +146,7 @@ private ConfigurationOptions CreateConfigurationOptions() public ConfigurationOptions ConfigurationOptions => _configurationOptions; /// - /// Gets or sets a version number to eventually reduce the avaible features accessible by cachemanager. + /// Gets or sets a version number to eventually reduce the available features accessible by cachemanager. /// E.g. set this to "2.4" to disable LUA support. /// /// @@ -193,6 +193,10 @@ public string ConnectionString Database = _configurationOptions.DefaultDatabase ?? Database; _connectionString = _configurationOptions.ToString(); + if (string.IsNullOrWhiteSpace(_connectionString)) + { + throw new ArgumentException("Provided redis connection string seems to be invalid."); + } } } @@ -309,4 +313,4 @@ public ServerEndPoint(string host, int port) /// The host. public string Host { get; set; } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RedisConfigurationBuilderExtensions.cs b/src/CacheManager.StackExchange.Redis/RedisConfigurationBuilderExtensions.cs index f2b75ab7..0b7b08f7 100644 --- a/src/CacheManager.StackExchange.Redis/RedisConfigurationBuilderExtensions.cs +++ b/src/CacheManager.StackExchange.Redis/RedisConfigurationBuilderExtensions.cs @@ -15,7 +15,7 @@ public static class RedisConfigurationBuilderExtensions /// /// The builder instance. /// - /// The configuration key which can be used to refernce this configuration by a redis cache handle or backplane. + /// The configuration key which can be used to reference this configuration by a redis cache handle or backplane. /// /// The redis configuration object. /// The configuration builder. @@ -35,7 +35,7 @@ public static ConfigurationBuilderCachePart WithRedisConfiguration(this Configur /// /// The builder instance. /// - /// The configuration key which can be used to refernce this configuration by a redis cache handle or backplane. + /// The configuration key which can be used to reference this configuration by a redis cache handle or backplane. /// /// The redis connection string. /// The redis database to be used. @@ -63,7 +63,7 @@ public static ConfigurationBuilderCachePart WithRedisConfiguration(this Configur /// /// The builder instance. /// - /// The configuration key which can be used to refernce this configuration by a redis cache handle or backplane. + /// The configuration key which can be used to reference this configuration by a redis cache handle or backplane. /// /// The connection multiplexer instance. /// The redis database to use for caching. diff --git a/src/CacheManager.StackExchange.Redis/RedisConfigurationSection.cs b/src/CacheManager.StackExchange.Redis/RedisConfigurationSection.cs index ba335243..3a93205d 100644 --- a/src/CacheManager.StackExchange.Redis/RedisConfigurationSection.cs +++ b/src/CacheManager.StackExchange.Redis/RedisConfigurationSection.cs @@ -1,5 +1,4 @@ -#if !NETSTANDARD -using System.Collections.Generic; +using System.Collections.Generic; using System.Configuration; namespace CacheManager.Redis @@ -16,7 +15,7 @@ namespace CacheManager.Redis /// database="0" /// database="113" /// strictCompatibilityModeVersion="the redis version, e.g. 2.6, or leave null" - /// + /// /// { connectionString="redis0:6379,redis1:6380,keepAlive=180,allowAdmin=true" } /// OR /// { @@ -93,7 +92,7 @@ public EndpointCollection() /// Returns an enumerator that iterates through the collection. /// /// - /// A that can be used to iterate + /// A that can be used to iterate /// through the collection. /// public new IEnumerator GetEnumerator() @@ -107,19 +106,19 @@ public EndpointCollection() } /// - /// When overridden in a derived class, creates a new . + /// When overridden in a derived class, creates a new . /// - /// A new . + /// A new . protected override ConfigurationElement CreateNewElement() => new Endpoint(); /// /// Gets the element key for a specified configuration element when overridden in a derived class. /// /// - /// The to return the key for. + /// The to return the key for. /// /// - /// An that acts as the key for the specified . + /// An that acts as the key for the specified . /// protected override object GetElementKey(ConfigurationElement element) { @@ -173,7 +172,7 @@ public RedisOptionCollection() /// Returns an enumerator that iterates through the collection. /// /// - /// A that can be used to iterate + /// A that can be used to iterate /// through the collection. /// public new IEnumerator GetEnumerator() @@ -187,19 +186,19 @@ public RedisOptionCollection() } /// - /// When overridden in a derived class, creates a new . + /// When overridden in a derived class, creates a new . /// - /// A new . + /// A new . protected override ConfigurationElement CreateNewElement() => new RedisOptions(); /// /// Gets the element key for a specified configuration element when overridden in a derived class. /// /// - /// The to return the key for. + /// The to return the key for. /// /// - /// An that acts as the key for the specified . + /// An that acts as the key for the specified . /// protected override object GetElementKey(ConfigurationElement element) => ((RedisOptions)element).Id; } @@ -406,4 +405,3 @@ public string StrictCompatibilityModeVersion } } } -#endif \ No newline at end of file diff --git a/src/CacheManager.StackExchange.Redis/RedisConfigurations.cs b/src/CacheManager.StackExchange.Redis/RedisConfigurations.cs index a1a9b197..d4c31c03 100644 --- a/src/CacheManager.StackExchange.Redis/RedisConfigurations.cs +++ b/src/CacheManager.StackExchange.Redis/RedisConfigurations.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -#if !NETSTANDARD +#if !NETSTANDARD1 using System.Configuration; #endif using System.IO; @@ -32,7 +32,7 @@ private static Dictionary Configurations { _config = new Dictionary(); -#if !NETSTANDARD +#if !NETSTANDARD1 var section = ConfigurationManager.GetSection(RedisConfigurationSection.DefaultSectionName) as RedisConfigurationSection; if (section != null) { @@ -81,7 +81,7 @@ public static RedisConfiguration GetConfiguration(string configurationName) if (!Configurations.ContainsKey(configurationName)) { -#if NETSTANDARD +#if NETSTANDARD1 throw new InvalidOperationException("No configuration added for configuration name " + configurationName); #else // check connection strings if there is one matching the name @@ -100,7 +100,7 @@ public static RedisConfiguration GetConfiguration(string configurationName) return Configurations[configurationName]; } -#if !NETSTANDARD +#if !NETSTANDARD1 /// /// Loads the configuration. @@ -204,4 +204,4 @@ public static void LoadConfiguration() #endif } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RedisConnectionManager.cs b/src/CacheManager.StackExchange.Redis/RedisConnectionManager.cs index b79b934b..8665ecbc 100644 --- a/src/CacheManager.StackExchange.Redis/RedisConnectionManager.cs +++ b/src/CacheManager.StackExchange.Redis/RedisConnectionManager.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using StackExchange.Redis; using static CacheManager.Core.Utility.Guard; @@ -18,16 +18,19 @@ internal class RedisConnectionManager private readonly ILogger _logger; private readonly string _connectionString; private readonly RedisConfiguration _configuration; + private readonly ILoggerFactory _loggerFactory; public RedisConnectionManager(RedisConfiguration configuration, ILoggerFactory loggerFactory) { NotNull(configuration, nameof(configuration)); NotNull(loggerFactory, nameof(loggerFactory)); + NotNullOrWhiteSpace(configuration.ConnectionString, nameof(RedisConfiguration.ConnectionString)); _configuration = configuration; + _loggerFactory = loggerFactory; _connectionString = configuration.ConnectionString; - _logger = loggerFactory.CreateLogger(this); + _logger = loggerFactory.CreateLogger(this.GetType()); } public IEnumerable Servers @@ -149,10 +152,10 @@ public IConnectionMultiplexer Connect() { if (_logger.IsEnabled(LogLevel.Information)) { - _logger.LogInfo("Trying to connect with the following configuration: '{0}'", RemoveCredentials(_connectionString)); + _logger.LogInformation("Trying to connect with the following configuration: '{0}'", RemoveCredentials(_connectionString)); } - connection = ConnectionMultiplexer.Connect(_connectionString, new LogWriter(_logger)); + connection = ConnectionMultiplexer.Connect(_connectionString, o => o.LoggerFactory = _loggerFactory); if (!connection.IsConnected) { @@ -162,20 +165,20 @@ public IConnectionMultiplexer Connect() connection.ConnectionRestored += (sender, args) => { - _logger.LogInfo(args.Exception, "Connection restored, type: '{0}', failure: '{1}'", args.ConnectionType, args.FailureType); + _logger.LogInformation(args.Exception, "Connection restored, type: '{0}', failure: '{1}'", args.ConnectionType, args.FailureType); }; if (!_configuration.TwemproxyEnabled) { + // TODO: re-test what IsReplica can do for us, readonly? var endpoints = connection.GetEndPoints(); if (!endpoints.Select(p => connection.GetServer(p)) - .Any(p => !p.IsSlave || p.AllowSlaveWrites)) + .Any(p => !p.IsReplica)) { throw new InvalidOperationException("No writeable endpoint found."); } } - connection.PreserveAsyncOrder = false; _connections.Add(_connectionString, connection); } } @@ -202,30 +205,5 @@ private static string RemoveCredentials(string value) return Regex.Replace(value, @"password\s*=\s*[^,]*", "password=****", RegexOptions.IgnoreCase); } - - private class LogWriter : StringWriter - { - private readonly ILogger _logger; - - public LogWriter(ILogger logger) - { - _logger = logger; - } - - public override void Write(char value) - { - } - - public override void Write(string value) - { - _logger.LogDebug(value); - } - - public override void Write(char[] buffer, int index, int count) - { - var logValue = new string(buffer, index, count); - _logger.LogDebug(RemoveCredentials(logValue)); - } - } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RedisValueConverter.cs b/src/CacheManager.StackExchange.Redis/RedisValueConverter.cs index dd383b18..4f67d6de 100644 --- a/src/CacheManager.StackExchange.Redis/RedisValueConverter.cs +++ b/src/CacheManager.StackExchange.Redis/RedisValueConverter.cs @@ -63,9 +63,9 @@ public RedisValueConverter(ICacheSerializer serializer) byte[] IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => value; - RedisValue IRedisValueConverter.ToRedisValue(byte value) => value; + RedisValue IRedisValueConverter.ToRedisValue(byte value) => (int)value; - byte IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (byte)value; + byte IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (byte)(int)value; RedisValue IRedisValueConverter.ToRedisValue(string value) => value; @@ -83,9 +83,9 @@ public RedisValueConverter(ICacheSerializer serializer) short IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (short)value; - RedisValue IRedisValueConverter.ToRedisValue(ushort value) => value; + RedisValue IRedisValueConverter.ToRedisValue(ushort value) => (int)value; - ushort IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (ushort)value; + ushort IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (ushort)(int)value; RedisValue IRedisValueConverter.ToRedisValue(float value) => (double)value; @@ -103,15 +103,15 @@ public RedisValueConverter(ICacheSerializer serializer) long IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (long)value; - // ulong can exceed the supported lenght of storing integers (which is signed 64bit integer) + // ulong can exceed the supported length of storing integers (which is signed 64bit integer) // also, even if we do not exceed long.MaxValue, the SA client stores it as double for no aparent reason => cast to long fixes it. RedisValue IRedisValueConverter.ToRedisValue(ulong value) => value > long.MaxValue ? (RedisValue)value.ToString() : checked((long)value); ulong IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => ulong.Parse(value); - RedisValue IRedisValueConverter.ToRedisValue(char value) => value; + RedisValue IRedisValueConverter.ToRedisValue(char value) => (uint)value; - char IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (char)value; + char IRedisValueConverter.FromRedisValue(RedisValue value, string valueType) => (char)(uint)value; [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Scope = "member", Target = "CacheManager.Redis.RedisValueConverter.#CacheManager.Redis.IRedisValueConverter`1.ToRedisValue(System.Object)", Justification = "For performance reasons we don't do checks at this point. Also, its internally used only.")] RedisValue IRedisValueConverter.ToRedisValue(object value) @@ -271,4 +271,4 @@ private object Deserialize(RedisValue value, string valueType) return _serializer.Deserialize(value, type); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.StackExchange.Redis/RetryHelper.cs b/src/CacheManager.StackExchange.Redis/RetryHelper.cs index 92d9cb48..09406683 100644 --- a/src/CacheManager.StackExchange.Redis/RetryHelper.cs +++ b/src/CacheManager.StackExchange.Redis/RetryHelper.cs @@ -1,6 +1,5 @@ using System; -using System.Threading.Tasks; -using CacheManager.Core.Logging; +using Microsoft.Extensions.Logging; using StackExchange.Redis; namespace CacheManager.Redis @@ -36,12 +35,7 @@ public static T Retry(Func retryme, int timeOut, int retries, ILogger logg throw; } - logger.LogWarn(ex, WarningMessage, tries, retries); -#if NET40 - TaskEx.Delay(timeOut).Wait(); -#else - Task.Delay(timeOut).Wait(); -#endif + logger.LogWarning(ex, WarningMessage, tries, retries); } catch (RedisConnectionException ex) { @@ -51,12 +45,7 @@ public static T Retry(Func retryme, int timeOut, int retries, ILogger logg throw; } - logger.LogWarn(ex, WarningMessage, tries, retries); -#if NET40 - TaskEx.Delay(timeOut).Wait(); -#else - Task.Delay(timeOut).Wait(); -#endif + logger.LogWarning(ex, WarningMessage, tries, retries); } catch (TimeoutException ex) { @@ -66,12 +55,7 @@ public static T Retry(Func retryme, int timeOut, int retries, ILogger logg throw; } - logger.LogWarn(ex, WarningMessage, tries, retries); -#if NET40 - TaskEx.Delay(timeOut).Wait(); -#else - Task.Delay(timeOut).Wait(); -#endif + logger.LogWarning(ex, WarningMessage, tries, retries); } catch (AggregateException aggregateException) { @@ -90,17 +74,12 @@ public static T Retry(Func retryme, int timeOut, int retries, ILogger logg if (e is RedisConnectionException || e is System.TimeoutException || e is RedisServerException) { - logger.LogWarn(e, WarningMessage, tries, retries); -#if NET40 - TaskEx.Delay(timeOut).Wait(); -#else - Task.Delay(timeOut).Wait(); -#endif + logger.LogWarning(e, WarningMessage, tries, retries); return true; } - logger.LogCritical("Unhandled exception occurred.", aggregateException); + logger.LogCritical(aggregateException, "Unhandled exception occurred."); return false; }); } @@ -123,4 +102,4 @@ public static void Retry(Action retryme, int timeOut, int retries, ILogger logge logger); } } -} \ No newline at end of file +} diff --git a/src/CacheManager.SystemRuntimeCaching/CacheManager.SystemRuntimeCaching.csproj b/src/CacheManager.SystemRuntimeCaching/CacheManager.SystemRuntimeCaching.csproj index 48be5979..9f574d64 100644 --- a/src/CacheManager.SystemRuntimeCaching/CacheManager.SystemRuntimeCaching.csproj +++ b/src/CacheManager.SystemRuntimeCaching/CacheManager.SystemRuntimeCaching.csproj @@ -2,18 +2,22 @@ CacheManager extension package which adds System.Runtime.Caching.MemoryCache as an option for a local in-memory cache layer. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. - net40;net45 + net472;netstandard2.0;net8.0 true true Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached + true - + - - + + + + + - + \ No newline at end of file diff --git a/src/CacheManager.SystemRuntimeCaching/MemoryCacheHandle`1.cs b/src/CacheManager.SystemRuntimeCaching/MemoryCacheHandle`1.cs index 9babda4d..d30b9be7 100644 --- a/src/CacheManager.SystemRuntimeCaching/MemoryCacheHandle`1.cs +++ b/src/CacheManager.SystemRuntimeCaching/MemoryCacheHandle`1.cs @@ -4,8 +4,7 @@ using System.Runtime.Caching; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; -using static CacheManager.Core.Utility.Guard; +using Microsoft.Extensions.Logging; namespace CacheManager.SystemRuntimeCaching { @@ -35,21 +34,42 @@ public class MemoryCacheHandle : BaseCacheHandle /// The cache handle configuration. /// The logger factory. public MemoryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) + : this(managerConfiguration, configuration, loggerFactory, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The manager configuration. + /// The cache handle configuration. + /// The logger factory. + /// The vendor specific options. + public MemoryCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory, RuntimeMemoryCacheOptions memoryCacheOptions) : base(managerConfiguration, configuration) { - NotNull(configuration, nameof(configuration)); - NotNull(loggerFactory, nameof(loggerFactory)); + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } - Logger = loggerFactory.CreateLogger(this); + if (loggerFactory is null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + Logger = loggerFactory.CreateLogger(this.GetType()); _cacheName = configuration.Name; - if (_cacheName.ToUpper(CultureInfo.InvariantCulture).Equals(DefaultName.ToUpper(CultureInfo.InvariantCulture))) + + //if (_cacheName.ToUpper(CultureInfo.InvariantCulture).Equals(DefaultName.ToUpper(CultureInfo.InvariantCulture))) + if (DefaultName.Equals(_cacheName, StringComparison.InvariantCultureIgnoreCase)) { _cache = MemoryCache.Default; } else { - _cache = new MemoryCache(_cacheName); + _cache = new MemoryCache(_cacheName, memoryCacheOptions?.AsNameValueCollection()); } _instanceKey = Guid.NewGuid().ToString(); @@ -97,7 +117,11 @@ public override bool Exists(string key) /// public override bool Exists(string key, string region) { - NotNullOrWhiteSpace(region, nameof(region)); + if (string.IsNullOrWhiteSpace(region)) + { + throw new ArgumentException($"'{nameof(region)}' cannot be null or whitespace.", nameof(region)); + } + var fullKey = GetItemKey(key, region); return _cache.Contains(fullKey); } @@ -301,7 +325,10 @@ private CacheItemPolicy GetPolicy(CacheItem item) private string GetItemKey(string key, string region = null) { - NotNullOrWhiteSpace(key, nameof(key)); + if (string.IsNullOrWhiteSpace(key)) + { + throw new ArgumentException($"'{nameof(key)}' cannot be null or whitespace.", nameof(key)); + } if (string.IsNullOrWhiteSpace(region)) { @@ -397,4 +424,4 @@ private static void ParseKeyParts(int instanceKeyLength, string fullKey, out boo } } } -} \ No newline at end of file +} diff --git a/src/CacheManager.SystemRuntimeCaching/RuntimeCachingBuilderExtensions.cs b/src/CacheManager.SystemRuntimeCaching/RuntimeCachingBuilderExtensions.cs index ce767ad5..ee8ee370 100644 --- a/src/CacheManager.SystemRuntimeCaching/RuntimeCachingBuilderExtensions.cs +++ b/src/CacheManager.SystemRuntimeCaching/RuntimeCachingBuilderExtensions.cs @@ -39,5 +39,45 @@ public static ConfigurationBuilderCacheHandlePart WithSystemRuntimeCacheHandle(t /// Thrown if is null. public static ConfigurationBuilderCacheHandlePart WithSystemRuntimeCacheHandle(this ConfigurationBuilderCachePart part, string instanceName, bool isBackplaneSource = false) => part?.WithHandle(typeof(MemoryCacheHandle<>), instanceName, isBackplaneSource); + + /// + /// Adds a using a instance with the given . + /// The named cache instance can be configured via . + /// + /// The builder part. + /// The name to be used for the cache instance. + /// + /// The which should be used to initiate this cache. + /// If Null, default options will be used. + /// + /// + /// The builder part. + /// + /// If part is null. + /// Thrown if is null. + public static ConfigurationBuilderCacheHandlePart WithSystemRuntimeCacheHandle( + this ConfigurationBuilderCachePart part, string instanceName, RuntimeMemoryCacheOptions options) + => WithSystemRuntimeCacheHandle(part, instanceName, false, options); + + /// + /// Adds a using a instance with the given . + /// The named cache instance can be configured via . + /// + /// The builder part. + /// The name to be used for the cache instance. + /// Set this to true if this cache handle should be the source of the backplane. + /// This setting will be ignored if no backplane is configured. + /// + /// The which should be used to initiate this cache. + /// If Null, default options will be used. + /// + /// + /// The builder part. + /// + /// If part is null. + /// Thrown if is null. + public static ConfigurationBuilderCacheHandlePart WithSystemRuntimeCacheHandle( + this ConfigurationBuilderCachePart part, string instanceName, bool isBackplaneSource, RuntimeMemoryCacheOptions options) + => part?.WithHandle(typeof(MemoryCacheHandle<>), instanceName, isBackplaneSource, options); } -} \ No newline at end of file +} diff --git a/src/CacheManager.SystemRuntimeCaching/RuntimeMemoryCacheOptions.cs b/src/CacheManager.SystemRuntimeCaching/RuntimeMemoryCacheOptions.cs new file mode 100644 index 00000000..9168d4ae --- /dev/null +++ b/src/CacheManager.SystemRuntimeCaching/RuntimeMemoryCacheOptions.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.Linq; +using System.Text; + +namespace CacheManager.SystemRuntimeCaching +{ + /// + /// configuration options + /// + public class RuntimeMemoryCacheOptions + { + /// + /// An integer value that specifies the maximum allowable size, in megabytes, that an instance of a MemoryCache can grow to. The default value is 0, which means that the autosizing heuristics of the MemoryCache class are used by default. + /// + public int CacheMemoryLimitMegabytes { get; set; } = 0; + + /// + /// An integer value between 0 and 100 that specifies the maximum percentage of physically installed computer memory that can be consumed by the cache. The default value is 0, which means that the autosizing heuristics of the MemoryCache class are used by default. + /// + public int PhysicalMemoryLimitPercentage { get; set; } = 0; + + /// + /// A value that indicates the time interval after which the cache implementation compares the current memory load against the absolute and percentage-based memory limits that are set for the cache instance. + /// + public TimeSpan PollingInterval { get; set; } = TimeSpan.FromMinutes(2); + + /// + /// Gets the configuration as a + /// + /// A with the current configuration. + public NameValueCollection AsNameValueCollection() + { + return new NameValueCollection(3) + { + { nameof(CacheMemoryLimitMegabytes), CacheMemoryLimitMegabytes.ToString(CultureInfo.InvariantCulture) }, + { nameof(PhysicalMemoryLimitPercentage), PhysicalMemoryLimitPercentage.ToString(CultureInfo.InvariantCulture) }, + { nameof(PollingInterval), PollingInterval.ToString("c") } + }; + } + } +} diff --git a/src/CacheManager.Web/CacheManager.Web.csproj b/src/CacheManager.Web/CacheManager.Web.csproj deleted file mode 100644 index 5c40f29c..00000000 --- a/src/CacheManager.Web/CacheManager.Web.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - CacheManager extension package which uses System.Web.Caching and also comes with a custom OutputCache provider. CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. - net40;net45 - true - true - Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/CacheManager.Web/CacheManagerOutputCacheProvider.cs b/src/CacheManager.Web/CacheManagerOutputCacheProvider.cs deleted file mode 100644 index f6014622..00000000 --- a/src/CacheManager.Web/CacheManagerOutputCacheProvider.cs +++ /dev/null @@ -1,159 +0,0 @@ -using System; -using System.Collections.Specialized; -using System.Reflection; -using System.Web.Caching; -using CacheManager.Core; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Web -{ - /// - /// Implements a simple System.Web.Caching.OutputCacheProvider which uses a cache manager - /// configured via web.config. - /// - public class CacheManagerOutputCacheProvider : OutputCacheProvider - { - private static readonly object _configLock = new object(); - private static ICacheManager _cacheInstance; - private static bool _isInitialized = false; - - /// - /// Gets the cache. - /// - /// The cache. - /// - /// Output cache provider has not yet been initialized. - /// - public static ICacheManager Cache - { - get - { - Ensure(_isInitialized, "Output cache provider has not yet been initialized."); - - return _cacheInstance; - } - } - - /// - /// Inserts the specified entry into the output cache. - /// - /// A unique identifier for . - /// The content to add to the output cache. - /// The time and date on which the cached entry expires. - /// A reference to the specified provider. - public override object Add(string key, object entry, DateTime utcExpiry) - { - if (!_cacheInstance.Add(GetCacheItem(key, entry, utcExpiry))) - { - return Cache.Get(key); - } - - return null; - } - - /// - /// Returns a reference to the specified entry in the output cache. - /// - /// A unique identifier for a cached entry in the output cache. - /// - /// The value that identifies the specified entry in the cache, or - /// null if the specified entry is not in the cache. - /// - public override object Get(string key) => Cache.Get(key); - - /// - /// Initializes the provider. - /// - /// The friendly name of the provider. - /// - /// A collection of the name/value pairs representing the provider-specific attributes - /// specified in the configuration for this provider. - /// - /// Might be re thrown. - public override void Initialize(string name, NameValueCollection config) - { - NotNull(config, nameof(config)); - - try - { - if (!_isInitialized) - { - lock (_configLock) - { - if (!_isInitialized) - { - var cacheName = config["cacheName"]; - if (string.IsNullOrWhiteSpace(cacheName)) - { - cacheName = "default"; - } - - InitializeStaticCache(cacheName); - _isInitialized = true; - } - } - } - - base.Initialize(name, config); - } - catch (TargetInvocationException ex) - { - if (ex.InnerException != null) - { - throw new InvalidOperationException(ex.InnerException.Message, ex.InnerException); - } - - throw; - } - } - - /// - /// Removes the specified entry from the output cache. - /// - /// The unique identifier for the entry to remove from the output cache. - public override void Remove(string key) - { - Cache.Remove(key); - } - - /// - /// Inserts the specified entry into the output cache, overwriting the entry if it is - /// already cached. - /// - /// A unique identifier for . - /// The content to add to the output cache. - /// - /// The time and date on which the cached expires. - /// - public override void Set(string key, object entry, DateTime utcExpiry) - { - Cache.Put(GetCacheItem(key, entry, utcExpiry)); - } - - private static CacheItem GetCacheItem(string key, object entry, DateTime utcExpiry) - { - CacheItem newItem; - if (utcExpiry != default(DateTime) && utcExpiry != DateTime.MaxValue) - { - var timeout = TimeSpan.FromTicks(utcExpiry.Ticks - DateTime.UtcNow.Ticks); - if (timeout.TotalMilliseconds < 0) - { - timeout = TimeSpan.FromSeconds(1); - } - - newItem = new CacheItem(key, entry, ExpirationMode.Absolute, timeout); - } - else - { - newItem = new CacheItem(key, entry); - } - - return newItem; - } - - private static void InitializeStaticCache(string cacheName) - { - _cacheInstance = CacheFactory.FromConfiguration(cacheName); - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Web/ContextFactory.cs b/src/CacheManager.Web/ContextFactory.cs deleted file mode 100644 index 4a5479e0..00000000 --- a/src/CacheManager.Web/ContextFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Web; - -namespace CacheManager.Web -{ - internal static class ContextFactory - { - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "HttpContext", Justification = "External naming")] - public static HttpContextBase CreateContext() - { - if (HttpContext.Current == null) - { - throw new InvalidOperationException("HttpContext.Current is required for System.Web caching and must not be null."); - } - - return new HttpContextWrapper(HttpContext.Current); - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Web/Properties/AssemblyInfo.cs b/src/CacheManager.Web/Properties/AssemblyInfo.cs deleted file mode 100644 index a46fb3be..00000000 --- a/src/CacheManager.Web/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System; - -[assembly: CLSCompliant(true)] \ No newline at end of file diff --git a/src/CacheManager.Web/SystemWebCacheHandle`1.cs b/src/CacheManager.Web/SystemWebCacheHandle`1.cs deleted file mode 100644 index 2ae002fb..00000000 --- a/src/CacheManager.Web/SystemWebCacheHandle`1.cs +++ /dev/null @@ -1,399 +0,0 @@ -using System; -using System.Web; -using System.Web.Caching; -using CacheManager.Core; -using CacheManager.Core.Internal; -using CacheManager.Core.Logging; -using static CacheManager.Core.Utility.Guard; - -namespace CacheManager.Web -{ - /// - /// Implementation based on . - /// - /// The type of the cache value. - /// - /// Although the MemoryCache doesn't support regions nor a RemoveAll/Clear method, we will - /// implement it via cache dependencies. - /// - public class SystemWebCacheHandle : BaseCacheHandle - { - private string _instanceKey = null; - private int _instanceKeyLength; - - /// - /// Initializes a new instance of the class. - /// - /// The manager configuration. - /// The cache handle configuration. - /// The logger factory. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "For unit testing only, will never cause issues.")] - public SystemWebCacheHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) - : base(managerConfiguration, configuration) - { - NotNull(loggerFactory, nameof(loggerFactory)); - Logger = loggerFactory.CreateLogger(this); - - _instanceKey = Guid.NewGuid().ToString(); - _instanceKeyLength = _instanceKey.Length; - - CreateInstanceToken(); - } - - /// - /// Gets the number of items the cache handle currently maintains. - /// - /// The count. - public override int Count => (int)Context.Cache.Count; - - /// - /// Gets the http context being used to get the Cache instance. - /// This implementation requires to be not null. - /// - /// The http context instance. - protected virtual HttpContextBase Context => ContextFactory.CreateContext(); - - /// - protected override ILogger Logger { get; } - - /// - /// Clears this cache, removing all items in the base cache and all regions. - /// - public override void Clear() - { - Context.Cache.Remove(_instanceKey); - CreateInstanceToken(); - } - - /// - /// Clears the cache region, removing all items from the specified only. - /// - /// The cache region. - public override void ClearRegion(string region) => - Context.Cache.Remove(GetRegionTokenKey(region)); - - /// - public override bool Exists(string key) - { - return GetCacheItemInternal(key) != null; - } - - /// - public override bool Exists(string key, string region) - { - NotNullOrWhiteSpace(region, nameof(region)); - - return GetCacheItemInternal(key, region) != null; - } - - /// - /// Adds a value to the cache. - /// - /// - /// Be aware that sliding expiration for this cache works only if the timeout is set to more than 2000ms. - /// - /// The CacheItem to be added to the cache. - /// - /// true if the key was not already added to the cache, false otherwise. - /// - protected override bool AddInternalPrepared(CacheItem item) - { - var key = GetItemKey(item); - var settings = GetCacheSettings(item); - - if (settings.SlidingExpire.TotalMilliseconds > 0 && settings.SlidingExpire.TotalMilliseconds < 2000) - { - Logger.LogWarn( - "System.Web.Caching.Cache sliding expiration works only with a value larger than 2000ms, " - + $"but you configured '{settings.SlidingExpire.TotalMilliseconds}' for key {item.Key}:{item.Region}."); - } - - var result = Context.Cache.Add( - key: key, - value: item, - dependencies: settings.Dependency, - absoluteExpiration: settings.AbsoluteExpire, - slidingExpiration: settings.SlidingExpire, - priority: CacheItemPriority.Normal, - onRemoveCallback: ItemRemoved); - - // result will be the existing value if the key is already stored, the new value will not override the key - return result == null; - } - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key) => GetCacheItemInternal(key, null); - - /// - /// Gets a CacheItem for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// The CacheItem. - protected override CacheItem GetCacheItemInternal(string key, string region) - { - var fullKey = GetItemKey(key, region); - var item = Context.Cache.Get(fullKey) as CacheItem; - - if (item == null) - { - return null; - } - - // cache.Get eventually triggers eviction callback, but just in case... - if (item.IsExpired) - { - RemoveInternal(item.Key, item.Region); - TriggerCacheSpecificRemove(item.Key, item.Region, Core.Internal.CacheItemRemovedReason.Expired, item.Value); - return null; - } - - return item; - } - - /// - /// Puts the into the cache. If the item exists it will get updated - /// with the new value. If the item doesn't exist, the item will be added to the cache. - /// - /// - /// Be aware that sliding expiration for this cache works only if the timeout is set to more than 2000ms. - /// - /// The CacheItem to be added to the cache. - protected override void PutInternalPrepared(CacheItem item) - { - var key = GetItemKey(item); - var settings = GetCacheSettings(item); - - if (settings.SlidingExpire.TotalMilliseconds > 0 && settings.SlidingExpire.TotalMilliseconds < 2000) - { - Logger.LogWarn( - "System.Web.Caching.Cache sliding expiration works only with a value larger than 2000ms, " - + $"but you configured '{settings.SlidingExpire.TotalMilliseconds}' for key {item.Key}:{item.Region}."); - } - - Context.Cache.Insert( - key: key, - value: item, - dependencies: settings.Dependency, - absoluteExpiration: settings.AbsoluteExpire, - slidingExpiration: settings.SlidingExpire, - priority: CacheItemPriority.Normal, - onRemoveCallback: ItemRemoved); - } - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key) => RemoveInternal(key, null); - - /// - /// Removes a value from the cache for the specified key. - /// - /// The key being used to identify the item within the cache. - /// The cache region. - /// - /// true if the key was found and removed from the cache, false otherwise. - /// - protected override bool RemoveInternal(string key, string region) - { - var fullKey = GetItemKey(key, region); - var obj = Context.Cache.Remove(fullKey); - - return obj != null; - } - - private static bool IsExpired(CacheItem item) - { - var now = DateTime.UtcNow; - if (item.ExpirationMode == ExpirationMode.Absolute - && item.CreatedUtc.Add(item.ExpirationTimeout) < now) - { - return true; - } - else if (item.ExpirationMode == ExpirationMode.Sliding - && item.LastAccessedUtc.Add(item.ExpirationTimeout) < now) - { - return true; - } - - return false; - } - - private void CreateInstanceToken() - { - // don't add a new key while we are disposing our instance - if (!Disposing) - { - CacheItemRemovedCallback callback = (key, item, reason) => - { - _instanceKey = Guid.NewGuid().ToString(); - _instanceKeyLength = _instanceKey.Length; - }; - - var instanceItem = new CacheItem(_instanceKey, _instanceKey); - Context.Cache.Add( - _instanceKey, - instanceItem, - null, - Cache.NoAbsoluteExpiration, - Cache.NoSlidingExpiration, - CacheItemPriority.NotRemovable, - callback); - } - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "We don't own the instance")] - private void CreateRegionToken(string region) - { - var key = GetRegionTokenKey(region); - - // add region token with dependency on our instance token, so that all regions get - // removed whenever the instance gets cleared. - var dependency = new CacheDependency(null, new[] { _instanceKey }); - Context.Cache.Add(key, region, dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); - } - - private string GetItemKey(CacheItem item) => GetItemKey(item?.Key, item?.Region); - - private string GetItemKey(string key, string region = null) - { - NotNullOrWhiteSpace(key, nameof(key)); - - if (string.IsNullOrWhiteSpace(region)) - { - return _instanceKey + ":" + key; - } - - return string.Concat(_instanceKey, "@", region.Length, "@", region, ":", key); - } - - private CacheDependency CreateDependency(CacheItem item) - { - string[] cacheKeys; - - if (string.IsNullOrWhiteSpace(item.Region)) - { - cacheKeys = new string[] { _instanceKey }; - } - else - { - var regionKey = GetRegionTokenKey(item.Region); - if (Context.Cache[regionKey] == null) - { - CreateRegionToken(item.Region); - } - - cacheKeys = new string[] { _instanceKey, regionKey }; - } - - return new CacheDependency(null, cacheKeys); - } - - private string GetRegionTokenKey(string region) - { - var key = string.Concat(_instanceKey, "_", region); - return key; - } - - private void ItemRemoved(string fullKey, object item, System.Web.Caching.CacheItemRemovedReason reason) - { - if (string.IsNullOrWhiteSpace(fullKey)) - { - return; - } - - // ignore manually removed items, stats will be updated already - if (reason == System.Web.Caching.CacheItemRemovedReason.Removed) - { - return; - } - - bool isToken; - bool hasRegion; - string key; - string region; - ParseKeyParts(_instanceKeyLength, fullKey, out isToken, out hasRegion, out region, out key); - - if (!isToken) - { - if (hasRegion) - { - Stats.OnRemove(region); - } - else - { - Stats.OnRemove(); - } - - var cacheItem = item as CacheItem; - object originalValue = null; - if (item != null) - { - originalValue = cacheItem.Value; - } - - // trigger cachemanager's remove on evicted and expired items - if (reason == System.Web.Caching.CacheItemRemovedReason.Underused) - { - TriggerCacheSpecificRemove(key, region, Core.Internal.CacheItemRemovedReason.Evicted, originalValue); - } - else if (reason == System.Web.Caching.CacheItemRemovedReason.Expired) - { - TriggerCacheSpecificRemove(key, region, Core.Internal.CacheItemRemovedReason.Expired, originalValue); - } - } - } - - private static void ParseKeyParts(int instanceKeyLength, string fullKey, out bool isToken, out bool hasRegion, out string region, out string key) - { - var relevantKey = fullKey.Substring(instanceKeyLength); - isToken = relevantKey[0] == '_'; - hasRegion = false; - region = null; - key = null; - - if (!isToken) - { - hasRegion = relevantKey[0] == '@'; - var regionLenEnd = hasRegion ? relevantKey.IndexOf('@', 1) : -1; - - int regionLen; - regionLen = hasRegion && regionLenEnd > 0 ? int.TryParse(relevantKey.Substring(1, regionLenEnd - 1), out regionLen) ? regionLen : 0 : 0; - hasRegion = hasRegion && regionLen > 0; - - var restKey = hasRegion ? relevantKey.Substring(regionLenEnd + 1) : relevantKey; - region = hasRegion ? restKey.Substring(0, regionLen) : null; - key = restKey.Substring(regionLen + 1); - } - } - - private CacheSettings GetCacheSettings(CacheItem item) - { - var settings = new CacheSettings() - { - Dependency = CreateDependency(item), - AbsoluteExpire = item.ExpirationMode == ExpirationMode.Absolute ? DateTime.UtcNow.Add(item.ExpirationTimeout) : Cache.NoAbsoluteExpiration, - SlidingExpire = item.ExpirationMode == ExpirationMode.Sliding ? item.ExpirationTimeout : Cache.NoSlidingExpiration, - }; - - return settings; - } - - private class CacheSettings - { - public CacheDependency Dependency { get; set; } - - public DateTime AbsoluteExpire { get; set; } = Cache.NoAbsoluteExpiration; - - public TimeSpan SlidingExpire { get; set; } = Cache.NoSlidingExpiration; - } - } -} \ No newline at end of file diff --git a/src/CacheManager.Web/WebConfigurationBuilderExtensions.cs b/src/CacheManager.Web/WebConfigurationBuilderExtensions.cs deleted file mode 100644 index a4b6044c..00000000 --- a/src/CacheManager.Web/WebConfigurationBuilderExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using CacheManager.Web; - -namespace CacheManager.Core -{ - /// - /// Extensions for the configuration builder specific to System.Runtime.Caching cache handle. - /// - public static class WebConfigurationBuilderExtensions - { - /// - /// Adds a to the cache manager. - /// This handle uses System.Web.Caching.Cache and requires HttpContext.Current to be not null. - /// - /// The builder part. - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The builder part. - /// - /// The builder part. - public static ConfigurationBuilderCacheHandlePart WithSystemWebCacheHandle(this ConfigurationBuilderCachePart part, bool isBackplaneSource = false) - => WithSystemWebCacheHandle(part, Guid.NewGuid().ToString("N"), isBackplaneSource); - - /// - /// Adds a to the cache manager. - /// This handle uses System.Web.Caching.Cache and requires HttpContext.Current to be not null. - /// - /// The builder part. - /// The name to be used for the cache handle instance. - /// Set this to true if this cache handle should be the source of the backplane. - /// This setting will be ignored if no backplane is configured. - /// - /// The builder part. - /// - /// If part is null. - /// Thrown if is null. - public static ConfigurationBuilderCacheHandlePart WithSystemWebCacheHandle(this ConfigurationBuilderCachePart part, string instanceName, bool isBackplaneSource = false) - => part?.WithHandle(typeof(SystemWebCacheHandle<>), instanceName, isBackplaneSource); - } -} \ No newline at end of file diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report-github.md deleted file mode 100644 index efe74bc4..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdErr | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |---------------- |-------------- |-------------- |------- |-------------- |------- |---------- | - Dictionary | 348.8331 ns | 2.2450 ns | 11.6655 ns | 1.00 | 0.00 | 0.0309 | 184 B | - Runtime | 2,087.0435 ns | 14.5742 ns | 79.8259 ns | 5.99 | 0.30 | 0.6480 | 3.16 kB | - MsMemory | 1,450.8287 ns | 8.8780 ns | 47.8093 ns | 4.16 | 0.19 | 0.1284 | 764 B | - Redis | 104,014.9027 ns | 443.6979 ns | 2,389.3865 ns | 298.50 | 11.90 | - | 1.51 kB | - Memcached | 147,246.4678 ns | 1,720.1031 ns | 9,421.3930 ns | 422.57 | 30.00 | - | 13.77 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.csv deleted file mode 100644 index 5425b767..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdErr;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;348.8331 ns;2.2450 ns;11.6655 ns;1.00;0.00;0.0309;184 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"2,087.0435 ns";14.5742 ns;79.8259 ns;5.99;0.30;0.6480;3.16 kB -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,450.8287 ns";8.8780 ns;47.8093 ns;4.16;0.19;0.1284;764 B -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"104,014.9027 ns";443.6979 ns;"2,389.3865 ns";298.50;11.90;-;1.51 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"147,246.4678 ns";"1,720.1031 ns";"9,421.3930 ns";422.57;30.00;-;13.77 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.html deleted file mode 100644 index 66742da6..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/AddSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -AddSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdErr StdDevScaledScaled-StdDevGen 0Allocated
Dictionary348.8331 ns2.2450 ns11.6655 ns1.00 0.000.0309184 B
Runtime2,087.0435 ns14.5742 ns79.8259 ns5.99 0.300.64803.16 kB
MsMemory1,450.8287 ns8.8780 ns47.8093 ns4.16 0.190.1284764 B
Redis104,014.9027 ns443.6979 ns2,389.3865 ns298.50 11.90-1.51 kB
Memcached147,246.4678 ns1,720.1031 ns9,421.3930 ns422.57 30.00-13.77 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report-github.md deleted file mode 100644 index 333f2cb4..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |---------------- |-------------- |------- |-------------- |------- |---------- | - Dictionary | 116.6133 ns | 1.1805 ns | 1.00 | 0.00 | - | 0 B | - Runtime | 383.3126 ns | 6.2799 ns | 3.29 | 0.06 | 0.0242 | 208 B | - MsMemory | 396.9492 ns | 9.4612 ns | 3.40 | 0.09 | 0.0181 | 176 B | - Redis | 62,905.6330 ns | 1,565.1500 ns | 539.49 | 14.22 | - | 2.19 kB | - Memcached | 114,185.2557 ns | 2,292.9042 ns | 979.28 | 21.60 | - | 14.29 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.csv deleted file mode 100644 index 805acaf1..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;116.6133 ns;1.1805 ns;1.00;0.00;-;0 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;383.3126 ns;6.2799 ns;3.29;0.06;0.0242;208 B -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;396.9492 ns;9.4612 ns;3.40;0.09;0.0181;176 B -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"62,905.6330 ns";"1,565.1500 ns";539.49;14.22;-;2.19 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"114,185.2557 ns";"2,292.9042 ns";979.28;21.60;-;14.29 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.html deleted file mode 100644 index bebc0510..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/GetSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -GetSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdDevScaledScaled-StdDevGen 0Allocated
Dictionary116.6133 ns1.1805 ns1.00 0.00-0 B
Runtime383.3126 ns6.2799 ns3.29 0.060.0242208 B
MsMemory396.9492 ns9.4612 ns3.40 0.090.0181176 B
Redis62,905.6330 ns1,565.1500 ns539.49 14.22-2.19 kB
Memcached114,185.2557 ns2,292.9042 ns979.28 21.60-14.29 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report-github.md deleted file mode 100644 index 13535085..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdErr | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |--------------- |-------------- |-------------- |------- |-------------- |------- |---------- | - Dictionary | 243.5642 ns | 0.7127 ns | 3.8380 ns | 1.00 | 0.00 | 0.0257 | 160 B | - Runtime | 2,462.5431 ns | 15.6490 ns | 85.7133 ns | 10.11 | 0.38 | 1.2548 | 5.68 kB | - MsMemory | 1,307.1531 ns | 2.8219 ns | 14.6628 ns | 5.37 | 0.10 | 0.1915 | 1.02 kB | - Redis | 2,138.2635 ns | 12.3456 ns | 64.1494 ns | 8.78 | 0.29 | 0.0768 | 1.1 kB | - Memcached | 96,120.9035 ns | 1,375.9735 ns | 7,409.8438 ns | 394.74 | 30.51 | 0.3255 | 13 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.csv deleted file mode 100644 index 561a44d3..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdErr;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;243.5642 ns;0.7127 ns;3.8380 ns;1.00;0.00;0.0257;160 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"2,462.5431 ns";15.6490 ns;85.7133 ns;10.11;0.38;1.2548;5.68 kB -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,307.1531 ns";2.8219 ns;14.6628 ns;5.37;0.10;0.1915;1.02 kB -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"2,138.2635 ns";12.3456 ns;64.1494 ns;8.78;0.29;0.0768;1.1 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"96,120.9035 ns";"1,375.9735 ns";"7,409.8438 ns";394.74;30.51;0.3255;13 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.html deleted file mode 100644 index 5b29f9a2..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/PutSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -PutSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdErr StdDevScaledScaled-StdDevGen 0Allocated
Dictionary243.5642 ns0.7127 ns3.8380 ns1.00 0.000.0257160 B
Runtime2,462.5431 ns15.6490 ns85.7133 ns10.11 0.381.25485.68 kB
MsMemory1,307.1531 ns2.8219 ns14.6628 ns5.37 0.100.19151.02 kB
Redis2,138.2635 ns12.3456 ns64.1494 ns8.78 0.290.07681.1 kB
Memcached96,120.9035 ns1,375.9735 ns7,409.8438 ns394.74 30.510.325513 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report-github.md deleted file mode 100644 index 379acca5..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdDev | Scaled | Scaled-StdDev | Gen 0 | Gen 1 | Allocated | ---------------------- |------------ |---------- |------- |-------------- |-------- |------- |---------- | - BinarySerializer | 105.5278 us | 1.5448 us | 1.92 | 0.04 | 8.4635 | - | 58.05 kB | - JsonSerializer | 55.0184 us | 0.9774 us | 1.00 | 0.00 | 7.0964 | - | 41.56 kB | - JsonGzSerializer | 228.2791 us | 3.1088 us | 4.15 | 0.09 | 68.2292 | 5.7292 | 329.66 kB | - ProtoBufSerializer | 37.6229 us | 1.0164 us | 0.68 | 0.02 | 3.8493 | - | 22.42 kB | - BondBinarySerializer | 7.3235 us | 0.2123 us | 0.13 | 0.00 | 0.8321 | - | 5.02 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.csv deleted file mode 100644 index be93849e..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdDev;Scaled;Scaled-StdDev;Gen 0;Gen 1;Allocated -BinarySerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;105.5278 us;1.5448 us;1.92;0.04;8.4635;-;58.05 kB -JsonSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;55.0184 us;0.9774 us;1.00;0.00;7.0964;-;41.56 kB -JsonGzSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;228.2791 us;3.1088 us;4.15;0.09;68.2292;5.7292;329.66 kB -ProtoBufSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;37.6229 us;1.0164 us;0.68;0.02;3.8493;-;22.42 kB -BondBinarySerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;7.3235 us;0.2123 us;0.13;0.00;0.8321;-;5.02 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.html deleted file mode 100644 index fb4b5cd8..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/SerializationBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -SerializationBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method MeanStdDevScaledScaled-StdDevGen 0Gen 1Allocated
BinarySerializer105.5278 us1.5448 us1.92 0.048.4635-58.05 kB
JsonSerializer55.0184 us0.9774 us1.00 0.007.0964-41.56 kB
JsonGzSerializer228.2791 us3.1088 us4.15 0.0968.22925.7292329.66 kB
ProtoBufSerializer37.6229 us1.0164 us0.68 0.023.8493-22.42 kB
BondBinarySerializer7.3235 us0.2123 us0.13 0.000.8321-5.02 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report-github.md deleted file mode 100644 index 95164858..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdErr | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |---------------- |-------------- |--------------- |------- |-------------- |------- |---------- | - Dictionary | 404.0928 ns | 1.7180 ns | 9.0906 ns | 1.00 | 0.00 | 0.0285 | 224 B | - Runtime | 2,844.5756 ns | 11.2859 ns | 58.6432 ns | 7.04 | 0.21 | 1.2360 | 5.99 kB | - MsMemory | 1,811.6219 ns | 4.2517 ns | 22.4980 ns | 4.49 | 0.11 | 0.2060 | 1.26 kB | - Redis | 126,840.3081 ns | 831.6598 ns | 4,240.6498 ns | 314.04 | 12.35 | - | 2.78 kB | - Memcached | 219,499.2918 ns | 3,823.4166 ns | 20,941.7152 ns | 543.45 | 52.33 | - | 27.46 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.csv deleted file mode 100644 index 17d041b3..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdErr;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;404.0928 ns;1.7180 ns;9.0906 ns;1.00;0.00;0.0285;224 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"2,844.5756 ns";11.2859 ns;58.6432 ns;7.04;0.21;1.2360;5.99 kB -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,811.6219 ns";4.2517 ns;22.4980 ns;4.49;0.11;0.2060;1.26 kB -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"126,840.3081 ns";831.6598 ns;"4,240.6498 ns";314.04;12.35;-;2.78 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"219,499.2918 ns";"3,823.4166 ns";"20,941.7152 ns";543.45;52.33;-;27.46 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.html deleted file mode 100644 index d3144cfd..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results-0.9.3/UpdateSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -UpdateSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdErr StdDevScaledScaled-StdDevGen 0Allocated
Dictionary404.0928 ns1.7180 ns9.0906 ns1.00 0.000.0285224 B
Runtime2,844.5756 ns11.2859 ns58.6432 ns7.04 0.211.23605.99 kB
MsMemory1,811.6219 ns4.2517 ns22.4980 ns4.49 0.110.20601.26 kB
Redis126,840.3081 ns831.6598 ns4,240.6498 ns314.04 12.35-2.78 kB
Memcached219,499.2918 ns3,823.4166 ns20,941.7152 ns543.45 52.33-27.46 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report-github.md deleted file mode 100644 index c66e6640..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdErr | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |---------------- |-------------- |-------------- |------- |-------------- |------- |---------- | - Dictionary | 321.1602 ns | 1.6496 ns | 9.0353 ns | 1.00 | 0.00 | 0.0309 | 184 B | - Runtime | 1,869.6133 ns | 5.2912 ns | 28.9811 ns | 5.83 | 0.18 | 0.6561 | 3.16 kB | - MsMemory | 1,038.4112 ns | 3.5986 ns | 19.3789 ns | 3.24 | 0.11 | 0.0559 | 448 B | - Redis | 92,822.7871 ns | 1,378.6964 ns | 7,551.4311 ns | 289.24 | 24.46 | - | 1.51 kB | - Memcached | 135,684.3124 ns | 1,764.1267 ns | 9,166.6710 ns | 422.80 | 30.33 | - | 13.77 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.csv deleted file mode 100644 index 5d5961db..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdErr;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;321.1602 ns;1.6496 ns;9.0353 ns;1.00;0.00;0.0309;184 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,869.6133 ns";5.2912 ns;28.9811 ns;5.83;0.18;0.6561;3.16 kB -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,038.4112 ns";3.5986 ns;19.3789 ns;3.24;0.11;0.0559;448 B -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"92,822.7871 ns";"1,378.6964 ns";"7,551.4311 ns";289.24;24.46;-;1.51 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"135,684.3124 ns";"1,764.1267 ns";"9,166.6710 ns";422.80;30.33;-;13.77 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.html deleted file mode 100644 index 131163bc..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/AddSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -AddSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdErr StdDevScaledScaled-StdDevGen 0Allocated
Dictionary321.1602 ns1.6496 ns9.0353 ns1.00 0.000.0309184 B
Runtime1,869.6133 ns5.2912 ns28.9811 ns5.83 0.180.65613.16 kB
MsMemory1,038.4112 ns3.5986 ns19.3789 ns3.24 0.110.0559448 B
Redis92,822.7871 ns1,378.6964 ns7,551.4311 ns289.24 24.46-1.51 kB
Memcached135,684.3124 ns1,764.1267 ns9,166.6710 ns422.80 30.33-13.77 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report-github.md deleted file mode 100644 index d7468b8d..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report-github.md +++ /dev/null @@ -1,24 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063) -Processor=Intel Core i7-6700 CPU 3.40GHz (Skylake), ProcessorCount=8 -Frequency=3328125 Hz, Resolution=300.4695 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 - Job-VUBPRE : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 - -Runtime=Clr LaunchCount=1 TargetCount=10 -WarmupCount=4 - -``` - | Method | Mean | Error | StdDev | Median | Op/s | Scaled | ScaledSD | Rank | Gen 0 | Allocated | - |------------------------ |----------:|----------:|---------:|----------:|-------------:|-------:|---------:|-----:|-------:|----------:| - | SerializeChange | 194.57 ns | 11.309 ns | 7.480 ns | 192.86 ns | 5,139,629.5 | 1.00 | 0.00 | 4 | 0.1523 | 640 B | - | DeserializeChange | 241.69 ns | 10.354 ns | 6.848 ns | 238.51 ns | 4,137,485.5 | 1.24 | 0.06 | 5 | 0.0875 | 368 B | - | SerializeChangeRegion | 249.23 ns | 7.700 ns | 4.582 ns | 249.67 ns | 4,012,334.1 | 1.28 | 0.05 | 6 | 0.1826 | 768 B | - | DeserializeChangeRegion | 305.05 ns | 8.953 ns | 5.922 ns | 306.25 ns | 3,278,156.0 | 1.57 | 0.06 | 7 | 0.0987 | 416 B | - | SerializeClear | 96.21 ns | 4.459 ns | 2.949 ns | 95.74 ns | 10,393,877.9 | 0.50 | 0.02 | 1 | 0.1162 | 488 B | - | DeserializeClear | 158.92 ns | 7.949 ns | 5.258 ns | 159.25 ns | 6,292,374.9 | 0.82 | 0.04 | 2 | 0.0741 | 312 B | - | SerializeClearRegion | 169.66 ns | 7.262 ns | 3.798 ns | 169.60 ns | 5,894,312.1 | 0.87 | 0.04 | 3 | 0.1581 | 664 B | - | DeserializeClearRegion | 240.22 ns | 8.661 ns | 5.154 ns | 240.20 ns | 4,162,849.7 | 1.24 | 0.05 | 5 | 0.0892 | 376 B | - | SerializeRemove | 255.63 ns | 15.071 ns | 9.968 ns | 258.50 ns | 3,911,924.7 | 1.32 | 0.07 | 6 | 0.1826 | 768 B | - | DeserializeRemove | 300.98 ns | 9.420 ns | 5.606 ns | 299.66 ns | 3,322,483.1 | 1.55 | 0.06 | 7 | 0.0987 | 416 B | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.csv deleted file mode 100644 index 67ac40c6..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.csv +++ /dev/null @@ -1,11 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxAbsoluteError;MaxRelativeError;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;RetainVm;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;Error;StdDev;Median;Op/s;Scaled;ScaledSD;Rank;Gen 0;Allocated -SerializeChange;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;194.57 ns;11.309 ns;7.480 ns;192.86 ns;"5,139,629.5";1.00;0.00;4;0.1523;640 B -DeserializeChange;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;241.69 ns;10.354 ns;6.848 ns;238.51 ns;"4,137,485.5";1.24;0.06;5;0.0875;368 B -SerializeChangeRegion;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;249.23 ns;7.700 ns;4.582 ns;249.67 ns;"4,012,334.1";1.28;0.05;6;0.1826;768 B -DeserializeChangeRegion;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;305.05 ns;8.953 ns;5.922 ns;306.25 ns;"3,278,156.0";1.57;0.06;7;0.0987;416 B -SerializeClear;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;96.21 ns;4.459 ns;2.949 ns;95.74 ns;"10,393,877.9";0.50;0.02;1;0.1162;488 B -DeserializeClear;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;158.92 ns;7.949 ns;5.258 ns;159.25 ns;"6,292,374.9";0.82;0.04;2;0.0741;312 B -SerializeClearRegion;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;169.66 ns;7.262 ns;3.798 ns;169.60 ns;"5,894,312.1";0.87;0.04;3;0.1581;664 B -DeserializeClearRegion;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;240.22 ns;8.661 ns;5.154 ns;240.20 ns;"4,162,849.7";1.24;0.05;5;0.0892;376 B -SerializeRemove;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;255.63 ns;15.071 ns;9.968 ns;258.50 ns;"3,911,924.7";1.32;0.07;6;0.1826;768 B -DeserializeRemove;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;300.98 ns;9.420 ns;5.606 ns;299.66 ns;"3,322,483.1";1.55;0.06;7;0.0987;416 B diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.html deleted file mode 100644 index b39c51c1..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmark-report.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - -BackplaneMessageBenchmark - - - - -

-BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
-Processor=Intel Core i7-6700 CPU 3.40GHz (Skylake), ProcessorCount=8
-Frequency=3328125 Hz, Resolution=300.4695 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
-  Job-VUBPRE : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
-
-
Runtime=Clr  LaunchCount=1  TargetCount=10  
-WarmupCount=4  
-
- - - - - - - - - - - - - - -
MethodMeanErrorStdDevMedian Op/sScaledScaledSDRankGen 0Allocated
SerializeChange194.57 ns11.309 ns7.480 ns192.86 ns5,139,629.51.000.0040.1523640 B
DeserializeChange241.69 ns10.354 ns6.848 ns238.51 ns4,137,485.51.240.0650.0875368 B
SerializeChangeRegion249.23 ns7.700 ns4.582 ns249.67 ns4,012,334.11.280.0560.1826768 B
DeserializeChangeRegion305.05 ns8.953 ns5.922 ns306.25 ns3,278,156.01.570.0670.0987416 B
SerializeClear96.21 ns4.459 ns2.949 ns95.74 ns10,393,877.90.500.0210.1162488 B
DeserializeClear158.92 ns7.949 ns5.258 ns159.25 ns6,292,374.90.820.0420.0741312 B
SerializeClearRegion169.66 ns7.262 ns3.798 ns169.60 ns5,894,312.10.870.0430.1581664 B
DeserializeClearRegion240.22 ns8.661 ns5.154 ns240.20 ns4,162,849.71.240.0550.0892376 B
SerializeRemove255.63 ns15.071 ns9.968 ns258.50 ns3,911,924.71.320.0760.1826768 B
DeserializeRemove300.98 ns9.420 ns5.606 ns299.66 ns3,322,483.11.550.0670.0987416 B
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report-github.md deleted file mode 100644 index 74c67239..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report-github.md +++ /dev/null @@ -1,16 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063) -Processor=Intel Core i7-6700 CPU 3.40GHz (Skylake), ProcessorCount=8 -Frequency=3328125 Hz, Resolution=300.4695 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 - Job-VUBPRE : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0 - -Runtime=Clr LaunchCount=1 TargetCount=10 -WarmupCount=4 - -``` - | Method | Mean | Error | StdDev | Median | Op/s | Rank | Gen 0 | Allocated | - |---------------- |---------:|----------:|----------:|---------:|----------:|-----:|-------:|----------:| - | SerializeMany | 5.650 us | 0.1873 us | 0.1239 us | 5.626 us | 177,004.2 | 1 | 2.3804 | 9.78 KB | - | DeserializeMany | 7.132 us | 0.3477 us | 0.2300 us | 7.115 us | 140,203.9 | 2 | 1.7548 | 7.22 KB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.csv deleted file mode 100644 index 4c935232..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.csv +++ /dev/null @@ -1,3 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxAbsoluteError;MaxRelativeError;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;RetainVm;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;Error;StdDev;Median;Op/s;Rank;Gen 0;Allocated -SerializeMany;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;5.650 us;0.1873 us;0.1239 us;5.626 us;"177,004.2";1;2.3804;9.78 KB -DeserializeMany;Default;False;Default;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;False;Default;Default;Default;1;Default;1;Default;10;16;4;7.132 us;0.3477 us;0.2300 us;7.115 us;"140,203.9";2;1.7548;7.22 KB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.html deleted file mode 100644 index 566df967..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/BackplaneMessageBenchmarkMultiple-report.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - -BackplaneMessageBenchmarkMultiple - - - - -

-BenchmarkDotNet=v0.10.8, OS=Windows 10 Redstone 2 (10.0.15063)
-Processor=Intel Core i7-6700 CPU 3.40GHz (Skylake), ProcessorCount=8
-Frequency=3328125 Hz, Resolution=300.4695 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
-  Job-VUBPRE : Clr 4.0.30319.42000, 64bit RyuJIT-v4.7.2098.0
-
-
Runtime=Clr  LaunchCount=1  TargetCount=10  
-WarmupCount=4  
-
- - - - - - -
MethodMeanErrorStdDevMedianOp/sRankGen 0Allocated
SerializeMany5.650 us0.1873 us0.1239 us5.626 us177,004.212.38049.78 KB
DeserializeMany7.132 us0.3477 us0.2300 us7.115 us140,203.921.75487.22 KB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report-github.md deleted file mode 100644 index 1688ba37..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report-github.md +++ /dev/null @@ -1,19 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - Method | Mean | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | ------------ |---------------- |-------------- |------- |-------------- |------- |---------- | - Dictionary | 126.8698 ns | 2.7517 ns | 1.00 | 0.00 | - | 0 B | - Runtime | 458.1133 ns | 10.6768 ns | 3.61 | 0.11 | 0.0247 | 208 B | - MsMemory | 310.6273 ns | 11.6469 ns | 2.45 | 0.10 | - | 0 B | - Redis | 61,794.6588 ns | 1,762.1822 ns | 487.29 | 17.10 | - | 2.18 kB | - Memcached | 108,869.9158 ns | 3,183.5684 ns | 858.51 | 30.60 | - | 14.29 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.csv deleted file mode 100644 index 3a13c832..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.csv +++ /dev/null @@ -1,6 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Dictionary;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;126.8698 ns;2.7517 ns;1.00;0.00;-;0 B -Runtime;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;458.1133 ns;10.6768 ns;3.61;0.11;0.0247;208 B -MsMemory;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;310.6273 ns;11.6469 ns;2.45;0.10;-;0 B -Redis;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"61,794.6588 ns";"1,762.1822 ns";487.29;17.10;-;2.18 kB -Memcached;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"108,869.9158 ns";"3,183.5684 ns";858.51;30.60;-;14.29 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.html deleted file mode 100644 index d240cf76..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GetSingleBenchmark-report.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - -GetSingleBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - -
Method Mean StdDevScaledScaled-StdDevGen 0Allocated
Dictionary126.8698 ns2.7517 ns1.00 0.00-0 B
Runtime458.1133 ns10.6768 ns3.61 0.110.0247208 B
MsMemory310.6273 ns11.6469 ns2.45 0.10-0 B
Redis61,794.6588 ns1,762.1822 ns487.29 17.10-2.18 kB
Memcached108,869.9158 ns3,183.5684 ns858.51 30.60-14.29 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report-github.md deleted file mode 100644 index b6efab5b..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report-github.md +++ /dev/null @@ -1,18 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` - -Method | Mean | StdDev | Scaled | Scaled-StdDev | Gen 0 | Allocated | -------------- |---------- |---------- |------- |-------------- |-------- |---------- | - Naive | 1.3792 ms | 0.0211 ms | 1.00 | 0.00 | 29.6875 | 301.06 kB | - Manuel | 1.3892 ms | 0.0465 ms | 1.01 | 0.04 | 5.4688 | 191.09 kB | - ManuelPooled | 1.3653 ms | 0.0510 ms | 0.99 | 0.04 | - | 106.26 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.csv deleted file mode 100644 index 88153cb0..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.csv +++ /dev/null @@ -1,4 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -Naive;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;1.3792 ms;0.0211 ms;1.00;0.00;29.6875;301.06 kB -Manuel;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;1.3892 ms;0.0465 ms;1.01;0.04;5.4688;191.09 kB -ManuelPooled;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;1.3653 ms;0.0510 ms;0.99;0.04;-;106.26 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.html deleted file mode 100644 index a57c5c62..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/GzBenchmark-report.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -GzBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - -
MethodMeanStdDevScaledScaled-StdDevGen 0Allocated
Naive1.3792 ms0.0211 ms1.00 0.0029.6875301.06 kB
Manuel1.3892 ms0.0465 ms1.01 0.045.4688191.09 kB
ManuelPooled1.3653 ms0.0510 ms0.99 0.04-106.26 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report-github.md deleted file mode 100644 index d603dc7c..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report-github.md +++ /dev/null @@ -1,21 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 - -``` -| Method | Mean | Scaled | Allocated | -|------------------------- |-------------- |-------- |---------- | -| JsonSerializer | 319.7445 us | 1.00 | 157.08 kB | -| BinarySerializer | 498.2847 us | 1.56 | 327.16 kB | -| JsonGzSerializer | 1,018.0015 us | 3.19 | 312.9 kB | -| ProtoBufSerializer | 135.8551 us | 0.43 | 152.68 kB | -| BondBinarySerializer | 85.7551 us | 0.27 | 65.41 kB | -| BondFastBinarySerializer | 83.4832 us | 0.26 | 65.7 kB | -| BondSimpleJsonSerializer | 232.3750 us | 0.73 | 160.55 kB | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.csv deleted file mode 100644 index 6057cb93..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.csv +++ /dev/null @@ -1,8 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdErr;StdDev;Scaled;Scaled-StdDev;Gen 0;Allocated -BinarySerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;498.2847 us;3.4540 us;18.2768 us;1.56;0.08;56.3802;327.16 kB -JsonSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;319.7445 us;2.3651 us;12.9543 us;1.00;0.00;27.2135;157.08 kB -JsonGzSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;"1,018.0015 us";7.2070 us;38.8108 us;3.19;0.17;36.7188;312.9 kB -ProtoBufSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;135.8551 us;1.5883 us;8.2532 us;0.43;0.03;31.0547;152.68 kB -BondBinarySerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;85.7551 us;0.5521 us;2.9733 us;0.27;0.01;12.7116;65.41 kB -BondFastBinarySerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;83.4832 us;0.5788 us;3.1701 us;0.26;0.01;13.0208;65.7 kB -BondSimpleJsonSerializer;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;232.3750 us;0.9338 us;4.9415 us;0.73;0.03;27.6693;160.55 kB diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.html deleted file mode 100644 index 70fe840e..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/SerializationBenchmark-report.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - -SerializationBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  
-
- - - - - - - - - - - -
Method MeanStdErrStdDevScaledScaled-StdDevGen 0Allocated
BinarySerializer498.2847 us3.4540 us18.2768 us1.56 0.0856.3802327.16 kB
JsonSerializer319.7445 us2.3651 us12.9543 us1.00 0.0027.2135157.08 kB
JsonGzSerializer1,018.0015 us7.2070 us38.8108 us3.19 0.1736.7188312.9 kB
ProtoBufSerializer135.8551 us1.5883 us8.2532 us0.43 0.0331.0547152.68 kB
BondBinarySerializer85.7551 us0.5521 us2.9733 us0.27 0.0112.711665.41 kB
BondFastBinarySerializer83.4832 us0.5788 us3.1701 us0.26 0.0113.020865.7 kB
BondSimpleJsonSerializer232.3750 us0.9338 us4.9415 us0.73 0.0327.6693160.55 kB
- - diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report-github.md b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report-github.md deleted file mode 100644 index dae7fc5b..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report-github.md +++ /dev/null @@ -1,17 +0,0 @@ -``` ini - -BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0 -Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8 -Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC - [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0 - -Platform=X64 LaunchCount=2 TargetCount=15 -WarmupCount=10 Allocated=0 B - -``` - Method | Mean | StdDev | Scaled | Scaled-StdDev | --------------------- |----------- |---------- |------- |-------------- | - Framework | 22.1431 ns | 0.2677 ns | 1.00 | 0.00 | - ManualCalcNaive | 11.4425 ns | 0.2960 ns | 0.52 | 0.01 | - ManualCalcOptimized | 7.8302 ns | 0.1593 ns | 0.35 | 0.01 | diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.csv b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.csv deleted file mode 100644 index ed8926c7..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.csv +++ /dev/null @@ -1,4 +0,0 @@ -Method;Job;AnalyzeLaunchVariance;EvaluateOverhead;MaxStdErrRelative;MinInvokeCount;MinIterationTime;RemoveOutliers;Affinity;Jit;Platform;Runtime;AllowVeryLargeObjects;Concurrent;CpuGroups;Force;Server;Clock;EngineFactory;Toolchain;InvocationCount;IterationTime;LaunchCount;RunStrategy;TargetCount;UnrollFactor;WarmupCount;Mean;StdDev;Scaled;Scaled-StdDev;Allocated -Framework;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;22.1431 ns;0.2677 ns;1.00;0.00;0 B -ManualCalcNaive;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;11.4425 ns;0.2960 ns;0.52;0.01;0 B -ManualCalcOptimized;Default;False;Default;Default;Default;Default;Default;255;RyuJit;X64;Clr;False;True;False;True;False;Default;Default;Default;1;Default;2;Default;15;16;10;7.8302 ns;0.1593 ns;0.35;0.01;0 B diff --git a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.html b/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.html deleted file mode 100644 index 90bf8750..00000000 --- a/test/CacheManager.Benchmarks/BenchmarkDotNet.Artifacts/results/UnixTimestampBenchmark-report.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - -UnixTimestampBenchmark - - - - -

-BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
-Processor=Intel(R) Core(TM) i7-6700 CPU 3.40GHz, ProcessorCount=8
-Frequency=3328120 Hz, Resolution=300.4699 ns, Timer=TSC
-  [Host]     : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-  Job-DZPVZX : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1586.0
-
-
Platform=X64  LaunchCount=2  TargetCount=15  
-WarmupCount=10  Allocated=0 B  
-
- - - - - - - -
MethodMeanStdDevScaledScaled-StdDev
Framework22.1431 ns0.2677 ns1.00 0.00
ManualCalcNaive11.4425 ns0.2960 ns0.52 0.01
ManualCalcOptimized7.8302 ns0.1593 ns0.35 0.01
- - diff --git a/test/CacheManager.Benchmarks/Program.cs b/test/CacheManager.Benchmarks/Program.cs deleted file mode 100644 index 06074b7f..00000000 --- a/test/CacheManager.Benchmarks/Program.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using BenchmarkDotNet.Columns; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; -using BenchmarkDotNet.Running; - -namespace CacheManager.Benchmarks -{ - public class CacheManagerBenchConfig : ManualConfig - { - public CacheManagerBenchConfig() - { - Add(Job.MediumRun - .With(Platform.X64)); - } - } - - public class Program - { - public static void Main(string[] args) - { - //new BackplaneMessageBenchmark().DeserializeChange(); - new BackplaneMessageBenchmarkMultiple().SerializeMany(); - new BackplaneMessageBenchmarkMultiple().DeserializeMany(); - - do - { - var config = ManualConfig.Create(DefaultConfig.Instance) - //.With(exporters: BenchmarkDotNet.Exporters.DefaultExporters.) - .With(BenchmarkDotNet.Analysers.EnvironmentAnalyser.Default) - .With(BenchmarkDotNet.Exporters.MarkdownExporter.GitHub) - .With(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default) - .With(StatisticColumn.Mean) - .With(StatisticColumn.Median) - //.With(StatisticColumn.Min) - //.With(StatisticColumn.Max) - .With(StatisticColumn.StdDev) - .With(StatisticColumn.OperationsPerSecond) - .With(BaselineScaledColumn.Scaled) - //.With(BaselineScaledColumn.ScaledStdDev) - .With(RankColumn.Arabic) - - .With(Job.Clr - .WithTargetCount(10) - .WithWarmupCount(4) - .WithLaunchCount(1)); - - //.With(Job.Clr - // .WithTargetCount(10) - // .WithWarmupCount(5) - // .WithLaunchCount(1)); - - BenchmarkSwitcher - .FromAssembly(typeof(Program).GetTypeInfo().Assembly) - .Run(args, config); - - Console.WriteLine("done!"); - Console.WriteLine("Press escape to exit or any key to continue..."); - } while (Console.ReadKey().Key != ConsoleKey.Escape); - } - } -} \ No newline at end of file diff --git a/test/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj b/test/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj deleted file mode 100644 index 109f93f7..00000000 --- a/test/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj +++ /dev/null @@ -1,55 +0,0 @@ - - - - CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features. - 1.0.1 - MichaConrad - net451;netcoreapp1.0 - CacheManager.Config.Tests - Exe - ../../tools/key.snk - true - true - CacheManager.Config.Tests - 1.0.4 - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(DefineConstants);NETCOREAPP - - - - - - diff --git a/test/CacheManager.Config.Tests/Program.cs b/test/CacheManager.Config.Tests/Program.cs deleted file mode 100644 index 6d91af7e..00000000 --- a/test/CacheManager.Config.Tests/Program.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using CacheManager.Core; -using CacheManager.Redis; -#if !NETCOREAPP -using Enyim.Caching; -using Enyim.Caching.Configuration; -#endif -using Microsoft.Extensions.Logging; - -namespace CacheManager.Config.Tests -{ - internal class Program - { - public static void Main(string[] args) - { - var iterations = 100; - try - { - var builder = new Core.ConfigurationBuilder("myCache"); - builder.WithMicrosoftLogging(f => - { - f.AddConsole(LogLevel.Warning); - f.AddDebug(LogLevel.Debug); - }); - - builder - .WithRetryTimeout(500) - .WithMaxRetries(5); - - builder - .WithDictionaryHandle() - .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(20)) - .DisableStatistics(); - - builder - .WithRedisCacheHandle("redis", true) - .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60)) - .DisableStatistics(); - - builder.WithRedisBackplane("redis"); - - builder.WithRedisConfiguration("redis", config => - { - config - //.UseTwemproxy() - //.UseCompatibilityMode("2.4") - .WithAllowAdmin() - .WithDatabase(0) - .WithConnectionTimeout(5000) - .WithEndpoint("127.0.0.1", 6379); - }); - - //builder.WithRedisConfiguration("redis", "localhost:22121"); - - builder.WithBondCompactBinarySerializer(); - -#if !NETCOREAPP - //var memcachedCfg = new MemcachedClientConfiguration(); - //memcachedCfg.AddServer("localhost", 11211); - //builder.WithMemcachedCacheHandle(memcachedCfg); -#endif - - var cacheA = new BaseCacheManager(builder.Build()); - cacheA.Clear(); - - for (var i = 0; i < iterations; i++) - { - var redisHandle = cacheA.CacheHandles.OfType>().First(); - foreach (var server in redisHandle.Servers) - { - Console.WriteLine($"{server.ToString()}=>{server.EndPoint} connected:{server.IsConnected} isSlave:{server.IsSlave}"); - } - - try - { - Tests.PutAndMultiGetTest(cacheA); - } - catch (AggregateException ex) - { - ex.Handle((e) => - { - Console.WriteLine(e); - return true; - }); - } - catch (Exception e) - { - Console.WriteLine("Error: " + e.Message + "\n" + e.StackTrace); - Thread.Sleep(1000); - } - - Console.WriteLine("---------------------------------------------------------"); - } - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - - Console.ForegroundColor = ConsoleColor.DarkGreen; - Console.WriteLine("We are done..."); - Console.ForegroundColor = ConsoleColor.Gray; - Console.ReadKey(); - } - } -} diff --git a/test/CacheManager.Events.Tests/Program.cs b/test/CacheManager.Events.Tests/Program.cs deleted file mode 100644 index fea3c31a..00000000 --- a/test/CacheManager.Events.Tests/Program.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Linq; -using System.Threading; -using Microsoft.Extensions.CommandLineUtils; -using Microsoft.Extensions.Logging; - -namespace CacheManager.Events.Tests -{ - internal class Program - { - private static void Main(string[] args) - { - var loggerFactory = new LoggerFactory() - .AddConsole(LogLevel.Warning); - - var app = new CommandLineApplication(false); - app.Command("redis", (cmdApp) => new RedisCommand(cmdApp, loggerFactory), throwOnUnexpectedArg: true); - app.Command("redisAndMemory", (cmdApp) => new RedisAndMemoryCommand(cmdApp, loggerFactory), throwOnUnexpectedArg: true); - app.Command("redisAndMemoryNoMessages", (cmdApp) => new RedisAndMemoryNoMessagingCommand(cmdApp, loggerFactory), throwOnUnexpectedArg: true); - app.Command("memoryOnly", (cmdApp) => new MemoryOnlyCommand(cmdApp, loggerFactory), throwOnUnexpectedArg: true); - app.HelpOption("-h|--help"); - if (args.Length == 0) - { - app.ShowHelp(); - } - - try - { - app.Execute(args); - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - } - } -} \ No newline at end of file diff --git a/test/CacheManager.MSConfiguration.TypeLoad.Tests/CacheManager.MSConfiguration.TypeLoad.Tests.csproj b/test/CacheManager.MSConfiguration.TypeLoad.Tests/CacheManager.MSConfiguration.TypeLoad.Tests.csproj index 2908724d..502ae3cc 100644 --- a/test/CacheManager.MSConfiguration.TypeLoad.Tests/CacheManager.MSConfiguration.TypeLoad.Tests.csproj +++ b/test/CacheManager.MSConfiguration.TypeLoad.Tests/CacheManager.MSConfiguration.TypeLoad.Tests.csproj @@ -2,12 +2,11 @@ CacheManager.MSConfiguration.TypeLoad.Tests Class Library - Micha - net452;netcoreapp1.0 + net8.0 CacheManager.MSConfiguration.TypeLoad.Tests CacheManager.MSConfiguration.TypeLoad.Tests true - 1.1.1 + $(NoWarn);CA2021 @@ -21,20 +20,21 @@ - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers + + + - + + + - - - - - - - $(DefineConstants);NETCOREAPP - \ No newline at end of file diff --git a/test/CacheManager.MSConfiguration.TypeLoad.Tests/MicrosoftConfigurationTests.cs b/test/CacheManager.MSConfiguration.TypeLoad.Tests/MicrosoftConfigurationTests.cs index 7f69829b..caa54b92 100644 --- a/test/CacheManager.MSConfiguration.TypeLoad.Tests/MicrosoftConfigurationTests.cs +++ b/test/CacheManager.MSConfiguration.TypeLoad.Tests/MicrosoftConfigurationTests.cs @@ -18,7 +18,7 @@ public void Configuration_RedisConfig_NotReferenced() }; Action act = () => GetConfiguration(data).LoadRedisConfigurations(); - act.ShouldThrow("*Redis types could not be loaded*"); + act.Should().Throw("*Redis types could not be loaded*"); } [Fact] @@ -33,37 +33,7 @@ public void Configuration_CacheHandle_Redis_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*'Redis' could not be loaded*"); - } - - [Fact] - public void Configuration_CacheHandle_Memcached_NotReferenced() - { - var data = new Dictionary - { - {"cacheManagers:0:name", "name"}, - {"cacheManagers:0:handles:0:knownType", "Memcached"}, - {"cacheManagers:0:handles:0:key", "key"} - }; - - var config = GetConfiguration(data); - Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*'Memcached' could not be loaded*"); - } - - [Fact] - public void Configuration_CacheHandle_Couchbase_NotReferenced() - { - var data = new Dictionary - { - {"cacheManagers:0:name", "name"}, - {"cacheManagers:0:handles:0:knownType", "Couchbase"}, - {"cacheManagers:0:handles:0:key", "key"} - }; - - var config = GetConfiguration(data); - Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*'Couchbase' could not be loaded*"); + action.Should().Throw().WithMessage("*'Redis' could not be loaded*"); } [Fact] @@ -78,22 +48,7 @@ public void Configuration_CacheHandle_SystemRuntime_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*'SystemRuntime' could not be loaded*"); - } - - [Fact] - public void Configuration_CacheHandle_Web_NotReferenced() - { - var data = new Dictionary - { - {"cacheManagers:0:name", "name"}, - {"cacheManagers:0:handles:0:knownType", "SystemWeb"}, - {"cacheManagers:0:handles:0:key", "key"} - }; - - var config = GetConfiguration(data); - Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*'SystemWeb' could not be loaded*"); + action.Should().Throw().WithMessage("*'SystemRuntime' could not be loaded*"); } [Fact] @@ -108,7 +63,7 @@ public void Configuration_Serializer_Json_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'Json' could not be loaded*"); + action.Should().Throw().WithMessage("*serializer type 'Json' could not be loaded*"); } [Fact] @@ -123,7 +78,7 @@ public void Configuration_Serializer_GzJson_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'GzJson' could not be loaded*"); + action.Should().Throw().WithMessage("*serializer type 'GzJson' could not be loaded*"); } [Fact] @@ -138,7 +93,7 @@ public void Configuration_Serializer_Protobuf_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'Protobuf' could not be loaded*"); + action.Should().Throw().WithMessage("*serializer type 'Protobuf' could not be loaded*"); } [Fact] @@ -153,7 +108,7 @@ public void Configuration_Serializer_BondCompactBinary_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'BondCompactBinary' could not be loaded*"); + action.Should().Throw().WithMessage("*serializer type 'BondCompactBinary' could not be loaded*"); } [Fact] @@ -168,7 +123,7 @@ public void Configuration_Serializer_BondFastBinary_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'BondFastBinary' could not be loaded*"); + action.Should().Throw().WithMessage("*serializer type 'BondFastBinary' could not be loaded*"); } [Fact] @@ -183,30 +138,14 @@ public void Configuration_Serializer_BondSimpleJson_NotReferenced() var config = GetConfiguration(data); Action action = () => config.GetCacheConfiguration("name"); - action.ShouldThrow().WithMessage("*serializer type 'BondSimpleJson' could not be loaded*"); - } - -#if NETCOREAPP - [Fact] - public void Configuration_Serializer_BinaryInvalidOnCore() - { - var data = new Dictionary - { - {"cacheManagers:0:name", "name"}, - {"cacheManagers:0:handles:0:knownType", "Dictionary"}, - {"cacheManagers:0:serializer:knownType", "Binary"}, - }; - - Action act = () => GetConfiguration(data).GetCacheConfiguration("name"); - act.ShouldThrow().WithMessage("*BinaryCacheSerializer is not available*"); + action.Should().Throw().WithMessage("*serializer type 'BondSimpleJson' could not be loaded*"); } -#endif private static IConfigurationRoot GetConfiguration(IDictionary data) { - var configurationBuilder = new Microsoft.Extensions.Configuration.ConfigurationBuilder(); + var configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddInMemoryCollection(data); return configurationBuilder.Build(); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/BackplaneMessageTest.cs b/test/CacheManager.Tests/BackplaneMessageTest.cs index 885828d0..256eede5 100644 --- a/test/CacheManager.Tests/BackplaneMessageTest.cs +++ b/test/CacheManager.Tests/BackplaneMessageTest.cs @@ -28,8 +28,8 @@ public void BackplaneMessage_ChangeAddKey() deserialized.Region.Should().Be(null); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Add); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -50,8 +50,8 @@ public void BackplaneMessage_ChangeAddKeyRegion() deserialized.Region.Should().Be(region); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Add); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -71,8 +71,8 @@ public void BackplaneMessage_ChangePutKey() deserialized.Region.Should().Be(null); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Put); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -93,8 +93,8 @@ public void BackplaneMessage_ChangePutKeyRegion() deserialized.Region.Should().Be(region); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Put); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -114,8 +114,8 @@ public void BackplaneMessage_ChangeUpdateKey() deserialized.Region.Should().Be(null); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Update); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -136,8 +136,8 @@ public void BackplaneMessage_ChangePutUpdateRegion() deserialized.Region.Should().Be(region); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Update); deserialized.Action.Should().Be(BackplaneAction.Changed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -157,8 +157,8 @@ public void BackplaneMessage_RemovedKey() deserialized.Region.Should().Be(null); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Invalid); deserialized.Action.Should().Be(BackplaneAction.Removed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -179,8 +179,8 @@ public void BackplaneMessage_RemovedKeyRegion() deserialized.Region.Should().Be(region); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Invalid); deserialized.Action.Should().Be(BackplaneAction.Removed); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -199,8 +199,8 @@ public void BackplaneMessage_Clear() deserialized.Region.Should().Be(null); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Invalid); deserialized.Action.Should().Be(BackplaneAction.Clear); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -221,8 +221,8 @@ public void BackplaneMessage_ClearRegion() deserialized.Region.Should().Be(region); deserialized.ChangeAction.Should().Be(CacheItemChangedEventAction.Invalid); deserialized.Action.Should().Be(BackplaneAction.ClearRegion); - deserialized.OwnerIdentity.ShouldBeEquivalentTo(owner); - deserialized.ShouldBeEquivalentTo(msg); + deserialized.OwnerIdentity.Should().BeEquivalentTo(owner); + deserialized.Should().BeEquivalentTo(msg); } [Fact] @@ -545,7 +545,7 @@ public void BackplaneMessage_Hashset_DifferentMessage() } [Fact] - public void BackplaneMessage_Mulitple() + public void BackplaneMessage_Multiple() { // arrange var owner = new byte[] { 1, 2, 3, 4 }; @@ -556,11 +556,11 @@ public void BackplaneMessage_Mulitple() var deserialized = BackplaneMessage.Deserialize(serialized).ToArray(); messages.Count.Should().Be(41); - deserialized.ShouldAllBeEquivalentTo(messages); + deserialized.Should().BeEquivalentTo(messages); } [Fact] - public void BackplaneMessage_Mulitple_IgnoreOwner() + public void BackplaneMessage_Multiple_IgnoreOwner() { // arrange var owner = new byte[] { 1, 2, 3, 4 }; @@ -581,7 +581,7 @@ private static ISet CreateMany(byte[] owner) var region = Guid.NewGuid().ToString(); // test hash compare works too, result hashset should still have 41 messages only! - for (var m = 0; m < 10000; m++) + for (var m = 0; m < 100; m++) { for (var i = 0; i < 10; i++) { @@ -611,7 +611,7 @@ public void BackplaneMessage_DeserializeInvalidBytes_WrongOwnerLen() var data = new byte[] { 0, 118, 50, 0, 4, 0, 1, 2, 3, 4 }; Action act = () => BackplaneMessage.Deserialize(data).First(); - act.ShouldThrow().WithMessage("*Cannot read bytes,*"); + act.Should().Throw().WithMessage("*Cannot read bytes,*"); } [Fact] @@ -621,7 +621,7 @@ public void BackplaneMessage_DeserializeInvalidBytes_NoAction() var data = new byte[] { 0, 118, 50, 0, 4, 0, 0, 0, 1, 2, 3, 4 }; Action act = () => BackplaneMessage.Deserialize(data).First(); - act.ShouldThrow().WithMessage("*Cannot read byte,*"); + act.Should().Throw().WithMessage("*Cannot read byte,*"); } [Fact] @@ -631,7 +631,7 @@ public void BackplaneMessage_DeserializeInvalidBytes_WrongAction() var data = new byte[] { 0, 118, 50, 0, 4, 0, 0, 0, 1, 2, 3, 4, 255 }; Action act = () => BackplaneMessage.Deserialize(data).First(); - act.ShouldThrow().WithMessage("*invalid message type*"); + act.Should().Throw().WithMessage("*invalid message type*"); } [Fact] @@ -641,7 +641,7 @@ public void BackplaneMessage_DeserializeInvalidBytes_InvalidString() var data = new byte[] { 0, 118, 50, 0, 4, 0, 0, 0, 1, 2, 3, 4, 3, 10, 0, 0, 0, 42 }; Action act = () => BackplaneMessage.Deserialize(data).First(); - act.ShouldThrow().WithMessage("*Cannot read string,*"); + act.Should().Throw().WithMessage("*Cannot read string,*"); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheFactoryTests.cs b/test/CacheManager.Tests/CacheFactoryTests.cs index 2aec525c..cd396c7e 100644 --- a/test/CacheManager.Tests/CacheFactoryTests.cs +++ b/test/CacheManager.Tests/CacheFactoryTests.cs @@ -1,9 +1,7 @@ -#if !NETCOREAPP -using System; +using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using CacheManager.Core; -using CacheManager.Core.Internal; using CacheManager.Redis; using CacheManager.Serialization.Json; using FluentAssertions; @@ -18,7 +16,7 @@ public class CacheFactoryTests [Fact] public void ConfigurationBuilder_EmptyCtor() { - var builder = new ConfigurationBuilder(); + var builder = new CacheConfigurationBuilder(); var cfg = builder.Build(); cfg.Should().NotBeNull(); @@ -28,39 +26,43 @@ public void ConfigurationBuilder_EmptyCtor() [Fact] public void ConfigurationBuilder_NamedCtorNull() { - Action act = () => new ConfigurationBuilder((string)null); + Action act = () => new CacheConfigurationBuilder((string)null); - act.ShouldThrow().WithMessage("*name*"); + act.Should().Throw() + .And.ParamName.Equals("name"); } [Fact] public void ConfigurationBuilder_ForConfigCtorNull() { - Action act = () => new ConfigurationBuilder((ICacheManagerConfiguration)null); + Action act = () => new CacheConfigurationBuilder((ICacheManagerConfiguration)null); - act.ShouldThrow().WithMessage("*forConfiguration*"); + act.Should().Throw() + .And.ParamName.Equals("forConfiguration"); } [Fact] public void ConfigurationBuilder_NamedForConfigCtorNull() { - Action act = () => new ConfigurationBuilder(null, null); + Action act = () => new CacheConfigurationBuilder(null, null); - act.ShouldThrow().WithMessage("*name*"); + act.Should().Throw() + .And.ParamName.Equals("name"); } [Fact] public void ConfigurationBuilder_NamedForConfigCtorNullB() { - Action act = () => new ConfigurationBuilder("name", null); + Action act = () => new CacheConfigurationBuilder("name", null); - act.ShouldThrow().WithMessage("*forConfiguration*"); + act.Should().Throw() + .And.ParamName.Equals("forConfiguration"); } [Fact] public void ConfigurationBuilder_EmptyCtorAdd() { - var builder = new ConfigurationBuilder(); + var builder = new CacheConfigurationBuilder(); builder.WithDictionaryHandle(); var cfg = builder.Build(); @@ -70,12 +72,12 @@ public void ConfigurationBuilder_EmptyCtorAdd() [Fact] public void ConfigurationBuilder_ForConfiguration() { - var builder = new ConfigurationBuilder("name"); + var builder = new CacheConfigurationBuilder("name"); builder.WithDictionaryHandle().WithExpiration(ExpirationMode.Sliding, TimeSpan.FromMinutes(10)); builder.WithJsonSerializer(); var cfg = builder.Build(); - var forCfg = new ConfigurationBuilder("newName", cfg); + var forCfg = new CacheConfigurationBuilder("newName", cfg); forCfg.WithDictionaryHandle().WithExpiration(ExpirationMode.Absolute, TimeSpan.FromHours(1)); forCfg.WithGzJsonSerializer(); @@ -97,8 +99,8 @@ public void CacheFactory_FromConfig_NullCheck_A() Action act = () => CacheFactory.FromConfiguration((CacheManagerConfiguration)null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: configuration*"); + act.Should().Throw() + .And.ParamName.Equals("configuration"); } [Fact] @@ -111,8 +113,8 @@ public void CacheFactory_FromConfig_NullCheck_B() Action act = () => CacheFactory.FromConfiguration((string)null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: configName*"); + act.Should().Throw() + .And.ParamName.Equals("configName"); } [Fact] @@ -120,13 +122,13 @@ public void CacheFactory_FromConfig_NullCheck_B() public void CacheFactory_FromConfig_TestInit_A() { // arrange - var config = ConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); + var config = CacheConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); // act Action act = () => CacheFactory.FromConfiguration(config); // assert - act.ShouldNotThrow(); + act.Should().NotThrow(); } [Fact] @@ -134,7 +136,7 @@ public void CacheFactory_FromConfig_TestInit_A() public void CacheFactory_FromConfig_TestInit_B() { // arrange - var config = ConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); + var config = CacheConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); // act var cache = CacheFactory.FromConfiguration("custom name", config); @@ -148,7 +150,7 @@ public void CacheFactory_FromConfig_TestInit_B() public void CacheFactory_FromConfig_TestInit_C() { // arrange - var config = ConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); + var config = CacheConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle()); // act var cache = CacheFactory.FromConfiguration(typeof(object), "custom name", config) as ICacheManager; @@ -158,6 +160,7 @@ public void CacheFactory_FromConfig_TestInit_C() } #if !NO_APP_CONFIG + [Fact] [ReplaceCulture] [Trait("category", "NotOnMono")] @@ -166,11 +169,11 @@ public void CacheFactory_FromConfig_NonGeneric_NullCheck_A() // arrange // act - Action act = () => CacheFactory.FromConfiguration((Type)null, "c1"); + Action act = () => CacheFactory.FromConfiguration(null, "c1"); // assert - act.ShouldThrow() - .WithMessage("*cacheValueType*"); + act.Should().Throw() + .And.ParamName.Equals("cacheValueType"); } [Fact] @@ -180,11 +183,11 @@ public void CacheFactory_FromConfig_NonGeneric_NullCheck_B() // arrange // act - Action act = () => CacheFactory.FromConfiguration((Type)null, (CacheManagerConfiguration)null); + Action act = () => CacheFactory.FromConfiguration(null, (CacheManagerConfiguration)null); // assert - act.ShouldThrow() - .WithMessage("*cacheValueType*"); + act.Should().Throw() + .And.ParamName.Equals("cacheValueType"); } [Fact] @@ -198,9 +201,10 @@ public void CacheFactory_FromConfig_NonGeneric_NullCheck_C() Action act = () => CacheFactory.FromConfiguration((Type)null, "c1", "cacheManager"); // assert - act.ShouldThrow() - .WithMessage("*cacheValueType*"); + act.Should().Throw() + .And.ParamName.Equals("cacheValueType"); } + #endif [Fact] @@ -216,8 +220,8 @@ public void CacheFactory_Build_WithHandle_WithoutName() }); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: handleName*"); + act.Should().Throw() + .And.ParamName.Equals("handleName"); } [Fact] @@ -230,43 +234,8 @@ public void CacheFactory_Build_ParamB() Action act = () => CacheFactory.Build(null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: settings*"); - } - - [Fact] - [ReplaceCulture] - public void CacheFactory_Build_DisablePerfCounters() - { - // act - Func> act = () => CacheFactory.Build(settings => - { - settings.WithUpdateMode(CacheUpdateMode.Up) - .WithDictionaryHandle("h1") - .DisablePerformanceCounters(); - }); - - // assert - act().CacheHandles.ElementAt(0).Configuration.EnablePerformanceCounters.Should().BeFalse(); - act().CacheHandles.ElementAt(0).Configuration.EnableStatistics.Should().BeFalse("this is the default value"); - } - - [Fact] - [ReplaceCulture] - public void CacheFactory_Build_EnablePerfCounters() - { - // act - Func> act = () => CacheFactory.Build(settings => - { - settings - .WithDictionaryHandle("h1") - .DisableStatistics() // disable it first - .EnablePerformanceCounters(); // should enable stats - }); - - // assert - act().CacheHandles.ElementAt(0).Configuration.EnablePerformanceCounters.Should().BeTrue(); - act().CacheHandles.ElementAt(0).Configuration.EnableStatistics.Should().BeTrue("is required for perf counters"); + act.Should().Throw() + .And.ParamName.Equals("settings"); } [Fact] @@ -282,7 +251,6 @@ public void CacheFactory_Build_EnableStats() }); // assert - act().CacheHandles.ElementAt(0).Configuration.EnablePerformanceCounters.Should().BeFalse("is default"); act().CacheHandles.ElementAt(0).Configuration.EnableStatistics.Should().BeTrue(); } @@ -298,7 +266,6 @@ public void CacheFactory_Build_DefaultStatsAndPerf() }); // assert - act().CacheHandles.ElementAt(0).Configuration.EnablePerformanceCounters.Should().BeFalse("is default"); act().CacheHandles.ElementAt(0).Configuration.EnableStatistics.Should().BeFalse("is default"); } @@ -315,7 +282,7 @@ public void CacheFactory_Build_WithInvalidExpiration() }); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("If expiration mode*"); } @@ -330,7 +297,7 @@ public void CacheFactory_Build_WithInvalidMaxRetries() }); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("Maximum number of retries must be greater*"); } @@ -345,7 +312,7 @@ public void CacheFactory_Build_WithInvalidRetryTimeout() }); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("Retry timeout must be greater*"); } @@ -367,7 +334,7 @@ public void CacheFactory_Build_WithRedisBackplaneNoBackplaneSource() }; // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("*At least one cache handle must be*"); } @@ -384,7 +351,7 @@ public void CacheFactory_Build_WithRedisBackplaneTooManyBackplaneSources() }); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("*Only one cache handle can be *"); } @@ -401,7 +368,7 @@ public void CacheFactory_Build_WithRedisBackplaneNoRedisConfig() }); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("*No configuration added for configuration name*"); } @@ -416,8 +383,8 @@ public void CacheFactory_Build_WithRedisBackplaneNoName() }); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: configurationKey*"); + act.Should().Throw() + .And.ParamName.Equals("configurationKey"); } [Fact] @@ -431,8 +398,8 @@ public void CacheFactory_Build_WithRedisConfigurationNoKeyA() }); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: configurationKey*"); + act.Should().Throw() + .And.ParamName.Equals("configurationKey"); } [Fact] @@ -446,8 +413,8 @@ public void CacheFactory_Build_WithRedisConfigurationNoKeyB() }); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: configurationKey*"); + act.Should().Throw() + .And.ParamName.Equals("configurationKey"); } [Fact] @@ -461,8 +428,8 @@ public void CacheFactory_Build_WithRedisConfigurationInvalidEndpoint() }); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: host*"); + act.Should().Throw() + .And.ParamName.Equals("configurationKey"); } [Fact] @@ -471,7 +438,7 @@ public void CacheFactory_Build_WithRedisConfigurationConnectionString() { // arrange var name = Guid.NewGuid().ToString(); - var connection = "127.0.0.1:8080,allowAdmin=true,name=myName"; + var connection = "127.0.0.1:8080,allowAdmin=true,name=myName,defaultDatabase=1"; var expected = StackExchange.Redis.ConfigurationOptions.Parse(connection); // act @@ -484,13 +451,14 @@ public void CacheFactory_Build_WithRedisConfigurationConnectionString() var config = RedisConfigurations.GetConfiguration(name); // assert - config.ConfigurationOptions.ShouldBeEquivalentTo(expected); + config.ConfigurationOptions.ToString().Should().BeEquivalentTo(expected.ToString()); config.TwemproxyEnabled.Should().BeFalse(); config.AllowAdmin.Should().BeTrue(); config.IsSsl.Should().BeFalse(); config.Key.Should().Be(name); + config.Database.Should().Be(1); } - + [Fact] [ReplaceCulture] public void CacheFactory_Build_WithRedisConnectionStringWithProxy() @@ -510,14 +478,13 @@ public void CacheFactory_Build_WithRedisConnectionStringWithProxy() var config = RedisConfigurations.GetConfiguration(name); // assert - config.ConfigurationOptions.ShouldBeEquivalentTo(expected); + config.ConfigurationOptions.ToString().Should().BeEquivalentTo(expected.ToString()); config.TwemproxyEnabled.Should().BeTrue(); config.AllowAdmin.Should().BeFalse(); config.IsSsl.Should().BeTrue(); config.Key.Should().Be(name); } - [Fact] [ReplaceCulture] public void CacheFactory_Build_WithRedisConfigurationValidateBuilder() @@ -553,7 +520,7 @@ public void CacheFactory_Build_WithRedisConfigurationValidateBuilder() configuration.Password.Should().Be("secret"); configuration.IsSsl.Should().BeTrue(); configuration.SslHost.Should().Be("mySslHost"); - configuration.Endpoints.ShouldBeEquivalentTo(new[] { new ServerEndPoint("127.0.0.1", 2323), new ServerEndPoint("nohost", 60999) }); + configuration.Endpoints.Should().BeEquivalentTo(new[] { new ServerEndPoint("127.0.0.1", 2323), new ServerEndPoint("nohost", 60999) }); } [Fact] @@ -575,7 +542,7 @@ public void CacheFactory_Build_ValidateSettings() .WithUpdateMode(CacheUpdateMode.None) .WithDictionaryHandle("h1") .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromHours(12)) - .EnablePerformanceCounters() + .EnableStatistics() .And.WithDictionaryHandle("h2") .WithExpiration(ExpirationMode.None, TimeSpan.Zero) .DisableStatistics() @@ -590,24 +557,21 @@ public void CacheFactory_Build_ValidateSettings() act.Configuration.MaxRetries.Should().Be(22); act.Configuration.RetryTimeout.Should().Be(2223); act.CacheHandles.ElementAt(0).Configuration.Name.Should().Be("h1"); - act.CacheHandles.ElementAt(0).Configuration.EnablePerformanceCounters.Should().BeTrue(); act.CacheHandles.ElementAt(0).Configuration.EnableStatistics.Should().BeTrue(); act.CacheHandles.ElementAt(0).Configuration.ExpirationMode.Should().Be(ExpirationMode.Absolute); act.CacheHandles.ElementAt(0).Configuration.ExpirationTimeout.Should().Be(new TimeSpan(12, 0, 0)); act.CacheHandles.ElementAt(1).Configuration.Name.Should().Be("h2"); - act.CacheHandles.ElementAt(1).Configuration.EnablePerformanceCounters.Should().BeFalse(); act.CacheHandles.ElementAt(1).Configuration.EnableStatistics.Should().BeFalse(); act.CacheHandles.ElementAt(1).Configuration.ExpirationMode.Should().Be(ExpirationMode.None); act.CacheHandles.ElementAt(1).Configuration.ExpirationTimeout.Should().Be(new TimeSpan(0, 0, 0)); act.CacheHandles.ElementAt(2).Configuration.Name.Should().Be("h3"); - act.CacheHandles.ElementAt(2).Configuration.EnablePerformanceCounters.Should().BeFalse(); act.CacheHandles.ElementAt(2).Configuration.EnableStatistics.Should().BeTrue(); act.CacheHandles.ElementAt(2).Configuration.ExpirationMode.Should().Be(ExpirationMode.Sliding); act.CacheHandles.ElementAt(2).Configuration.ExpirationTimeout.Should().Be(new TimeSpan(0, 0, 231)); } - + [Fact] [ReplaceCulture] [Trait("category", "NotOnMono")] @@ -662,7 +626,7 @@ public void CacheFactory_FromConfig_NonGeneric_C() { var cache = CacheFactory.FromConfiguration( typeof(string), - ConfigurationBuilder.BuildConfiguration(cfg => cfg.WithSystemRuntimeCacheHandle())) as ICacheManager; + CacheConfigurationBuilder.BuildConfiguration(cfg => cfg.WithSystemRuntimeCacheHandle())) as ICacheManager; cache.Should().NotBeNull(); cache.CacheHandles.Count().Should().Be(1); @@ -712,19 +676,5 @@ public void CacheFactory_Build_WithJsonSerializerCustomSettings() .WithJsonSerializer(serializationSettings, deserializationSettings) .WithSystemRuntimeCacheHandle()); } - - [Fact] - [ReplaceCulture] - public void CacheFactory_Build_WithSerializer_SimpleBinary() - { - var cache = CacheFactory.Build( - p => - p.WithSerializer(typeof(BinaryCacheSerializer)) - .WithSystemRuntimeCacheHandle()); - - cache.Configuration.SerializerType.Should().NotBeNull(); - cache.Configuration.SerializerType.Should().Be(typeof(BinaryCacheSerializer)); - } } } -#endif \ No newline at end of file diff --git a/test/CacheManager.Tests/CacheItemValidation.cs b/test/CacheManager.Tests/CacheItemValidation.cs index 6e3cd3ce..4597f7e7 100644 --- a/test/CacheManager.Tests/CacheItemValidation.cs +++ b/test/CacheManager.Tests/CacheItemValidation.cs @@ -11,7 +11,7 @@ public class CacheItemValidation { [Fact] [Trait("category", "Unreliable")] - public void CacheItem_WithAbsoluteExpiration() + public void CacheItemValidation_WithAbsoluteExpiration() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -25,12 +25,14 @@ public void CacheItem_WithAbsoluteExpiration() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); + result.CreatedUtc.Kind.Should().Be(baseItem.CreatedUtc.Kind); + result.CreatedUtc.Kind.Should().Be(DateTimeKind.Utc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); } [Fact] - public void CacheItem_WithAbsoluteExpiration_Invalid() + public void CacheItemValidation_WithAbsoluteExpiration_Invalid() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -39,11 +41,11 @@ public void CacheItem_WithAbsoluteExpiration_Invalid() Action act = () => baseItem.WithAbsoluteExpiration(DateTimeOffset.Now.AddMinutes(-10)); // assert - act.ShouldThrow().WithMessage("*value must be greater*"); + act.Should().Throw().WithMessage("*value must be greater*"); } [Fact] - public void CacheItem_WithAbsoluteExpiration_InvalidB() + public void CacheItemValidation_WithAbsoluteExpiration_InvalidB() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -52,12 +54,11 @@ public void CacheItem_WithAbsoluteExpiration_InvalidB() Action act = () => baseItem.WithAbsoluteExpiration(TimeSpan.FromMilliseconds(-10)); // assert - act.ShouldThrow().WithMessage("*value must be greater*"); + act.Should().Throw().WithMessage("*value must be greater*"); } - [Fact] - public void CacheItem_WithSlidingExpiration_Invalid() + public void CacheItemValidation_WithSlidingExpiration_Invalid() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -66,22 +67,22 @@ public void CacheItem_WithSlidingExpiration_Invalid() Action act = () => baseItem.WithSlidingExpiration(TimeSpan.FromDays(-1)); // assert - act.ShouldThrow().WithMessage("*value must be greater*"); + act.Should().Throw().WithMessage("*value must be greater*"); } [Fact] - public void CacheItem_WithExpiration_Invalid() + public void CacheItemValidation_WithExpiration_Invalid() { // arrange // act Action act = () => new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromTicks(long.MaxValue)); // assert - act.ShouldThrow().WithMessage("*365*"); + act.Should().Throw().WithMessage("*365*"); } [Fact] - public void CacheItem_WithCreated() + public void CacheItemValidation_WithCreated() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -91,17 +92,17 @@ public void CacheItem_WithCreated() var result = baseItem.WithCreated(created); // assert - result.CreatedUtc.Should().Be(created); + result.CreatedUtc.Should().BeCloseTo(created); result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); result.ExpirationMode.Should().Be(baseItem.ExpirationMode); result.ExpirationTimeout.Should().Be(baseItem.ExpirationTimeout); } [Fact] - public void CacheItem_WithExpiration_None() + public void CacheItemValidation_WithExpiration_None() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -115,12 +116,12 @@ public void CacheItem_WithExpiration_None() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); } [Fact] - public void CacheItem_WithExpiration_Sliding() + public void CacheItemValidation_WithExpiration_Sliding() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Absolute, TimeSpan.FromDays(10)); @@ -134,13 +135,13 @@ public void CacheItem_WithExpiration_Sliding() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); } [Fact] [Trait("category", "Unreliable")] - public void CacheItem_WithExpiration_Absolute() + public void CacheItemValidation_WithExpiration_Absolute() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -154,12 +155,12 @@ public void CacheItem_WithExpiration_Absolute() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(result.CreatedUtc); // !! Changed due to issue #136 - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(result.CreatedUtc); // !! Changed due to issue #136 + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); } [Fact] - public void CacheItem_WithNoExpiration() + public void CacheItemValidation_WithNoExpiration() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Sliding, TimeSpan.FromDays(10)); @@ -173,12 +174,12 @@ public void CacheItem_WithNoExpiration() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); } [Fact] - public void CacheItem_WithSlidingExpiration() + public void CacheItemValidation_WithSlidingExpiration() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Absolute, TimeSpan.FromDays(10)); @@ -192,12 +193,12 @@ public void CacheItem_WithSlidingExpiration() result.Value.Should().Be(baseItem.Value); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); } [Fact] - public void CacheItem_WithValue() + public void CacheItemValidation_WithValue() { // arrange var baseItem = new CacheItem("key", "region", "value", ExpirationMode.Absolute, TimeSpan.FromDays(10)); @@ -209,8 +210,8 @@ public void CacheItem_WithValue() result.Value.Should().Be("new value"); result.Region.Should().Be(baseItem.Region); result.Key.Should().Be(baseItem.Key); - result.CreatedUtc.Should().Be(baseItem.CreatedUtc); - result.LastAccessedUtc.Should().Be(baseItem.LastAccessedUtc); + result.CreatedUtc.Should().BeCloseTo(baseItem.CreatedUtc); + result.LastAccessedUtc.Should().BeCloseTo(baseItem.LastAccessedUtc); result.ExpirationMode.Should().Be(baseItem.ExpirationMode); result.ExpirationTimeout.Should().Be(baseItem.ExpirationTimeout); } @@ -219,7 +220,7 @@ public void CacheItem_WithValue() [Fact] [ReplaceCulture] - public void CacheItem_Ctor1_EmptyKey() + public void CacheItemValidation_Ctor1_EmptyKey() { // arrange var key = string.Empty; @@ -229,12 +230,13 @@ public void CacheItem_Ctor1_EmptyKey() Action act = () => new CacheItem(key, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor1_NullKey() + public void CacheItemValidation_Ctor1_NullKey() { // arrange string key = null; @@ -244,12 +246,13 @@ public void CacheItem_Ctor1_NullKey() Action act = () => new CacheItem(key, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor1_WhitespaceKey() + public void CacheItemValidation_Ctor1_WhitespaceKey() { // arrange string key = " "; @@ -259,12 +262,13 @@ public void CacheItem_Ctor1_WhitespaceKey() Action act = () => new CacheItem(key, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor1_NullValue() + public void CacheItemValidation_Ctor1_NullValue() { // arrange string key = "key"; @@ -274,12 +278,13 @@ public void CacheItem_Ctor1_NullValue() Action act = () => new CacheItem(key, value); // assert - act.ShouldThrow().WithMessage("*cannot be null.\r\nParameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor1_ValidateCreatedResult() + public void CacheItemValidation_Ctor1_ValidateCreatedResult() { // arrange string key = "key"; @@ -303,7 +308,7 @@ public void CacheItem_Ctor1_ValidateCreatedResult() [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_EmptyKey() + public void CacheItemValidation_Ctor2_EmptyKey() { // arrange var key = string.Empty; @@ -314,12 +319,13 @@ public void CacheItem_Ctor2_EmptyKey() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_NullKey() + public void CacheItemValidation_Ctor2_NullKey() { // arrange string key = null; @@ -330,12 +336,13 @@ public void CacheItem_Ctor2_NullKey() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_WhitespaceKey() + public void CacheItemValidation_Ctor2_WhitespaceKey() { // arrange string key = " "; @@ -346,12 +353,13 @@ public void CacheItem_Ctor2_WhitespaceKey() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_NullValue() + public void CacheItemValidation_Ctor2_NullValue() { // arrange string key = "key"; @@ -362,12 +370,13 @@ public void CacheItem_Ctor2_NullValue() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow().WithMessage("*cannot be null.\r\nParameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_EmptyRegion() + public void CacheItemValidation_Ctor2_EmptyRegion() { // arrange string key = "key"; @@ -378,13 +387,13 @@ public void CacheItem_Ctor2_EmptyRegion() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_NullRegion() + public void CacheItemValidation_Ctor2_NullRegion() { // arrange string key = "key"; @@ -395,13 +404,13 @@ public void CacheItem_Ctor2_NullRegion() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_WhitespaceRegion() + public void CacheItemValidation_Ctor2_WhitespaceRegion() { // arrange string key = "key"; @@ -412,13 +421,13 @@ public void CacheItem_Ctor2_WhitespaceRegion() Action act = () => new CacheItem(key, region, value); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor2_ValidateCreatedResult() + public void CacheItemValidation_Ctor2_ValidateCreatedResult() { // arrange string key = "key"; @@ -443,7 +452,7 @@ public void CacheItem_Ctor2_ValidateCreatedResult() [Fact] [ReplaceCulture] - public void CacheItem_Ctor3_EmptyKey() + public void CacheItemValidation_Ctor3_EmptyKey() { // arrange var key = string.Empty; @@ -455,12 +464,13 @@ public void CacheItem_Ctor3_EmptyKey() Action act = () => new CacheItem(key, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor3_NullKey() + public void CacheItemValidation_Ctor3_NullKey() { // arrange string key = null; @@ -472,12 +482,13 @@ public void CacheItem_Ctor3_NullKey() Action act = () => new CacheItem(key, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*cannot be null.\r\nParameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor3_WhitespaceKey() + public void CacheItemValidation_Ctor3_WhitespaceKey() { // arrange string key = " "; @@ -489,12 +500,13 @@ public void CacheItem_Ctor3_WhitespaceKey() Action act = () => new CacheItem(key, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor3_NullValue() + public void CacheItemValidation_Ctor3_NullValue() { // arrange string key = "key"; @@ -506,12 +518,13 @@ public void CacheItem_Ctor3_NullValue() Action act = () => new CacheItem(key, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*cannot be null.\r\nParameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor3_ValidateCreatedResult() + public void CacheItemValidation_Ctor3_ValidateCreatedResult() { // arrange string key = "key"; @@ -537,7 +550,7 @@ public void CacheItem_Ctor3_ValidateCreatedResult() [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_EmptyKey() + public void CacheItemValidation_Ctor4_EmptyKey() { // arrange var key = string.Empty; @@ -550,12 +563,13 @@ public void CacheItem_Ctor4_EmptyKey() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_NullKey() + public void CacheItemValidation_Ctor4_NullKey() { // arrange string key = null; @@ -568,12 +582,13 @@ public void CacheItem_Ctor4_NullKey() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_WhitespaceKey() + public void CacheItemValidation_Ctor4_WhitespaceKey() { // arrange string key = " "; @@ -586,12 +601,13 @@ public void CacheItem_Ctor4_WhitespaceKey() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_NullValue() + public void CacheItemValidation_Ctor4_NullValue() { // arrange string key = "key"; @@ -604,12 +620,13 @@ public void CacheItem_Ctor4_NullValue() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow().WithMessage("*Parameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_EmptyRegion() + public void CacheItemValidation_Ctor4_EmptyRegion() { // arrange string key = "key"; @@ -622,13 +639,13 @@ public void CacheItem_Ctor4_EmptyRegion() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_NullRegion() + public void CacheItemValidation_Ctor4_NullRegion() { // arrange string key = "key"; @@ -641,13 +658,13 @@ public void CacheItem_Ctor4_NullRegion() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_WhitespaceRegion() + public void CacheItemValidation_Ctor4_WhitespaceRegion() { // arrange string key = "key"; @@ -660,13 +677,13 @@ public void CacheItem_Ctor4_WhitespaceRegion() Action act = () => new CacheItem(key, region, value, mode, timeout); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] [ReplaceCulture] - public void CacheItem_Ctor4_ValidateCreatedResult() + public void CacheItemValidation_Ctor4_ValidateCreatedResult() { // arrange string key = "key"; @@ -691,7 +708,7 @@ public void CacheItem_Ctor4_ValidateCreatedResult() [Fact] [ReplaceCulture] - public void CacheItem_Ctor_ExpirationTimeoutDefaults() + public void CacheItemValidation_Ctor_ExpirationTimeoutDefaults() { // arrange string key = "key"; @@ -708,4 +725,4 @@ public void CacheItem_Ctor_ExpirationTimeoutDefaults() .And.Match>(p => p.Value == value); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheManager.Tests.csproj b/test/CacheManager.Tests/CacheManager.Tests.csproj index 7616cc6f..13fb34cb 100644 --- a/test/CacheManager.Tests/CacheManager.Tests.csproj +++ b/test/CacheManager.Tests/CacheManager.Tests.csproj @@ -2,7 +2,7 @@ - net452;netcoreapp1.1 + ;net8.0 1.0.0 CacheManager.Tests @@ -11,8 +11,13 @@ true CacheManager.Tests true + $(NoWarn);CA2021 + + + + PreserveNewest @@ -21,55 +26,55 @@ - - - + + Always + App.config + + + Always + App.config + + + + + + - + + - - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers + + + + - - - - + + + + + + - - - - - - - - - - - - - + + + + + - - $(DefineConstants);REDISENABLED;MOCK_HTTPCONTEXT_ENABLED; - - - $(DefineConstants);REDISENABLED;NETCOREAPP; - - - \ No newline at end of file diff --git a/test/CacheManager.Tests/CacheManagerAdvancedUpdateTests.cs b/test/CacheManager.Tests/CacheManagerAdvancedUpdateTests.cs index 40032391..d64ab0dc 100644 --- a/test/CacheManager.Tests/CacheManagerAdvancedUpdateTests.cs +++ b/test/CacheManager.Tests/CacheManagerAdvancedUpdateTests.cs @@ -3,14 +3,15 @@ using System.Linq; using CacheManager.Core; using CacheManager.Core.Internal; -using CacheManager.Core.Logging; + using FluentAssertions; +using Microsoft.Extensions.Logging; using Xunit; namespace CacheManager.Tests { [ExcludeFromCodeCoverage] - public class CacheManagerAdvancedUpdateTests + public class CacheManagerAdvancedUpdateTests : IClassFixture { [Theory] [ClassData(typeof(TestCacheManagers))] @@ -21,7 +22,7 @@ public void Update_ThrowsIf_FactoryReturnsNull(ICacheManager cache) var key = Guid.NewGuid().ToString(); cache.Add(key, "value"); Action act = () => cache.Update(key, v => null); - act.ShouldThrow("factory"); + act.Should().Throw("factory"); } } @@ -34,7 +35,7 @@ public void UpdateItemResult_ForSuccess() Func> act = () => UpdateItemResult.ForSuccess(item, true, 1001); // assert - act().ShouldBeEquivalentTo(new { Value = item, UpdateState = UpdateItemResultState.Success, NumberOfTriesNeeded = 1001, VersionConflictOccurred = true }); + act().Should().BeEquivalentTo(new { Value = item, UpdateState = UpdateItemResultState.Success, NumberOfTriesNeeded = 1001, VersionConflictOccurred = true }); } [Fact] @@ -45,7 +46,7 @@ public void UpdateItemResult_ForTooManyTries() Func> act = () => UpdateItemResult.ForTooManyRetries(1001); // assert - act().ShouldBeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.TooManyRetries, NumberOfTriesNeeded = 1001, VersionConflictOccurred = true }); + act().Should().BeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.TooManyRetries, NumberOfTriesNeeded = 1001, VersionConflictOccurred = true }); } [Fact] @@ -56,7 +57,7 @@ public void UpdateItemResult_ForDidNotExist() Func> act = () => UpdateItemResult.ForItemDidNotExist(); // assert - act().ShouldBeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.ItemDidNotExist, NumberOfTriesNeeded = 1, VersionConflictOccurred = false }); + act().Should().BeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.ItemDidNotExist, NumberOfTriesNeeded = 1, VersionConflictOccurred = false }); } [Fact] @@ -67,7 +68,7 @@ public void UpdateItemResult_ForFactoryReturnsNull() Func> act = () => UpdateItemResult.ForFactoryReturnedNull(); // assert - act().ShouldBeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.FactoryReturnedNull, NumberOfTriesNeeded = 1, VersionConflictOccurred = false }); + act().Should().BeEquivalentTo(new { Value = default(object), UpdateState = UpdateItemResultState.FactoryReturnedNull, NumberOfTriesNeeded = 1, VersionConflictOccurred = false }); } [Fact] @@ -289,7 +290,7 @@ public class MockCacheHandle : BaseCacheHandle public MockCacheHandle(CacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) : base(managerConfiguration, configuration) { - this.Logger = loggerFactory.CreateLogger(this); + this.Logger = loggerFactory.CreateLogger(this.GetType()); this.AddCall = () => true; this.PutCall = () => { }; this.RemoveCall = () => { }; @@ -362,4 +363,4 @@ protected override bool RemoveInternal(string key, string region) return true; } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheManagerEventsTest.cs b/test/CacheManager.Tests/CacheManagerEventsTest.cs index c088df45..b0d904c2 100644 --- a/test/CacheManager.Tests/CacheManagerEventsTest.cs +++ b/test/CacheManager.Tests/CacheManagerEventsTest.cs @@ -1,21 +1,30 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Threading.Tasks; -using CacheManager.Core; -using CacheManager.Core.Internal; -using CacheManager.Core.Logging; -using CacheManager.Core.Utility; -using FluentAssertions; -using StackExchange.Redis; -using Xunit; - -namespace CacheManager.Tests +namespace CacheManager.Tests { + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + using System.Threading.Tasks; + using CacheManager.Core; + using CacheManager.Core.Internal; + using CacheManager.Core.Utility; + using FluentAssertions; + using Microsoft.Extensions.Logging; + using StackExchange.Redis; + using Xunit; + using Xunit.Abstractions; + using static TestHelper; + [ExcludeFromCodeCoverage] - public class CacheManagerEventsTest + public class CacheManagerEventsTest : IClassFixture { + private readonly ITestOutputHelper _testOutputHelper; + + public CacheManagerEventsTest(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper ?? throw new ArgumentNullException(nameof(testOutputHelper)); + } + [Fact] [ReplaceCulture] public void Events_CacheActionEventArgsCtor() @@ -28,8 +37,8 @@ public void Events_CacheActionEventArgsCtor() Action act = () => new CacheActionEventArgs(key, region); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key*"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] @@ -44,7 +53,7 @@ public void Events_CacheActionEventArgsCtor_Valid() Func act = () => new CacheActionEventArgs(key, region); // assert - act().ShouldBeEquivalentTo(new { Region = (string)null, Key = key, Origin = CacheActionEventArgOrigin.Local }); + act().Should().BeEquivalentTo(new { Region = (string)null, Key = key, Origin = CacheActionEventArgOrigin.Local }); } [Fact] @@ -59,8 +68,8 @@ public void Events_CacheItemRemovedEventArgsCtor() Action act = () => new CacheItemRemovedEventArgs(key, region, CacheItemRemovedReason.Expired, null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key*"); + act.Should().Throw() + .And.ParamName.Equals("key"); } [Fact] @@ -75,7 +84,7 @@ public void Events_CacheItemRemovedEventArgsCtor_Valid() Func act = () => new CacheItemRemovedEventArgs(key, region, CacheItemRemovedReason.Expired, null, 2); // assert - act().ShouldBeEquivalentTo(new { Region = (string)null, Key = key, Reason = CacheItemRemovedReason.Expired, Level = 2, Value = (object)null }); + act().Should().BeEquivalentTo(new { Region = (string)null, Key = key, Reason = CacheItemRemovedReason.Expired, Level = 2, Value = (object)null }); } [Fact] @@ -90,7 +99,7 @@ public void Events_CacheItemRemovedEventArgsCtor_ValidB() Func act = () => new CacheItemRemovedEventArgs(key, region, CacheItemRemovedReason.Expired, "value", 2); // assert - act().ShouldBeEquivalentTo(new { Region = region, Key = key, Reason = CacheItemRemovedReason.Expired, Level = 2, Value = "value" }); + act().Should().BeEquivalentTo(new { Region = region, Key = key, Reason = CacheItemRemovedReason.Expired, Level = 2, Value = "value" }); } [Fact] @@ -105,7 +114,7 @@ public void Events_CacheItemRemovedEventArgsCtor_ValidC() Func act = () => new CacheItemRemovedEventArgs(key, region, CacheItemRemovedReason.Evicted, "value", 0); // assert - act().ShouldBeEquivalentTo(new { Region = region, Key = key, Reason = CacheItemRemovedReason.Evicted, Level = 0, Value = "value" }); + act().Should().BeEquivalentTo(new { Region = region, Key = key, Reason = CacheItemRemovedReason.Evicted, Level = 0, Value = "value" }); } [Fact] @@ -115,7 +124,7 @@ public void Events_CacheClearEventArgsCtor() Action act = () => new CacheClearEventArgs(); // assert - act.ShouldNotThrow(); + act.Should().NotThrow(); } [Fact] @@ -129,8 +138,8 @@ public void Events_CacheClearRegionEventArgsCtor() Action act = () => new CacheClearRegionEventArgs(region); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region*"); + act.Should().Throw() + .And.ParamName.Equals("region"); } [Fact] @@ -144,12 +153,18 @@ public void Events_CacheClearRegionEventArgsCtor_Valid() Func act = () => new CacheClearRegionEventArgs(region); // assert - act().ShouldBeEquivalentTo(new { Region = region, Origin = CacheActionEventArgOrigin.Local }); + act().Should().BeEquivalentTo(new { Region = region, Origin = CacheActionEventArgOrigin.Local }); } public class LongRunningEventTestBase { - public async Task RunTest(ICacheManagerConfiguration configuration, string useKey, string useRegion, bool endGetShouldBeNull = true, bool runGetWhileWaiting = true, bool expectValue = true) + public async Task RunTest( + ICacheManagerConfiguration configuration, + string useKey, + string useRegion, + bool endGetShouldBeNull = true, + bool runGetWhileWaiting = true, + bool expectValue = true) { var triggered = false; CacheItemRemovedEventArgs resultArgs = null; @@ -223,21 +238,19 @@ public async Task RunTest(ICacheManagerConfiguration } } -#if !NETCOREAPP - // exclusive inner class for parallel exec of this long running test public class SystemRuntimeSpecific : LongRunningEventTestBase { [Fact] public async Task Events_SysRuntime_ExpireTriggers() { - var cfg = new ConfigurationBuilder() + var cfg = new CacheConfigurationBuilder() .WithSystemRuntimeCacheHandle() .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); - string useRegion = "@_@23@_!!"; + var useKey = Guid.NewGuid().ToString(); + var useRegion = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, useRegion); result.Reason.Should().Be(CacheItemRemovedReason.Expired); @@ -250,14 +263,14 @@ public async Task Events_SysRuntime_ExpireTriggers() [Trait("category", "Unreliable")] public async Task Events_SysRuntime_ExpireEvictsAbove() { - var cfg = new ConfigurationBuilder() + var cfg = new CacheConfigurationBuilder() .WithDictionaryHandle() .And .WithSystemRuntimeCacheHandle() .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); + var useKey = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, null, true, false); @@ -267,7 +280,6 @@ public async Task Events_SysRuntime_ExpireEvictsAbove() result.Region.Should().BeNull(); } } -#endif // exclusive inner class for parallel exec of this long running test public class DictionarySpecific : LongRunningEventTestBase @@ -275,13 +287,13 @@ public class DictionarySpecific : LongRunningEventTestBase [Fact] public async Task Events_Dic_ExpireTriggers() { - var cfg = new ConfigurationBuilder() + var cfg = new CacheConfigurationBuilder() .WithDictionaryHandle() .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); - string useRegion = "@_@23@_!!"; + var useKey = Guid.NewGuid().ToString(); + var useRegion = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, useRegion, true, true); result.Reason.Should().Be(CacheItemRemovedReason.Expired); @@ -294,14 +306,14 @@ public async Task Events_Dic_ExpireTriggers() [Trait("category", "Unreliable")] public async Task Events_Dic_ExpireEvictsAbove() { - var cfg = new ConfigurationBuilder() - .WithDictionaryHandle() + var cfg = new CacheConfigurationBuilder() + .WithDictionaryHandle(options: new DictionaryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMilliseconds(10) }) .And - .WithDictionaryHandle() + .WithDictionaryHandle(options: new DictionaryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMilliseconds(10) }) .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); + var useKey = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, null, true, false); @@ -318,13 +330,13 @@ public class MsMemorySpecific : LongRunningEventTestBase [Fact] public async Task Events_MsMemory_ExpireTriggers() { - var cfg = new ConfigurationBuilder() + var cfg = new CacheConfigurationBuilder() .WithMicrosoftMemoryCacheHandle() .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); - string useRegion = "@_@23@_!!"; + var useKey = Guid.NewGuid().ToString(); + var useRegion = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, useRegion); result.Reason.Should().Be(CacheItemRemovedReason.Expired); @@ -337,14 +349,14 @@ public async Task Events_MsMemory_ExpireTriggers() [Trait("category", "Unreliable")] public async Task Events_MsMemory_ExpireEvictsAbove() { - var cfg = new ConfigurationBuilder() + var cfg = new CacheConfigurationBuilder() .WithDictionaryHandle() .And .WithMicrosoftMemoryCacheHandle() .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); + var useKey = Guid.NewGuid().ToString(); // we cannot wait for the cache to expire it on its own, it only checks if you actually actively do something... var result = await RunTest(cfg, useKey, null, true, true); @@ -356,69 +368,24 @@ public async Task Events_MsMemory_ExpireEvictsAbove() } } -#if MOCK_HTTPCONTEXT_ENABLED - +#if NET8_0_OR_GREATER // exclusive inner class for parallel exec of this long running test - public class WebCacheSpecific : LongRunningEventTestBase + public class RedisSpecific : LongRunningEventTestBase, IClassFixture { - [Fact] - public async Task Events_WebCache_ExpireTriggers() - { - var cfg = new ConfigurationBuilder() - .WithHandle(typeof(SystemWebCacheHandleWrapper<>)) - .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) - .Build(); - - string useKey = Guid.NewGuid().ToString(); - string useRegion = "@_@23@_!!"; - var result = await RunTest(cfg, useKey, useRegion); - - result.Reason.Should().Be(CacheItemRemovedReason.Expired); - result.Level.Should().Be(1); - result.Key.Should().Be(useKey); - result.Region.Should().Be(useRegion); - } - - [Fact] - [Trait("category", "Unreliable")] - public async Task Events_WebCache_ExpireEvictsAbove() - { - var cfg = new ConfigurationBuilder() - .WithDictionaryHandle() - .And - .WithHandle(typeof(SystemWebCacheHandleWrapper<>)) - .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) - .Build(); - - string useKey = Guid.NewGuid().ToString(); - - var result = await RunTest(cfg, useKey, null, true, false); - - result.Reason.Should().Be(CacheItemRemovedReason.Expired); - result.Level.Should().Be(2); - result.Key.Should().Be(useKey); - result.Region.Should().BeNull(); - } - } -#endif - - // exclusive inner class for parallel exec of this long running test - public class RedisSpecific : LongRunningEventTestBase - { - [Fact] + [Fact(Skip = "Garnet currently does not support keyspace notifications - cannot test...")] [Trait("category", "Redis")] [Trait("category", "Unreliable")] public async Task Events_Redis_ExpireTriggers() { - var cfg = new ConfigurationBuilder() - .WithRedisConfiguration("redis", "localhost, allowAdmin=true", 0, true) + var cfg = new CacheConfigurationBuilder() + .WithRedisConfiguration("redis", $"{TestManagers.RedisHost}:{TestManagers.RedisPort}, allowAdmin=true", 0, true) .WithJsonSerializer() .WithRedisCacheHandle("redis") .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); - string useRegion = "@_@23@_!!"; + var useKey = Guid.NewGuid().ToString(); + var useRegion = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, useRegion, true, true, false); result.Reason.Should().Be(CacheItemRemovedReason.Expired); @@ -427,21 +394,21 @@ public async Task Events_Redis_ExpireTriggers() result.Region.Should().Be(useRegion); } - [Fact] + [Fact(Skip = "Garnet currently does not support keyspace notifications - cannot test...")] [Trait("category", "Redis")] [Trait("category", "Unreliable")] public async Task Events_Redis_ExpireEvictsAbove() { - var cfg = new ConfigurationBuilder() - .WithDictionaryHandle() + var cfg = new CacheConfigurationBuilder() + .WithDictionaryHandle(options: new DictionaryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMilliseconds(10) }) .And - .WithRedisConfiguration("redis", "localhost, allowAdmin=true", 0, true) + .WithRedisConfiguration("redis", $"{TestManagers.RedisHost}:{TestManagers.RedisPort}, allowAdmin=true", 0, true) .WithJsonSerializer() .WithRedisCacheHandle("redis") .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(1)) .Build(); - string useKey = Guid.NewGuid().ToString(); + var useKey = Guid.NewGuid().ToString(); var result = await RunTest(cfg, useKey, null, true, false, false); @@ -451,6 +418,7 @@ public async Task Events_Redis_ExpireEvictsAbove() result.Region.Should().BeNull(); } } +#endif [Theory] [ClassData(typeof(TestCacheManagers))] @@ -475,7 +443,7 @@ public void Events_OnGet(T cache) result.Should().Be("something"); resultWithRegion.Should().BeNull("the key was not set with a region"); data.Calls.Should().Be(1, "we expect only one hit"); - data.Keys.ShouldAllBeEquivalentTo(new[] { key1 }, "we expect one call"); + data.Keys.Should().BeEquivalentTo(new[] { key1 }, "we expect one call"); data.Regions.Should().BeEmpty(); } } @@ -503,8 +471,8 @@ public void Events_OnGetWithRegion(T cache) resultWithoutRegion.Should().BeNull("the key was not set without a region"); result.Should().Be("something"); data.Calls.Should().Be(1, "we expect only one hit"); - data.Keys.ShouldAllBeEquivalentTo(new[] { key1 }); - data.Regions.ShouldAllBeEquivalentTo(new[] { region1 }); + data.Keys.Should().BeEquivalentTo(new[] { key1 }); + data.Regions.Should().BeEquivalentTo(new[] { region1 }); } } @@ -530,8 +498,8 @@ public void Events_OnGetMiss(T cache) result.Should().BeNull("the key was not set without region"); resultWithRegion.Should().BeNull("the key was not set with a region"); data.Calls.Should().Be(0, "we expect only one hit"); - data.Keys.ShouldAllBeEquivalentTo(new string[] { }, "we expect no calls"); - data.Regions.ShouldAllBeEquivalentTo(new string[] { }, "we expect no calls"); + data.Keys.Should().BeEquivalentTo(new string[] { }, "we expect no calls"); + data.Regions.Should().BeEquivalentTo(new string[] { }, "we expect no calls"); } } @@ -561,86 +529,113 @@ public void Events_OnGetManyHandles(T cache) // assert result.Should().Be("something"); data.Calls.Should().Be(4, "we expect 4 hits"); - data.Keys.ShouldAllBeEquivalentTo(Enumerable.Repeat(key1, 4), "we expect 4 hits"); - data.Regions.ShouldAllBeEquivalentTo(Enumerable.Repeat(region1, 4), "we expect 4 hits"); + data.Keys.Should().BeEquivalentTo(Enumerable.Repeat(key1, 4), "we expect 4 hits"); + data.Regions.Should().BeEquivalentTo(Enumerable.Repeat(region1, 4), "we expect 4 hits"); } } - [Fact] + [Fact(Skip = "Garnet currently does not support keyspace notifications - cannot test...")] [Trait("category", "Redis")] [Trait("category", "Unreliable")] public async Task Events_OnRemoveExternal_Redis_UpHandling() { var client = ConnectionMultiplexer.Connect("localhost"); - var config = new ConfigurationBuilder() - .WithDictionaryHandle() + var config = new CacheConfigurationBuilder() + .WithDictionaryHandle(options: new DictionaryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMilliseconds(10) }) .And .WithJsonSerializer() .WithRedisConfiguration("redis", client, enableKeyspaceNotifications: true) .WithRedisCacheHandle("redis") .Build(); - var key = Guid.NewGuid().ToString(); var onRemoveByHandleValid = false; + string key = null; var cache = new BaseCacheManager(config); - cache.OnRemoveByHandle += (s, args) => - { - if (args.Reason == CacheItemRemovedReason.ExternalDelete - && args.Key == key) - { - onRemoveByHandleValid = true; - } - }; - - cache.Add(key, 1234).Should().BeTrue(); - var x = cache.Get(key); - - client.GetDatabase(0).KeyDelete(key); - await Task.Delay(1000); + await RetryWithCondition( + 5, + async () => + { + key = Guid.NewGuid().ToString(); + await WaitUntilCancel((source) => + { + cache.OnRemoveByHandle += (s, args) => + { + // check if the direct KeyDelete with 'client' fires the event. This works only with keyspace notifications... + // if triggered, check the reason and validate the key + if (args.Reason == CacheItemRemovedReason.ExternalDelete + && args.Key == key) + { + // signal triggered for assertion + onRemoveByHandleValid = true; + // cancel the wait helper task... + source.Cancel(false); + } + }; + + cache.Add(key, 1234).Should().BeTrue(); + + var x = cache.Get(key); + + client.GetDatabase(0).KeyDelete(key); + }); + }, + () => onRemoveByHandleValid); onRemoveByHandleValid.Should().BeTrue("onRemoveByHandle Event should have been raised"); cache.CacheHandles.First().Get(key).Should().BeNull(); } - [Fact] + [Fact(Skip = "Garnet currently does not support keyspace notifications - cannot test...")] [Trait("category", "Redis")] [Trait("category", "Unreliable")] public async Task Events_OnRemoveExternal_Redis_NoneHandling() { var client = ConnectionMultiplexer.Connect("localhost"); - var config = new ConfigurationBuilder() + var config = new CacheConfigurationBuilder() .WithUpdateMode(CacheUpdateMode.None) - .WithDictionaryHandle() + .WithDictionaryHandle(options: new DictionaryCacheOptions() { ExpirationScanFrequency = TimeSpan.FromMilliseconds(10) }) .And .WithJsonSerializer() .WithRedisConfiguration("redis", client, enableKeyspaceNotifications: true) .WithRedisCacheHandle("redis") .Build(); - var key = Guid.NewGuid().ToString(); + string key = null; var onRemoveByHandleValid = false; var cache = new BaseCacheManager(config); - cache.OnRemoveByHandle += (s, args) => - { - if (args.Reason == CacheItemRemovedReason.ExternalDelete - && args.Key == key) - { - onRemoveByHandleValid = true; - } - }; - - cache.Add(key, 1234).Should().BeTrue(); - var x = cache.Get(key); - client.GetDatabase(0).KeyDelete(key); - - await Task.Delay(1000); + await RetryWithCondition( + 1, + async () => + { + key = Guid.NewGuid().ToString(); + _testOutputHelper.WriteLine("Try with " + key); + await WaitUntilCancel((source) => + { + cache.OnRemoveByHandle += (s, args) => + { + _testOutputHelper.WriteLine("event received " + args.Key); + if (args.Reason == CacheItemRemovedReason.ExternalDelete + && args.Key == key) + { + onRemoveByHandleValid = true; + source.Cancel(); + } + }; + + cache.Add(key, 1234).Should().BeTrue(); + var x = cache.Get(key); + + client.GetDatabase(0).KeyDelete(key); + }); + }, + () => onRemoveByHandleValid); onRemoveByHandleValid.Should().BeTrue("onRemoveByHandle Event should have been raised"); @@ -694,12 +689,12 @@ public void Events_OnRemoveMany(T cache) r4.Should().BeTrue($"{key2} {region2}" + cache.ToString()); data.Calls.Should().Be(8, $"we expect 8 hits for {key1} and {key2} \n-> keys: " + string.Join(", ", data.Keys)); - data.Keys.ShouldAllBeEquivalentTo( + data.Keys.Should().BeEquivalentTo( Enumerable.Repeat(key1, 4).Concat(Enumerable.Repeat(key2, 4)), cfg => cfg.WithStrictOrdering(), "we expect 8 hits"); - data.Regions.ShouldAllBeEquivalentTo( + data.Regions.Should().BeEquivalentTo( Enumerable.Repeat(region1, 4).Concat(Enumerable.Repeat(region2, 4)), cfg => cfg.WithStrictOrdering(), "we expect 8 hits"); @@ -751,14 +746,14 @@ public void Events_OnAddMany(T cache) // 3x true x 3 event handles = 9 calls data.Calls.Should().Be(9, "we expect 9 hits"); - data.Keys.ShouldAllBeEquivalentTo( + data.Keys.Should().BeEquivalentTo( Enumerable.Repeat(key1, 3) .Concat(Enumerable.Repeat(key2, 3)) .Concat(Enumerable.Repeat(key1, 3)), cfg => cfg.WithStrictOrdering(), "we expect 9 hits"); - data.Regions.ShouldAllBeEquivalentTo( + data.Regions.Should().BeEquivalentTo( Enumerable.Repeat(region1, 3) // 3 times region .Concat(Enumerable.Repeat(region2, 3)), // 3 times region2 cfg => cfg.WithStrictOrdering(), @@ -804,14 +799,14 @@ public void Events_OnPutMany(T cache) // assert 4x Put calls x 3 event handles = 12 calls data.Calls.Should().Be(12, $"we expect 12 hits for {key1} and {key2} \n-> keys: " + string.Join(", ", data.Keys)); - data.Keys.ShouldAllBeEquivalentTo( + data.Keys.Should().BeEquivalentTo( Enumerable.Repeat(key1, 3) .Concat(Enumerable.Repeat(key2, 3)) .Concat(Enumerable.Repeat(key1, 6)), cfg => cfg.WithStrictOrdering(), "we expect 12 hits"); - data.Regions.ShouldAllBeEquivalentTo( + data.Regions.Should().BeEquivalentTo( Enumerable.Repeat(region1, 3) // 3 times region .Concat(Enumerable.Repeat(region2, 3)) // 3 times region2 .Concat(Enumerable.Repeat(region1, 3)), // 3 times region @@ -860,12 +855,12 @@ public void Events_OnUpdate(T cache) // assert 4x Put calls x 3 event handles = 12 calls data.Calls.Should().Be(6, "we expect 6 hits"); - data.Keys.ShouldAllBeEquivalentTo( + data.Keys.Should().BeEquivalentTo( new string[] { key1, key2, key1, key1, key2, key1 }, cfg => cfg.WithStrictOrdering(), "we expect 3 adds and 3 updates in exact order"); - data.Regions.ShouldAllBeEquivalentTo( + data.Regions.Should().BeEquivalentTo( new string[] { region1, region2, region1, region2, }, cfg => cfg.WithStrictOrdering(), "we expect 4 region hits"); @@ -901,7 +896,7 @@ public void Events_OnClearRegion(T cache) cache.OnClear += (sender, args) => data.AddCall(); // this should not trigger cache.OnGet += (sender, args) => data.AddCall(args, key1, key2); // this should not trigger - // on remove now triggeres per cache handle eventually + // on remove now triggers per cache handle eventually cache.OnRemove += (sender, args) => data.AddCall(args, key1, key2); // this should not trigger cache.Put(key1, "something", region1); cache.Put(key2, "something", region2); @@ -915,7 +910,7 @@ public void Events_OnClearRegion(T cache) // assert 2x calls x 3 event handles = 6 calls data.Calls.Should().Be(6, $"we expect 6 hits for {key1} and {key2} \n-> keys: " + string.Join(", ", data.Keys)); - data.Regions.ShouldAllBeEquivalentTo( + data.Regions.Should().BeEquivalentTo( Enumerable.Repeat(region1, 3) // 3 times region .Concat(Enumerable.Repeat(region2, 3)), // 3 times region2 cfg => cfg.WithStrictOrdering(), @@ -1050,7 +1045,7 @@ public void Events_MockedCustomRemove_TestMultiLevelA() level = args.Level; }; - // tests if triggereing the first one really triggers the correct level + // tests if triggering the first one really triggers the correct level var handle = cache.CacheHandles.OfType().First(); handle.TestTrigger("key", null, CacheItemRemovedReason.Expired, null); @@ -1075,7 +1070,7 @@ public void Events_MockedCustomRemove_TestMultiLevelB() level = args.Level; }; - // tests if triggereing the last one really triggers the correct level + // tests if triggering the last one really triggers the correct level var handle = cache.CacheHandles.OfType().Last(); handle.TestTrigger("key", null, CacheItemRemovedReason.Expired, null); @@ -1146,9 +1141,10 @@ internal void AddCall() private class CustomRemoveEventTestHandle : BaseCacheHandle { - public CustomRemoveEventTestHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration) + public CustomRemoveEventTestHandle(ICacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory) : base(managerConfiguration, configuration) { + this.Logger = loggerFactory.CreateLogger(this.GetType()); } public void TestTrigger(string key, string region, CacheItemRemovedReason reason, object value) @@ -1164,13 +1160,7 @@ public override int Count } } - protected override ILogger Logger - { - get - { - return new NullLogger(); - } - } + protected override ILogger Logger { get; } public override void Clear() { @@ -1223,4 +1213,4 @@ protected override bool RemoveInternal(string key, string region) } } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheManagerExpirationTest.cs b/test/CacheManager.Tests/CacheManagerExpirationTest.cs index 5417b5eb..d78c85d9 100644 --- a/test/CacheManager.Tests/CacheManagerExpirationTest.cs +++ b/test/CacheManager.Tests/CacheManagerExpirationTest.cs @@ -1,17 +1,17 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Threading.Tasks; -using CacheManager.Core; -using FluentAssertions; -using Xunit; - -namespace CacheManager.Tests +namespace CacheManager.Tests { + using System; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + using System.Threading.Tasks; + using CacheManager.Core; + using FluentAssertions; + using Xunit; + [ExcludeFromCodeCoverage] - public class CacheManagerExpirationTest + public class CacheManagerExpirationTest : IClassFixture { - public class AllCaches + public class AllCaches : IClassFixture { [Trait("category", "Unreliable")] [Theory] @@ -21,13 +21,6 @@ public async Task Expiration_Sliding_DoesNotExpire_OnGet(T cache) { using (cache) { -#if MOCK_HTTPCONTEXT_ENABLED - if (cache.CacheHandles.OfType>().Any()) - { - // system.web caching doesn't support short sliding expiration. must be higher than 2000ms for some strange reason... - return; - } -#endif var timeout = 100; await TestSlidingExpiration( timeout, @@ -45,13 +38,6 @@ public async Task Expiration_Sliding_DoesNotExpire_OnUpdate(T cache) // see #50, update doesn't copy custom expire settings per item using (cache) { -#if MOCK_HTTPCONTEXT_ENABLED - if (cache.CacheHandles.OfType>().Any()) - { - // system.web caching doesn't support short sliding expiration. must be higher than 2000ms for some strange reason... - return; - } -#endif var timeout = 100; try { @@ -114,55 +100,6 @@ await TestSlidingExpiration( } } } -#if MEMCACHEDENABLED - - public class Memcached - { - [Fact] - [Trait("category", "Memcached")] - [Trait("category", "Unreliable")] - public async Task Memcached_Absolute_DoesExpire() - { - var timeout = 100; - var cache = CacheFactory.Build(settings => - { - settings - .WithMemcachedCacheHandle(MemcachedTests.Configuration) - .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromMilliseconds(timeout)); - }); - - using (cache) - { - await TestAbsoluteExpiration( - timeout, - (key) => cache.Add(key, "value"), - (key) => cache.Get(key)); - } - } - - [Fact] - [Trait("category", "Memcached")] - [Trait("category", "Unreliable")] - public async Task Memcached_Sliding_DoesExpire() - { - var timeout = 100; - var cache = CacheFactory.Build(settings => - { - settings - .WithMemcachedCacheHandle(MemcachedTests.Configuration) - .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromMilliseconds(timeout)); - }); - - using (cache) - { - await TestSlidingExpiration( - timeout, - (key) => cache.Add(key, "value"), - (key) => cache.Get(key)); - } - } - } -#endif public class MsMemory { @@ -201,8 +138,6 @@ await TestSlidingExpiration( } } -#if !NETCOREAPP - public class SysRuntime { [Fact] @@ -239,10 +174,8 @@ await TestSlidingExpiration( } } } - -#endif - - public class Redis +#if NET8_0_OR_GREATER + public class Redis : IClassFixture { [Fact] [Trait("category", "Redis")] @@ -345,6 +278,7 @@ await TestSlidingExpiration( } } } +#endif public class ExpireTests { @@ -561,12 +495,12 @@ public void Expiration_DoesNotAcceptExpirationInThePast(T cache) var expiration = TimeSpan.FromSeconds(-1); Action act = () => cache.Add(new CacheItem(key, "value", ExpirationMode.Sliding, expiration)); - act.ShouldThrow() + act.Should().Throw() .WithMessage("Expiration timeout must be greater than zero*"); } } - // Issue #57 - Verifying diggits will be ignored and stored as proper milliseconds value (integer). + // Issue #57 - Verifying digits will be ignored and stored as proper milliseconds value (integer). [Theory] [ClassData(typeof(TestCacheManagers))] public void Expiration_DoesNotBreak_OnVeryPreciseValue(T cache) @@ -578,7 +512,7 @@ public void Expiration_DoesNotBreak_OnVeryPreciseValue(T cache) var expiration = TimeSpan.FromTicks(TimeSpan.FromDays(20).Ticks); Action act = () => cache.Add(new CacheItem(key, "value", ExpirationMode.Sliding, expiration)); - act.ShouldNotThrow(); + act.Should().NotThrow(); var item = cache.GetCacheItem(key); item.Should().NotBeNull(); Math.Ceiling(item.ExpirationTimeout.TotalDays).Should().Be(Math.Ceiling(expiration.TotalDays)); @@ -586,7 +520,7 @@ public void Expiration_DoesNotBreak_OnVeryPreciseValue(T cache) } } - public class RemoveExpiration + public class RemoveExpiration : IClassFixture { // Issue #9 - item still expires [Theory] @@ -688,7 +622,7 @@ await TestRemoveExpiration( } } - public class RemoveExpirationExplicit + public class RemoveExpirationExplicit : IClassFixture { [Theory] [ClassData(typeof(TestCacheManagers))] @@ -753,7 +687,7 @@ await TestRemoveExpiration( } } - public class ValidateExpire + public class ValidateExpire : IClassFixture { [Theory] [ClassData(typeof(TestCacheManagers))] @@ -879,6 +813,7 @@ public void Expiration_Remove_ForKeyRegion_Validate(T cache) } } +#if NET8_0_OR_GREATER /* General expiration tests */ /// @@ -898,9 +833,10 @@ public void Redis_ExpirationTimeoutLimit() { Action act = () => cache.Add(new CacheItem(key, key, ExpirationMode.Absolute, timeout)); - act.ShouldThrow().WithMessage("*not supported*"); + act.Should().Throw().WithMessage("*not supported*"); } } +#endif // Related to #136 [Fact] @@ -1044,11 +980,9 @@ public void Configuration_AllowsZeroForDefaultExpiration() .WithDictionaryHandle() .WithExpiration(expirationMode, timeout)); - act.ShouldNotThrow(); + act.Should().NotThrow(); } -#if !NETCOREAPP - [Fact] public void BaseCacheHandle_ExpirationInherits_Issue_1() { @@ -1072,8 +1006,6 @@ public void BaseCacheHandle_ExpirationInherits_Issue_1() } } -#endif - private static void ValidateExistsInAllHandles(ICacheManager cache, string key) { foreach (var handle in cache.CacheHandles) diff --git a/test/CacheManager.Tests/CacheManagerRegionTests.cs b/test/CacheManager.Tests/CacheManagerRegionTests.cs index 6616ec63..ea02e28c 100644 --- a/test/CacheManager.Tests/CacheManagerRegionTests.cs +++ b/test/CacheManager.Tests/CacheManagerRegionTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Threading.Tasks; using CacheManager.Core; using FluentAssertions; using Xunit; @@ -13,7 +14,7 @@ namespace CacheManager.Tests /// removes an item from all handles defined. /// [ExcludeFromCodeCoverage] - public class CacheManagerRegionTests + public class CacheManagerRegionTests : IClassFixture { [Theory] [ClassData(typeof(TestCacheManagers))] @@ -87,7 +88,7 @@ public void CacheManager_Region_AddItems_UseDifferentKeys(T cache) [Theory] [ClassData(typeof(TestCacheManagers))] [Trait("category", "Unreliable")] - public void CacheManager_Region_ClearRegion(T cache) + public async Task CacheManager_Region_ClearRegion(T cache) where T : ICacheManager { using (cache) @@ -97,7 +98,7 @@ public void CacheManager_Region_ClearRegion(T cache) // act AddRegionData(cache, 20, 17, true, out keys, out regions); - + await Task.Delay(100); try { var clearedRegion = regions.ElementAt((int)Math.Ceiling(regions.Count / 2d)); @@ -273,7 +274,7 @@ private static void AddRegionData(ICache cache, int numItems, int numReg var key = sameKey ? sameKeyAllRegions + i : Guid.NewGuid().ToString(); var value = "Value in region " + r + ": " + i; - if (!cache.Add(key, value, region)) + if (!cache.Add(key: key, value: value, region: region)) { throw new InvalidOperationException("Adding key " + key + ":" + value + " didn't work. For cache\n" + cache.ToString()); } @@ -285,4 +286,4 @@ private static void AddRegionData(ICache cache, int numItems, int numReg } } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheManagerSimpleTests.cs b/test/CacheManager.Tests/CacheManagerSimpleTests.cs index ef0be44f..953f77ce 100644 --- a/test/CacheManager.Tests/CacheManagerSimpleTests.cs +++ b/test/CacheManager.Tests/CacheManagerSimpleTests.cs @@ -17,12 +17,25 @@ namespace CacheManager.Tests /// removes an item from all handles defined. /// [ExcludeFromCodeCoverage] - public class CacheManagerSimpleTests + public class CacheManagerSimpleTests : IClassFixture { private static object runLock = new object(); #region general + [Fact] + public void CacheManager_NullableTypes_ShouldNotAllowNulls() + { + var manager = new BaseCacheManager(CacheConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle())); + + DateTime? value = new Nullable(); + Assert.Null(value); + Action act = () => manager.Add(Guid.NewGuid().ToString(), value); + + act.Should().Throw() + .And.ParamName.Equals("value"); + } + [Fact] public void CacheManager_AddCacheItem_WithExpMode_ButWithoutTimeout() { @@ -33,7 +46,7 @@ public void CacheManager_AddCacheItem_WithExpMode_ButWithoutTimeout() // act Action act = () => cache.Add(new CacheItem(key, "something", ExpirationMode.Absolute, default(TimeSpan))); - act.ShouldThrow() + act.Should().Throw() .WithMessage("Expiration timeout must be greater than zero*"); } @@ -42,8 +55,8 @@ public void CacheManager_AddCacheItem_WithExpMode_ButWithoutTimeout() public void CacheManager_CtorA_NoConfig() { Action act = () => new BaseCacheManager(null); - act.ShouldThrow() - .WithMessage("*Parameter name: configuration"); + act.Should().Throw() + .And.ParamName.Equals("configuration"); } [Fact] @@ -51,7 +64,7 @@ public void CacheManager_CtorA_NoConfig() public void CacheManager_CtorA_ConfigNoName() { // name should be set from config and default is a Guid - var manager = new BaseCacheManager(ConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle())); + var manager = new BaseCacheManager(CacheConfigurationBuilder.BuildConfiguration(s => s.WithDictionaryHandle())); manager.Name.Should().NotBeNullOrWhiteSpace(); } @@ -61,7 +74,7 @@ public void CacheManager_CtorA_ConfigWithName() { // name should be implicitly set var manager = new BaseCacheManager( - ConfigurationBuilder.BuildConfiguration("newName", s => s.WithDictionaryHandle())); + CacheConfigurationBuilder.BuildConfiguration("newName", s => s.WithDictionaryHandle())); manager.Name.Should().Be("newName"); } @@ -83,14 +96,14 @@ public void CacheManager_Exists_InvalidKey(ICacheManager cache) Action actR = () => cache.Exists("key", null); // assert - act.ShouldThrow(cache.Configuration.ToString()) - .WithMessage("*Parameter name: key", cache.Configuration.ToString()); + act.Should().Throw(cache.Configuration.ToString()) + .And.ParamName.Equals("key"); - actB.ShouldThrow(cache.ToString()) - .WithMessage("*Parameter name: key", cache.Configuration.ToString()); + actB.Should().Throw(cache.ToString()) + .And.ParamName.Equals("key"); - actR.ShouldThrow(cache.ToString()) - .WithMessage("*Parameter name: region", cache.Configuration.ToString()); + actR.Should().Throw(cache.ToString()) + .And.ParamName.Equals("region"); } } @@ -182,11 +195,11 @@ public void CacheManager_Put_InvalidKey() Action actR = () => cache.Put(null, null, null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -204,11 +217,11 @@ public void CacheManager_Put_InvalidValue() Action actR = () => cache.Put("key", null, null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); - actR.ShouldThrow() - .WithMessage("*Parameter name: value"); + actR.Should().Throw() + .And.ParamName.Equals("value"); } } @@ -225,8 +238,8 @@ public void CacheManager_Put_InvalidCacheItem() Action act = () => cache.Put(null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: item"); + act.Should().Throw() + .And.ParamName.Equals("item"); } } @@ -243,8 +256,8 @@ public void CacheManager_Put_InvalidRegion() Action act = () => cache.Put("key", "value", null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -270,8 +283,8 @@ public void CacheManager_Put_CacheItem_Positive(T value) Action actRegion = () => cache.Put(itemRegion); // assert - act.ShouldNotThrow(); - actRegion.ShouldNotThrow(); + act.Should().NotThrow(); + actRegion.Should().NotThrow(); cache.Get(key).Should().Be(value); cache.Get(key, "region").Should().Be(value); } @@ -297,8 +310,8 @@ public void CacheManager_Put_KeyValue_Positive(T value) Action actRegion = () => cache.Put(key, value, "region"); // assert - act.ShouldNotThrow(); - actRegion.ShouldNotThrow(); + act.Should().NotThrow(); + actRegion.Should().NotThrow(); cache.Get(key).Should().Be(value); cache.Get(key, "region").Should().Be(value); } @@ -330,29 +343,29 @@ public void CacheManager_Update_InvalidKey() Action actTRU = () => cache.TryUpdate(null, null, null, 33, out val); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key*"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actR.Should().Throw() + .And.ParamName.Equals("key"); - actU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actU.Should().Throw() + .And.ParamName.Equals("key"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actRU.Should().Throw() + .And.ParamName.Equals("key"); - actT.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actT.Should().Throw() + .And.ParamName.Equals("key"); - actTR.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actTR.Should().Throw() + .And.ParamName.Equals("key"); - actTU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actTU.Should().Throw() + .And.ParamName.Equals("key"); - actTRU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actTRU.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -378,29 +391,29 @@ public void CacheManager_Update_InvalidUpdateFunc() Action actTRU = () => cache.TryUpdate("key", "r", null, 33, out val); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + act.Should().Throw() + .And.ParamName.Equals("updateValue"); - actR.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actR.Should().Throw() + .And.ParamName.Equals("updateValue"); - actU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actU.Should().Throw() + .And.ParamName.Equals("updateValue"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actRU.Should().Throw() + .And.ParamName.Equals("updateValue"); - actT.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actT.Should().Throw() + .And.ParamName.Equals("updateValue"); - actTR.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actTR.Should().Throw() + .And.ParamName.Equals("updateValue"); - actTU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actTU.Should().Throw() + .And.ParamName.Equals("updateValue"); - actTRU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actTRU.Should().Throw() + .And.ParamName.Equals("updateValue"); } } @@ -422,17 +435,17 @@ public void CacheManager_Update_InvalidRegion() Action actTRU = () => cache.TryUpdate("key", null, null, 33, out val); // assert - actR.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actR.Should().Throw() + .And.ParamName.Equals("region"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actRU.Should().Throw() + .And.ParamName.Equals("region"); - actTR.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actTR.Should().Throw() + .And.ParamName.Equals("region"); - actTRU.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actTRU.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -454,16 +467,16 @@ public void CacheManager_Update_InvalidConfig() Action actTRU = () => cache.TryUpdate("key", "region", a => a, -1, out val); // assert - act.ShouldThrow() + act.Should().Throw() .WithMessage("*retries must be greater than*"); - actR.ShouldThrow() + actR.Should().Throw() .WithMessage("*retries must be greater than*"); - actTU.ShouldThrow() + actTU.Should().Throw() .WithMessage("*retries must be greater than*"); - actTRU.ShouldThrow() + actTRU.Should().Throw() .WithMessage("*retries must be greater than*"); } } @@ -487,8 +500,8 @@ public void CacheManager_Update_ItemNotAdded(T cache) Func act2R = () => cache.TryUpdate(key, "region", item => item, out value); // assert - act.ShouldThrow("*failed*"); - actR.ShouldThrow("*failed*"); + act.Should().Throw("*failed*"); + actR.Should().Throw("*failed*"); act2().Should().BeFalse("Item has not been added to the cache"); act2R().Should().BeFalse("Item has not been added to the cache"); } @@ -521,10 +534,10 @@ public void CacheManager_Update_ValueFactoryReturnsNull(T cache) Func actTRU = () => cache.TryUpdate(key, region, (v) => null, 33, out val); // assert - act.ShouldThrow().WithMessage("*value factory returned null*"); - actR.ShouldThrow().WithMessage("*value factory returned null*"); - actU.ShouldThrow().WithMessage("*value factory returned null*"); - actRU.ShouldThrow().WithMessage("*value factory returned null*"); + act.Should().Throw().WithMessage("*value factory returned null*"); + actR.Should().Throw().WithMessage("*value factory returned null*"); + actU.Should().Throw().WithMessage("*value factory returned null*"); + actRU.Should().Throw().WithMessage("*value factory returned null*"); actT().Should().BeFalse(); actTR().Should().BeFalse(); @@ -587,17 +600,17 @@ public void CacheManager_AddOrUpdate_InvalidKey() Action actRU = () => cache.AddOrUpdate(null, "r", null, null, 33); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key*"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actR.Should().Throw() + .And.ParamName.Equals("key"); - actU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actU.Should().Throw() + .And.ParamName.Equals("key"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: key*"); + actRU.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -619,17 +632,17 @@ public void CacheManager_AddOrUpdate_InvalidUpdateFunc() Action actIU = () => cache.AddOrUpdate(new CacheItem("k", "v"), null, 1); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + act.Should().Throw() + .And.ParamName.Equals("updateValue"); - actR.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actR.Should().Throw() + .And.ParamName.Equals("updateValue"); - actU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actU.Should().Throw() + .And.ParamName.Equals("updateValue"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: updateValue*"); + actRU.Should().Throw() + .And.ParamName.Equals("updateValue"); } } @@ -647,11 +660,11 @@ public void CacheManager_AddOrUpdate_InvalidRegion() Action actRU = () => cache.AddOrUpdate("key", null, "value", a => a, 1); // assert - actR.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actR.Should().Throw() + .And.ParamName.Equals("region"); - actRU.ShouldThrow() - .WithMessage("*Parameter name: region*"); + actRU.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -670,13 +683,13 @@ public void CacheManager_AddOrUpdate_InvalidConfig() Action actIU = () => cache.AddOrUpdate(new CacheItem("k", "v"), (o) => o, -1); // assert - actU.ShouldThrow() + actU.Should().Throw() .WithMessage("*retries must be greater than*"); - actRU.ShouldThrow() + actRU.Should().Throw() .WithMessage("*retries must be greater than*"); - actIU.ShouldThrow() + actIU.Should().Throw() .WithMessage("*retries must be greater than*"); } } @@ -732,6 +745,33 @@ public void CacheManager_AddOrUpdate_Update_Simple(T cache) #region get or add + // validates #268 + [Fact] + public void CacheManager_GetOrAdd_Concurrent_SameKey() + { + var rnd = new Random(); + var cache = CacheFactory.Build(settings => settings + .WithMicrosoftMemoryCacheHandle()); + + CacheItem GenerateValue(string key) + { + Thread.Sleep(400); + return new CacheItem(key, $"{rnd.Next()} {DateTime.Now.ToLongTimeString()} : HALLO WORLD FOR " + key); + } + + object v1 = null; + object v2 = null; + + const string sameKey = "Test 1 "; + + Parallel.Invoke( + () => { v1 = cache.GetOrAddCacheItem(sameKey, GenerateValue).Value; }, + () => { v2 = cache.GetOrAddCacheItem(sameKey, GenerateValue).Value; } + ); + + Assert.True(v1 == v2); // FAILS + } + [Fact] [ReplaceCulture] public void CacheManager_GetOrAdd_InvalidKey() @@ -746,27 +786,27 @@ public void CacheManager_GetOrAdd_InvalidKey() Action actB = () => cache.GetOrAdd(null, "region", "value"); Action actC = () => cache.GetOrAdd(null, (k) => "value"); Action actD = () => cache.GetOrAdd(null, "region", (k, r) => "value"); - Action actE = () => cache.GetOrAdd(null, (k) => new CacheItem(k, "value")); - Action actF = () => cache.GetOrAdd(null, "region", (k, r) => new CacheItem(k, "value")); + Action actE = () => cache.GetOrAddCacheItem(null, (k) => new CacheItem(k, "value")); + Action actF = () => cache.GetOrAddCacheItem(null, "region", (k, r) => new CacheItem(k, "value")); // assert - actA.ShouldThrow() - .WithMessage("*key*"); + actA.Should().Throw() + .And.ParamName.Equals("key"); - actB.ShouldThrow() - .WithMessage("*key*"); + actB.Should().Throw() + .And.ParamName.Equals("key"); - actC.ShouldThrow() - .WithMessage("*key*"); + actC.Should().Throw() + .And.ParamName.Equals("key"); - actD.ShouldThrow() - .WithMessage("*key*"); + actD.Should().Throw() + .And.ParamName.Equals("key"); - actE.ShouldThrow() - .WithMessage("*key*"); + actE.Should().Throw() + .And.ParamName.Equals("key"); - actF.ShouldThrow() - .WithMessage("*key*"); + actF.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -787,17 +827,17 @@ public void CacheManager_TryGetOrAdd_InvalidKey() Action actF = () => cache.TryGetOrAdd(null, "region", (k, r) => new CacheItem(k, "value"), out val); // assert - actC.ShouldThrow() - .WithMessage("*key*"); + actC.Should().Throw() + .And.ParamName.Equals("key"); - actD.ShouldThrow() - .WithMessage("*key*"); + actD.Should().Throw() + .And.ParamName.Equals("key"); - actE.ShouldThrow() - .WithMessage("*key*"); + actE.Should().Throw() + .And.ParamName.Equals("key"); - actF.ShouldThrow() - .WithMessage("*key*"); + actF.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -815,11 +855,11 @@ public void CacheManager_GetOrAdd_InvalidRegion() Action actB = () => cache.GetOrAdd("key", null, (k, r) => "value"); // assert - actA.ShouldThrow() - .WithMessage("*region*"); + actA.Should().Throw() + .And.ParamName.Equals("region"); - actB.ShouldThrow() - .WithMessage("*region*"); + actB.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -837,8 +877,8 @@ public void CacheManager_TryGetOrAdd_InvalidRegion() Action actB = () => cache.TryGetOrAdd("key", null, (k, r) => "value", out val); // assert - actB.ShouldThrow() - .WithMessage("*region*"); + actB.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -852,15 +892,15 @@ public void CacheManager_GetOrAdd_InvalidFactory() })) { // arrange act - Action actA = () => cache.GetOrAdd("key", null); - Action actB = () => cache.GetOrAdd("key", "region", null); + Action actA = () => cache.GetOrAddCacheItem("key", null); + Action actB = () => cache.GetOrAddCacheItem("key", "region", null); // assert - actA.ShouldThrow() - .WithMessage("*valueFactory*"); + actA.Should().Throw() + .And.ParamName.Equals("valueFactory"); - actB.ShouldThrow() - .WithMessage("*valueFactory*"); + actB.Should().Throw() + .And.ParamName.Equals("valueFactory"); } } @@ -879,11 +919,11 @@ public void CacheManager_TryGetOrAdd_InvalidFactory() Action actB = () => cache.TryGetOrAdd("key", "region", null, out val); // assert - actA.ShouldThrow() - .WithMessage("*valueFactory*"); + actA.Should().Throw() + .And.ParamName.Equals("valueFactory"); - actB.ShouldThrow() - .WithMessage("*valueFactory*"); + actB.Should().Throw() + .And.ParamName.Equals("valueFactory"); } } @@ -906,8 +946,8 @@ public void CacheManager_GetOrAdd_SimpleAdd(T cache) cache.GetOrAdd(key, region, val); cache.GetOrAdd(keyF, (k) => val); cache.GetOrAdd(keyF, region, (k, r) => val); - cache.GetOrAdd(keyG, (k) => new CacheItem(keyG, val)); - cache.GetOrAdd(keyG, region, (k, r) => new CacheItem(keyG, region, val, ExpirationMode.Absolute, TimeSpan.FromMinutes(42))); + cache.GetOrAddCacheItem(keyG, (k) => new CacheItem(keyG, val)); + cache.GetOrAddCacheItem(keyG, region, (k, r) => new CacheItem(keyG, region, val, ExpirationMode.Absolute, TimeSpan.FromMinutes(42))); // assert cache[key].Should().Be(val); @@ -943,9 +983,9 @@ public void CacheManager_TryGetOrAdd_SimpleAdd(T cache) Func actA = () => cache.TryGetOrAdd(key, k => val, out valueA); Func actB = () => cache.TryGetOrAdd(key, region, (k, r) => val, out valueB); var valC = new CacheItem(key2, val); - Func actC = () => cache.TryGetOrAdd(key2, k => valC, out valueC); + Func actC = () => cache.TryGetOrAddCacheItem(key2, k => valC, out valueC); var valD = new CacheItem(key2, region, val, ExpirationMode.Absolute, TimeSpan.FromMinutes(42)); - Func actD = () => cache.TryGetOrAdd(key2, region, (k, r) => valD, out valueD); + Func actD = () => cache.TryGetOrAddCacheItem(key2, region, (k, r) => valD, out valueD); // assert actA().Should().BeTrue(); @@ -977,10 +1017,10 @@ public void CacheManager_GetOrAdd_FactoryReturnsNull(T cache) using (cache) { // act - Action act = () => cache.GetOrAdd(key, (k) => null); + Action act = () => cache.GetOrAddCacheItem(key, (k) => null); // assert - act.ShouldThrow("added"); + act.Should().Throw("added"); } } @@ -998,7 +1038,7 @@ public void CacheManager_TryGetOrAdd_FactoryReturnsNull(T cache) object val = null; CacheItem val2 = null; Func act = () => cache.TryGetOrAdd(key, (k) => null, out val); - Func actB = () => cache.TryGetOrAdd(key, (k) => null, out val2); + Func actB = () => cache.TryGetOrAddCacheItem(key, (k) => null, out val2); // assert act().Should().BeFalse(); @@ -1022,7 +1062,7 @@ public void CacheManager_GetOrAdd_AddNull(T cache) Action act = () => cache.GetOrAdd(key, (object)null); // assert - act.ShouldThrow("added"); + act.Should().Throw("added"); } } @@ -1049,8 +1089,8 @@ public void CacheManager_GetOrAdd_SimpleGet(T cache) // act var result = cache.GetOrAdd(key, val); var resultB = cache.GetOrAdd(key, region, val); - var resultC = cache.GetOrAdd(key, (k) => new CacheItem(key, val)); - var resultD = cache.GetOrAdd(key, region, (k, r) => new CacheItem(key, val)); + var resultC = cache.GetOrAddCacheItem(key, (k) => new CacheItem(key, val)); + var resultD = cache.GetOrAddCacheItem(key, region, (k, r) => new CacheItem(key, val)); Action act = () => cache.GetOrAdd(keyF, add); Action actB = () => cache.GetOrAdd(keyF, region, addRegion); @@ -1059,8 +1099,8 @@ public void CacheManager_GetOrAdd_SimpleGet(T cache) resultB.Should().Be(val); resultC.Value.Should().Be(val); resultD.Value.Should().Be(val); - act.ShouldNotThrow(); - actB.ShouldNotThrow(); + act.Should().NotThrow(); + actB.Should().NotThrow(); } } @@ -1120,7 +1160,7 @@ public async Task CacheManager_GetOrAdd_ForceRace(T cache) Func> action = () => { var tries = 0; - var created = cache.GetOrAdd(key, (k) => + var created = cache.GetOrAddCacheItem(key, (k) => { tries++; Interlocked.Increment(ref counter); @@ -1171,7 +1211,7 @@ public async Task CacheManager_TryGetOrAdd_ForceRace(T cache) { var tries = 0; CacheItem result = null; - while (!cache.TryGetOrAdd( + while (!cache.TryGetOrAddCacheItem( key, (k) => { tries++; @@ -1226,11 +1266,11 @@ public void CacheManager_Add_InvalidKey() Action actR = () => cache.Add(null, null, null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1250,11 +1290,11 @@ public void CacheManager_Add_InvalidValue() Action actR = () => cache.Add("key", null, "region"); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: value"); + act.Should().Throw() + .And.ParamName.Equals("value"); - actR.ShouldThrow() - .WithMessage("*Parameter name: value"); + actR.Should().Throw() + .And.ParamName.Equals("value"); } } @@ -1273,8 +1313,8 @@ public void CacheManager_Add_InvalidRegion() Action actR = () => cache.Add("key", "value", null); // assert - actR.ShouldThrow() - .WithMessage("*Parameter name: region"); + actR.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1292,8 +1332,8 @@ public void CacheManager_Add_InvalidCacheItem() Action act = () => cache.Add(null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: item"); + act.Should().Throw() + .And.ParamName.Equals("item"); } } @@ -1317,7 +1357,7 @@ public void CacheManager_Add_CacheItem_Positive(T value) Action act = () => cache.Add(item); // assert - act.ShouldNotThrow(); + act.Should().NotThrow(); cache.Get(key).Should().Be(value); } } @@ -1341,7 +1381,7 @@ public void CacheManager_Add_KeyValue_Positive(T value) Action act = () => cache.Add(key, value); // assert - act.ShouldNotThrow(); + act.Should().NotThrow(); cache.Get(key).Should().Be(value); } } @@ -1365,11 +1405,11 @@ public void CacheManager_Get_InvalidKey() Action actR = () => cache.Get(null, "region"); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1387,8 +1427,8 @@ public void CacheManager_Get_InvalidRegion() Action act = () => cache.Get("key", null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1407,11 +1447,11 @@ public void CacheManager_GetItem_InvalidKey() Action actR = () => cache.GetCacheItem(null, "region"); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1429,8 +1469,8 @@ public void CacheManager_GetItem_InvalidRegion() Action act = () => cache.GetCacheItem("key", null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1449,11 +1489,11 @@ public void CacheManager_GetT_InvalidKey() Action actR = () => cache.Get(null, "region"); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1471,8 +1511,8 @@ public void CacheManager_GetT_InvalidRegion() Action act = () => cache.Get("key", null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1542,7 +1582,7 @@ public void CacheManager_GetCacheItem_Positive() actAdd().Should().BeTrue("the cache should add the key/value"); actGet().Should() .NotBeNull("object was added") - .And.ShouldBeEquivalentTo(new { Key = key, Value = value }, p => p.ExcludingMissingMembers()); + .And.Should().BeEquivalentTo(new { Key = key, Value = value }, p => p.ExcludingMissingMembers()); } } @@ -1565,11 +1605,11 @@ public void CacheManager_Remove_InvalidKey() Action actR = () => cache.Remove(null, "region"); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1587,8 +1627,8 @@ public void CacheManager_Remove_InvalidRegion() Action act = () => cache.Remove("key", null); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1608,8 +1648,8 @@ public void CacheManager_Remove_KeyEmpty() Action act = () => cache.Remove(key); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1629,8 +1669,8 @@ public void CacheManager_Remove_KeyWhiteSpace() Action act = () => cache.Remove(key); // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1701,11 +1741,11 @@ public void CacheManager_Index_InvalidKey() Action actR = () => result = cache[key, "region"]; // assert - act.ShouldThrow() - .WithMessage("*Parameter name: key"); + act.Should().Throw() + .And.ParamName.Equals("key"); - actR.ShouldThrow() - .WithMessage("*Parameter name: key"); + actR.Should().Throw() + .And.ParamName.Equals("key"); } } @@ -1724,8 +1764,8 @@ public void CacheManager_Index_Key_RegionEmpty() Action act = () => result = cache["key", string.Empty]; // assert - act.ShouldThrow() - .WithMessage("*Parameter name: region"); + act.Should().Throw() + .And.ParamName.Equals("region"); } } @@ -1761,7 +1801,7 @@ public void CacheManager_NoCacheHandles() Action act = () => new BaseCacheManager(new CacheManagerConfiguration() { MaxRetries = 1000 }); // assert - act.ShouldThrow().WithMessage("*no cache handles*"); + act.Should().Throw().WithMessage("*no cache handles*"); } #endregion testing empty handle list @@ -1806,24 +1846,24 @@ public void CacheManager_CastGet(T cache) // act PopulateCache(cache, keys, values, 1); - string strSomething = cache.Get(keys[0]); - int someNumber = cache.Get(keys[1]); - float someFloating = cache.Get(keys[2]); - double someDoubling = cache.Get(keys[3]); - long someLonging = cache.Get(keys[4]); - bool someBooling = cache.Get(keys[5]); - ComplexType obj = cache.Get(keys[6]); + object strSomething = cache.Get(keys[0]); + object someNumber = cache.Get(keys[1]); + object someFloating = cache.Get(keys[2]); + object someDoubling = cache.Get(keys[3]); + object someLonging = cache.Get(keys[4]); + object someBooling = cache.Get(keys[5]); + object obj = cache.Get(keys[6]); object someObject = cache.Get("nonexistent"); // assert ValidateCacheValues(cache, keys, values); - strSomething.ShouldBeEquivalentTo(values[0]); - someNumber.ShouldBeEquivalentTo(values[1]); - someFloating.ShouldBeEquivalentTo(values[2]); - someDoubling.ShouldBeEquivalentTo(values[3]); - someLonging.ShouldBeEquivalentTo(values[4]); - someBooling.ShouldBeEquivalentTo(values[5]); - obj.ShouldBeEquivalentTo(values[6]); + strSomething.Should().BeEquivalentTo(values[0]); + someNumber.Should().BeEquivalentTo(values[1]); + someFloating.Should().BeEquivalentTo(values[2]); + someDoubling.Should().BeEquivalentTo(values[3]); + someLonging.Should().BeEquivalentTo(values[4]); + someBooling.Should().BeEquivalentTo(values[5]); + obj.Should().BeEquivalentTo(values[6]); someObject.Should().Be(null); } } @@ -1868,7 +1908,7 @@ public void CacheManager_SimplePut(T cache) }; // assert - actPut.ShouldNotThrow(); + actPut.Should().NotThrow(); ValidateCacheValues(cache, keys, values); } } @@ -1891,7 +1931,7 @@ public void CacheManager_SimpleAdd(T cache) }; // assert - actSet.ShouldNotThrow(); + actSet.Should().NotThrow(); ValidateCacheValues(cache, keys, values); } } @@ -1914,7 +1954,7 @@ public void CacheManager_SimpleIndexPut(T cache) }; // assert - actSet.ShouldNotThrow(); + actSet.Should().NotThrow(); ValidateCacheValues(cache, keys, values); } } @@ -2002,7 +2042,7 @@ public void CacheManager_SimpleUpdate(T cache) }; // assert - actSet.ShouldNotThrow(); + actSet.Should().NotThrow(); ValidateCacheValues(cache, keys, newValues); } } @@ -2096,10 +2136,7 @@ private static void ValidateCacheValues(ICacheManager cache, IList }).ToList(); } -#if !NETCOREAPP - [Serializable] -#endif [ProtoBuf.ProtoContract] [Bond.Schema] public class ComplexType @@ -2140,4 +2177,4 @@ public override bool Equals(object obj) public override int GetHashCode() => base.GetHashCode(); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/CacheManagerStatsTest.cs b/test/CacheManager.Tests/CacheManagerStatsTest.cs index b6f6696d..0a2c73be 100644 --- a/test/CacheManager.Tests/CacheManagerStatsTest.cs +++ b/test/CacheManager.Tests/CacheManagerStatsTest.cs @@ -11,7 +11,7 @@ namespace CacheManager.Tests { [ExcludeFromCodeCoverage] - public class CacheManagerStatsTest + public class CacheManagerStatsTest : IClassFixture { [Theory] [ClassData(typeof(TestCacheManagers))] @@ -51,16 +51,16 @@ public void CacheManager_Stats_AddGet(T cache) var handleCount = cache.CacheHandles.Count(); if (handleCount > 1) { - addCalls.Last().Should().Be(1); - addCalls.Take(handleCount - 1).ShouldAllBeEquivalentTo(0); + addCalls.Last().Should().Be(1L); + addCalls.Take(handleCount - 1).Should().AllBeEquivalentTo(0L); } else { - addCalls.ShouldAllBeEquivalentTo(1); + addCalls.Should().AllBeEquivalentTo(1L); } - items.ShouldAllBeEquivalentTo( - Enumerable.Repeat(0, cache.CacheHandles.Count() - 1).Concat(new[] { 1 })); + items.Should().BeEquivalentTo( + Enumerable.Repeat(0L, cache.CacheHandles.Count() - 1).Concat(new[] { 1L })); } } @@ -84,8 +84,8 @@ public void CacheManager_Stats_Clear() cache.Clear(); // assert all handles should have 2 clear increases. - clears.ShouldAllBeEquivalentTo( - Enumerable.Repeat(2, cache.CacheHandles.Count())); + clears.Should().BeEquivalentTo( + Enumerable.Repeat(2L, cache.CacheHandles.Count())); } } @@ -110,8 +110,8 @@ public void CacheManager_Stats_ClearRegion() cache.ClearRegion(Guid.NewGuid().ToString()); // assert all handles should have 2 clearRegion increases. - clears.ShouldAllBeEquivalentTo( - Enumerable.Repeat(2, cache.CacheHandles.Count())); + clears.Should().BeEquivalentTo( + Enumerable.Repeat(2L, cache.CacheHandles.Count())); } } @@ -135,8 +135,8 @@ public void CacheManager_Stats_Put(T cache) cache.Put(key2, "something", region); // assert all handles should have 2 clearRegion increases. - puts.ShouldAllBeEquivalentTo( - Enumerable.Repeat(3, cache.CacheHandles.Count())); + puts.Should().BeEquivalentTo( + Enumerable.Repeat(3L, cache.CacheHandles.Count())); } } @@ -161,9 +161,9 @@ public void CacheManager_Stats_Update(T cache) cache.Update(key1, v => "somethingelse"); cache.Update(key2, v => "somethingelse"); - // assert could be more than 2 adds.ShouldAllBeEquivalentTo( Enumerable.Repeat(0, - // cache.CacheHandles.Count)); gets.ShouldAllBeEquivalentTo( Enumerable.Repeat(2, - // cache.CacheHandles.Count)); hits.ShouldAllBeEquivalentTo( Enumerable.Repeat(2, cache.CacheHandles.Count)); + // assert could be more than 2 adds.Should().AllBeEquivalentTo( Enumerable.Repeat(0, + // cache.CacheHandles.Count)); gets.Should().AllBeEquivalentTo( Enumerable.Repeat(2, + // cache.CacheHandles.Count)); hits.Should().AllBeEquivalentTo( Enumerable.Repeat(2, cache.CacheHandles.Count)); } } @@ -205,7 +205,7 @@ public void CacheManager_Stats_Remove(T cache) if (adds.Count() > 1) { adds.Last().Should().Be(5); - adds.Take(adds.Count() - 1).ShouldAllBeEquivalentTo(0); + adds.Take(adds.Count() - 1).Should().AllBeEquivalentTo(0); } else { @@ -244,8 +244,8 @@ await ThreadTestHelper.RunAsync( await Task.Delay(20); putCounter.Should().Be(threads * iterations); - puts.ShouldAllBeEquivalentTo( - Enumerable.Repeat(threads * iterations, cache.CacheHandles.Count())); + puts.Should().BeEquivalentTo( + Enumerable.Repeat((long)(threads * iterations), cache.CacheHandles.Count())); } } -} \ No newline at end of file +} diff --git a/test/CacheManager.Tests/Configuration/configuration.ExpireTest.config b/test/CacheManager.Tests/Configuration/configuration.ExpireTest.config index 996a3dab..ad1f4fb9 100644 --- a/test/CacheManager.Tests/Configuration/configuration.ExpireTest.config +++ b/test/CacheManager.Tests/Configuration/configuration.ExpireTest.config @@ -6,7 +6,7 @@ - + @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnablePerfCounters.config b/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnablePerfCounters.config index 327598c1..3036fd4b 100644 --- a/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnablePerfCounters.config +++ b/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnablePerfCounters.config @@ -6,7 +6,7 @@ - + @@ -18,4 +18,4 @@ defaultExpirationMode="Sliding" defaultTimeout="20m" /> - \ No newline at end of file + diff --git a/test/CacheManager.Tests/Configuration/configuration.valid.allFeatures.config b/test/CacheManager.Tests/Configuration/configuration.valid.allFeatures.config index ae8ddd8e..f685b8e2 100644 --- a/test/CacheManager.Tests/Configuration/configuration.valid.allFeatures.config +++ b/test/CacheManager.Tests/Configuration/configuration.valid.allFeatures.config @@ -21,12 +21,12 @@ - + - + - -
- - -
- @@ -17,11 +10,11 @@ - + - + @@ -35,15 +28,27 @@ - + - + - + @@ -54,28 +59,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -90,4 +73,4 @@ - \ No newline at end of file + diff --git a/test/CacheManager.Tests/testhost.dll.config b/test/CacheManager.Tests/testhost.dll.config new file mode 100644 index 00000000..0e7a3317 --- /dev/null +++ b/test/CacheManager.Tests/testhost.dll.config @@ -0,0 +1,80 @@ + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/CacheManager.Tests/testhost.x86.dll.config b/test/CacheManager.Tests/testhost.x86.dll.config new file mode 100644 index 00000000..0e7a3317 --- /dev/null +++ b/test/CacheManager.Tests/testhost.x86.dll.config @@ -0,0 +1,80 @@ + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/CacheManager.Tests/xunit.runner.json b/test/CacheManager.Tests/xunit.runner.json index a863fd63..bf1c2488 100644 --- a/test/CacheManager.Tests/xunit.runner.json +++ b/test/CacheManager.Tests/xunit.runner.json @@ -1,8 +1,6 @@ { "parallelizeTestCollections": true, "methodDisplay": "method", - "preEnumerateTheories": false, - "diagnosticMessages": false, - "longRunningTestSeconds": 5, - "maxParallelThreads": 2 + "preEnumerateTheories": true, + "diagnosticMessages": false } diff --git a/tools/CacheManagerCfg.xsd b/tools/CacheManagerCfg.xsd index 82102c5e..5cd8f9e0 100644 --- a/tools/CacheManagerCfg.xsd +++ b/tools/CacheManagerCfg.xsd @@ -6,73 +6,71 @@ xmlns:mstns="http://cachemanager.michaco.net/schemas/CacheManagerCfg.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/cacheManager.json b/tools/cacheManager.json index 9b8fbebc..b9f521ed 100644 --- a/tools/cacheManager.json +++ b/tools/cacheManager.json @@ -95,8 +95,8 @@ "properties": { "knownType": { "type": "string", - "enum": [ "Binary", "Json", "Protobuf", "GzJson", "BondCompactBinary", "BondFastBinary", "BondSimpleJson" ], - "description": "Define a known serializer type instead of setting 'serializerType'. The respective library has to be installed. The default 'binary' might not be available on all platforms." + "enum": [ "Json", "Protobuf", "GzJson", "BondCompactBinary", "BondFastBinary", "BondSimpleJson" ], + "description": "Define a known serializer type instead of setting 'serializerType'. The respective library has to be installed." } }, "additionalProperties": false @@ -129,7 +129,7 @@ "properties": { "knownType": { "type": "string", - "enum": [ "Redis", "Couchbase", "Memcached" ], + "enum": [ "Redis" ], "description": "Shortcut to the known cache handle types. This requires the corresponding packages are installed." }, "key": { @@ -180,10 +180,6 @@ "type": "boolean", "description": "Determines if the cache handle is the backplane's source. (optional; if no backplane is defined, this can stay empty. If a backplane is defined, at least one handle must be flagged.)" }, - "enablePerformanceCounters": { - "type": "boolean", - "description": "Defines if windows performance counters should be enabled or not." - }, "enableStatistics": { "type": "boolean", "description": "Defines if statistics should be captured." @@ -205,7 +201,7 @@ }, "updateMode": { "type": "string", - "enum": [ "None", "Full", "Up" ], + "enum": [ "None", "Up" ], "description": "The update mode (default is Up).", "default": "Up" }, @@ -392,4 +388,4 @@ } }, "required": [ "cacheManagers" ] -} \ No newline at end of file +} diff --git a/tools/common.props b/tools/common.props index bee0e01e..2099bf24 100644 --- a/tools/common.props +++ b/tools/common.props @@ -2,32 +2,33 @@ - Copyright (c) 2017 MichaConrad - MichaConrad + Copyright (c) 2025 Michael Conrad + MichaConrad + CacheManager.NET + + icon.png + README.md + Apache-2.0 + https://cachemanager.michaco.net + http://cachemanager.michaco.net + true + true + true true - http://cachemanager.michaco.net/favicon-128.png - http://cachemanager.michaco.net - https://github.com/MichaCo/CacheManager/blob/master/LICENSE - git - https://github.com/MichaCo/CacheManager - - CacheManager.NET + true + snupkg + portable $(MSBuildThisFileDirectory)key.snk true true + $(VersionSuffix)-$(BuildNumber) - - - - \ No newline at end of file + + + + diff --git a/tools/icon.png b/tools/icon.png new file mode 100644 index 00000000..eb9e92ea Binary files /dev/null and b/tools/icon.png differ diff --git a/tools/memcached-amd64/RunMemcachd.bat b/tools/memcached-amd64/RunMemcachd.bat deleted file mode 100644 index cb32bdc8..00000000 --- a/tools/memcached-amd64/RunMemcachd.bat +++ /dev/null @@ -1,2 +0,0 @@ -:: requires linux subsystem for windows -bash run_memcached.sh \ No newline at end of file diff --git a/tools/memcached-amd64/StopMemcached.bat b/tools/memcached-amd64/StopMemcached.bat deleted file mode 100644 index 77f33278..00000000 --- a/tools/memcached-amd64/StopMemcached.bat +++ /dev/null @@ -1,2 +0,0 @@ -:: requires linux subsystem for windows -bash stop_memcached.sh \ No newline at end of file diff --git a/tools/memcached-amd64/run_memcached.sh b/tools/memcached-amd64/run_memcached.sh deleted file mode 100644 index 57487981..00000000 --- a/tools/memcached-amd64/run_memcached.sh +++ /dev/null @@ -1,14 +0,0 @@ -exists=$(whereis memcached | grep -c "bin/memcached") -if [[ $exists == 0 ]]; then - echo "installing memcached..." - sudo apt-get install memcached -y -fi - -status=$(service memcached status | grep -c "is running") -if [[ $status == 0 ]]; then - sudo service memcached start -else - echo "Memcached already running!" -fi - -service memcached status \ No newline at end of file diff --git a/tools/memcached-amd64/stop_memcached.sh b/tools/memcached-amd64/stop_memcached.sh deleted file mode 100644 index 78c54eb0..00000000 --- a/tools/memcached-amd64/stop_memcached.sh +++ /dev/null @@ -1,6 +0,0 @@ -sudo service memcached stop - -status=$(service memcached status | grep -c "is running") -if [[ $status == 0 ]]; then - echo "Service stopped" -fi \ No newline at end of file diff --git a/tools/redis/Cluster/7000/nodes.conf b/tools/redis/Cluster/7000/nodes.conf deleted file mode 100644 index 62ecbe30..00000000 --- a/tools/redis/Cluster/7000/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 slave c2deb32666652c94499cedc01f4a5849f1f03873 0 1489011302227 6 connected -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 slave 76fc6991abd39a80e72b96362256220294454ce1 0 1489011301718 5 connected -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 1489011303765 4 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 master - 0 1489011303245 3 connected 10923-16383 -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460 -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 master - 0 1489011303765 2 connected 5461-10922 -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7000/redis.conf b/tools/redis/Cluster/7000/redis.conf deleted file mode 100644 index 56465554..00000000 --- a/tools/redis/Cluster/7000/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7000 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/Cluster/7001/nodes.conf b/tools/redis/Cluster/7001/nodes.conf deleted file mode 100644 index c73e6746..00000000 --- a/tools/redis/Cluster/7001/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 slave c2deb32666652c94499cedc01f4a5849f1f03873 0 1489011303775 6 connected -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 slave 76fc6991abd39a80e72b96362256220294454ce1 0 1489011303250 5 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 master - 0 1489011302232 3 connected 10923-16383 -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 master - 0 1489011302739 1 connected 0-5460 -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 1489011301926 4 connected -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922 -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7001/redis.conf b/tools/redis/Cluster/7001/redis.conf deleted file mode 100644 index d0ec1469..00000000 --- a/tools/redis/Cluster/7001/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7001 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/Cluster/7002/nodes.conf b/tools/redis/Cluster/7002/nodes.conf deleted file mode 100644 index f9647c9c..00000000 --- a/tools/redis/Cluster/7002/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 slave c2deb32666652c94499cedc01f4a5849f1f03873 0 1489011304295 6 connected -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 master - 0 1489011302270 1 connected 0-5460 -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 slave 76fc6991abd39a80e72b96362256220294454ce1 0 1489011304600 5 connected -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 master - 0 1489011303281 2 connected 5461-10922 -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 1489011304397 4 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 myself,master - 0 0 3 connected 10923-16383 -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7002/redis.conf b/tools/redis/Cluster/7002/redis.conf deleted file mode 100644 index c923865d..00000000 --- a/tools/redis/Cluster/7002/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7002 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/Cluster/7003/nodes.conf b/tools/redis/Cluster/7003/nodes.conf deleted file mode 100644 index ac602249..00000000 --- a/tools/redis/Cluster/7003/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 slave c2deb32666652c94499cedc01f4a5849f1f03873 0 1489011304305 6 connected -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 myself,slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 0 4 connected -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 master - 0 1489011303795 1 connected 0-5460 -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 slave 76fc6991abd39a80e72b96362256220294454ce1 0 1489011304411 5 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 master - 0 1489011302270 3 connected 10923-16383 -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 master - 0 1489011303281 2 connected 5461-10922 -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7003/redis.conf b/tools/redis/Cluster/7003/redis.conf deleted file mode 100644 index 3d244fd9..00000000 --- a/tools/redis/Cluster/7003/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7003 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/Cluster/7004/nodes.conf b/tools/redis/Cluster/7004/nodes.conf deleted file mode 100644 index 5e2deee3..00000000 --- a/tools/redis/Cluster/7004/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 master - 0 1489011303281 1 connected 0-5460 -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 1489011302270 4 connected -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 myself,slave 76fc6991abd39a80e72b96362256220294454ce1 0 0 5 connected -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 master - 0 1489011304310 2 connected 5461-10922 -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 slave c2deb32666652c94499cedc01f4a5849f1f03873 0 1489011302776 6 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 master - 0 1489011302167 3 connected 10923-16383 -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7004/redis.conf b/tools/redis/Cluster/7004/redis.conf deleted file mode 100644 index e5b3c2ae..00000000 --- a/tools/redis/Cluster/7004/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7004 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/Cluster/7005/nodes.conf b/tools/redis/Cluster/7005/nodes.conf deleted file mode 100644 index b866484a..00000000 --- a/tools/redis/Cluster/7005/nodes.conf +++ /dev/null @@ -1,7 +0,0 @@ -76fc6991abd39a80e72b96362256220294454ce1 127.0.0.1:7001 master - 0 1489011302270 2 connected 5461-10922 -c6629041f2bc1c7740ce8567431ee975a7059a05 127.0.0.1:7000 master - 0 1489011302776 1 connected 0-5460 -d3b964e757e3f3f7b5ecb46b199f60313b95049d 127.0.0.1:7004 slave 76fc6991abd39a80e72b96362256220294454ce1 0 1489011301966 5 connected -c2deb32666652c94499cedc01f4a5849f1f03873 127.0.0.1:7002 master - 0 1489011301966 3 connected 10923-16383 -86ea72e0b7e81e4e28595df1f920c23151e32ff5 127.0.0.1:7003 slave c6629041f2bc1c7740ce8567431ee975a7059a05 0 1489011303281 4 connected -8160376d2096679aa466417c8cc3dd498a2bdd55 127.0.0.1:7005 myself,slave c2deb32666652c94499cedc01f4a5849f1f03873 0 0 6 connected -vars currentEpoch 6 lastVoteEpoch 0 diff --git a/tools/redis/Cluster/7005/redis.conf b/tools/redis/Cluster/7005/redis.conf deleted file mode 100644 index 11e19c91..00000000 --- a/tools/redis/Cluster/7005/redis.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 7005 -cluster-enabled yes -cluster-config-file nodes.conf -cluster-node-timeout 5000 -slave-read-only yes -cluster-require-full-coverage no \ No newline at end of file diff --git a/tools/redis/install-service.cmd b/tools/redis/install-service.cmd deleted file mode 100644 index 8057e2a4..00000000 --- a/tools/redis/install-service.cmd +++ /dev/null @@ -1,4 +0,0 @@ -cd /d %~dp0 -CALL install.cmd -@packages\Redis-64\tools\redis-server.exe --service-install %~dp0\master.conf -@packages\Redis-64\tools\redis-server.exe --service-start \ No newline at end of file diff --git a/tools/redis/install.cmd b/tools/redis/install.cmd deleted file mode 100644 index 9783c5ad..00000000 --- a/tools/redis/install.cmd +++ /dev/null @@ -1,23 +0,0 @@ -@echo off -cd %~dp0 - -SETLOCAL -SET NUGET_VERSION=latest -SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe - -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto restore -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:restore -IF EXIST packages\redis-64 goto run -.nuget\NuGet.exe install redis-64 -ExcludeVersion -o packages -nocache - - -:run diff --git a/tools/redis/master-debug.conf b/tools/redis/master-debug.conf deleted file mode 100644 index 8b92d603..00000000 --- a/tools/redis/master-debug.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 6379 -dbfilename master.rdb -databases 2000 -maxmemory 2gb -timeout 10 -loglevel debug \ No newline at end of file diff --git a/tools/redis/master.conf b/tools/redis/master.conf deleted file mode 100644 index 5605a5e6..00000000 --- a/tools/redis/master.conf +++ /dev/null @@ -1,14 +0,0 @@ -port 6379 -dbfilename master.rdb -databases 2000 -maxmemory 250mb -maxclients 1000 -notify-keyspace-events AKE - - -#loglevel debug -#save 900 1 -#save 300 10 -#save 60 10000 - -appendonly no \ No newline at end of file diff --git a/tools/redis/redis-cli master.cmd b/tools/redis/redis-cli master.cmd deleted file mode 100644 index bb76f04a..00000000 --- a/tools/redis/redis-cli master.cmd +++ /dev/null @@ -1 +0,0 @@ -@packages\Redis-64\tools\redis-cli.exe -p 6379 diff --git a/tools/redis/redis-server cluster.cmd b/tools/redis/redis-server cluster.cmd deleted file mode 100644 index b5ab5ca0..00000000 --- a/tools/redis/redis-server cluster.cmd +++ /dev/null @@ -1,21 +0,0 @@ -@echo off -cd /d %~dp0 -CALL install.cmd -pushd Cluster\7000 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd -pushd Cluster\7001 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd -pushd Cluster\7002 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd -pushd Cluster\7003 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd -pushd Cluster\7004 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd -pushd Cluster\7005 -@start ..\..\packages\Redis-64\tools\redis-server.exe redis.conf -popd \ No newline at end of file diff --git a/tools/redis/redis-server-full.cmd b/tools/redis/redis-server-full.cmd deleted file mode 100644 index 110d039a..00000000 --- a/tools/redis/redis-server-full.cmd +++ /dev/null @@ -1,7 +0,0 @@ -cd /d %~dp0 -CALL install.cmd -cmd /C start packages\Redis-64\tools\redis-server.exe master.conf -cmd /C start packages\Redis-64\tools\redis-server.exe slave.conf -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel1.conf --sentinel -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel2.conf --sentinel -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel3.conf --sentinel diff --git a/tools/redis/redis-server-master-debug.cmd b/tools/redis/redis-server-master-debug.cmd deleted file mode 100644 index be908b94..00000000 --- a/tools/redis/redis-server-master-debug.cmd +++ /dev/null @@ -1 +0,0 @@ -@packages\Redis-64\tools\redis-server.exe master-debug.conf diff --git a/tools/redis/redis-server-master.cmd b/tools/redis/redis-server-master.cmd deleted file mode 100644 index b151bf65..00000000 --- a/tools/redis/redis-server-master.cmd +++ /dev/null @@ -1,3 +0,0 @@ -cd /d %~dp0 -CALL install.cmd -@packages\Redis-64\tools\redis-server.exe master.conf diff --git a/tools/redis/redis-server-sentinel.cmd b/tools/redis/redis-server-sentinel.cmd deleted file mode 100644 index 18223cc4..00000000 --- a/tools/redis/redis-server-sentinel.cmd +++ /dev/null @@ -1,5 +0,0 @@ -cd /d %~dp0 -CALL install.cmd -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel1.conf --sentinel -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel2.conf --sentinel -cmd /C start packages\Redis-64\tools\redis-server.exe sentinel3.conf --sentinel diff --git a/tools/redis/redis-server-slave.cmd b/tools/redis/redis-server-slave.cmd deleted file mode 100644 index 641de985..00000000 --- a/tools/redis/redis-server-slave.cmd +++ /dev/null @@ -1 +0,0 @@ -@packages\Redis-64\tools\redis-server.exe slave.conf diff --git a/tools/redis/sentinel1.conf b/tools/redis/sentinel1.conf deleted file mode 100644 index 6cf132e0..00000000 --- a/tools/redis/sentinel1.conf +++ /dev/null @@ -1,9 +0,0 @@ -port 26380 -sentinel monitor mymaster 127.0.0.1 6379 2 -sentinel down-after-milliseconds mymaster 1000 -sentinel failover-timeout mymaster 1800 - -sentinel monitor resque 192.168.1.3 6380 4 -sentinel down-after-milliseconds resque 1000 -sentinel failover-timeout resque 1800 -sentinel parallel-syncs resque 5 \ No newline at end of file diff --git a/tools/redis/sentinel2.conf b/tools/redis/sentinel2.conf deleted file mode 100644 index 7c33eef9..00000000 --- a/tools/redis/sentinel2.conf +++ /dev/null @@ -1,9 +0,0 @@ -port 26381 -sentinel monitor mymaster 127.0.0.1 6379 2 -sentinel down-after-milliseconds mymaster 1000 -sentinel failover-timeout mymaster 1800 - -sentinel monitor resque 192.168.1.3 6380 4 -sentinel down-after-milliseconds resque 1000 -sentinel failover-timeout resque 1800 -sentinel parallel-syncs resque 5 diff --git a/tools/redis/sentinel3.conf b/tools/redis/sentinel3.conf deleted file mode 100644 index e278be00..00000000 --- a/tools/redis/sentinel3.conf +++ /dev/null @@ -1,9 +0,0 @@ -port 26382 -sentinel monitor mymaster 127.0.0.1 6379 2 -sentinel down-after-milliseconds mymaster 1000 -sentinel failover-timeout mymaster 1800 - -sentinel monitor resque 192.168.1.3 6380 4 -sentinel down-after-milliseconds resque 1000 -sentinel failover-timeout resque 1800 -sentinel parallel-syncs resque 5 \ No newline at end of file diff --git a/tools/redis/slave.conf b/tools/redis/slave.conf deleted file mode 100644 index 315e175f..00000000 --- a/tools/redis/slave.conf +++ /dev/null @@ -1,6 +0,0 @@ -port 6380 -slaveof 127.0.0.1 6379 -dbfilename slave.rdb -databases 2000 -maxmemory 2gb -save 180 1000 \ No newline at end of file diff --git a/tools/version.props b/tools/version.props index e92bfe72..16af6b29 100644 --- a/tools/version.props +++ b/tools/version.props @@ -1,5 +1,5 @@ - 1.1.2 + 2.0.0 - \ No newline at end of file +