├── .editorconfig
├── .gitattributes
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── Benchmarks.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── COPYRIGHT.txt
├── CacheManager.sln
├── Documentation
├── GetMsdn.cmd
├── api
│ └── index.md
├── apispec
│ ├── CacheManager_Core_CacheFactory_Build_System_String_System_Action_CacheManager_Core_ConfigurationBuilderCachePart__.md
│ ├── CacheManager_Core_JsonConfigurationBuilderExtensions.md
│ ├── CacheManager_Core_MicrosoftConfigurationExtensions.md
│ └── CacheManager_Core_MicrosoftLoggingBuilderExtensions.md
├── build.cmd
├── docfx.json
├── index.md
├── template
│ ├── ManagedReference.html.primary.tmpl
│ ├── partials
│ │ └── enum.tmpl.partial
│ └── toc.html.tmpl
└── toc.yml
├── LICENSE
├── NuGet.Config
├── README.md
├── azure-pipelines-ci.yml
├── benchmarks
├── CacheManager.Benchmarks
│ ├── .gitignore
│ ├── BackplaneMessageBenchmark.cs
│ ├── BaseCacheManagerBenchmark.cs
│ ├── CacheManager.Benchmarks.csproj
│ ├── GzBenchmark.cs
│ ├── PlainDictionaryUpdateBenchmark.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SerializationBenchmark.cs
│ ├── TestPoco.cs
│ └── UnixTimestampBenchmark.cs
├── CacheManager.Config.Tests
│ ├── CacheManager.Config.Tests.csproj
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Settings.StyleCop
│ ├── Tests.cs
│ └── cache.json
└── CacheManager.Events.Tests
│ ├── CacheEvent.cs
│ ├── CacheManager.Events.Tests.csproj
│ ├── EventCommand.cs
│ ├── EventHandling.cs
│ ├── MemoryOnlyCommand.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── RedisAndMemoryCommand.cs
│ └── Spinner.cs
├── samples
├── AspNetCore
│ ├── Controllers
│ │ ├── InfoController.cs
│ │ └── ValuesController.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── Web.csproj
│ ├── appsettings.json
│ ├── cache.json
│ └── web.config
└── CacheManager.Examples
│ ├── App.config
│ ├── CacheManager.Examples.csproj
│ ├── Program.cs
│ └── Properties
│ └── AssemblyInfo.cs
├── src
├── CacheManager.Core
│ ├── BaseCacheManager.Expire.cs
│ ├── BaseCacheManager.GetOrAdd.cs
│ ├── BaseCacheManager.Update.cs
│ ├── BaseCacheManager.cs
│ ├── CacheFactory.cs
│ ├── CacheHandleConfiguration.cs
│ ├── CacheItem.cs
│ ├── CacheManager.Core.csproj
│ ├── CacheManagerConfiguration.cs
│ ├── CacheUpdateMode.cs
│ ├── Configuration
│ │ ├── CacheConfigurationBuilder.cs
│ │ └── CacheManagerSection.cs
│ ├── ExpirationMode.cs
│ ├── ICache.cs
│ ├── ICacheManager.cs
│ ├── ICacheManagerConfiguration.cs
│ ├── Internal
│ │ ├── BackplaneMessage.cs
│ │ ├── BaseCache.cs
│ │ ├── BaseCacheHandle.cs
│ │ ├── CacheBackplane.cs
│ │ ├── CacheEventArgs.cs
│ │ ├── CacheReflectionHelper.cs
│ │ ├── CacheSerializer.cs
│ │ ├── CacheStats.cs
│ │ ├── CacheStatsCounter.cs
│ │ ├── CacheStatsCounterType.cs
│ │ ├── DictionaryCacheHandle.cs
│ │ ├── ICacheItemProperties.cs
│ │ ├── ICacheSerializer.cs
│ │ ├── RequiresSerializerAttribute.cs
│ │ ├── SerializerCacheItem.cs
│ │ ├── TypeCache.cs
│ │ └── UpdateItemResult.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── Utility
│ │ └── Guard.cs
├── CacheManager.Microsoft.Extensions.Caching.Memory
│ ├── CacheManager.Microsoft.Extensions.Caching.Memory.csproj
│ ├── MemoryCacheExtensions.cs
│ ├── MemoryCacheHandle`1.cs
│ ├── MicrosoftMemoryCachingBuilderExtensions.cs
│ └── Properties
│ │ └── AssemblyInfo.cs
├── CacheManager.Microsoft.Extensions.Configuration
│ ├── CacheManager.Microsoft.Extensions.Configuration.csproj
│ ├── MicrosoftConfigurationExtensions.cs
│ └── ServiceCollectionExtensions.cs
├── CacheManager.Serialization.Bond
│ ├── BondCacheItem.cs
│ ├── BondCompactBinaryCacheSerializer.cs
│ ├── BondConfigurationBuilderExtensions.cs
│ ├── BondFastBinaryCacheSerializer.cs
│ ├── BondSerializerBase.cs
│ ├── BondSimpleJsonCacheSerializer.cs
│ ├── CacheManager.Serialization.Bond.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── SerializerCache.cs
├── CacheManager.Serialization.DataContract
│ ├── CacheManager.Serialization.DataContract.csproj
│ ├── DataContractBinaryCacheSerializer.cs
│ ├── DataContractCacheItem.cs
│ ├── DataContractCacheSerializer.cs
│ ├── DataContractCacheSerializerBase.cs
│ ├── DataContractConfigurationBuilderExtensions.cs
│ ├── DataContractGzJsonCacheSerializer.cs
│ ├── DataContractJsonCacheSerializer.cs
│ └── Properties
│ │ └── AssemblyInfo.cs
├── CacheManager.Serialization.Json
│ ├── CacheManager.Serialization.Json.csproj
│ ├── GzJsonCacheSerializer.cs
│ ├── JsonCacheItem.cs
│ ├── JsonCacheSerializer.cs
│ ├── JsonConfigurationBuilderExtensions.cs
│ └── Properties
│ │ └── AssemblyInfo.cs
├── CacheManager.Serialization.ProtoBuf
│ ├── CacheManager.Serialization.ProtoBuf.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── ProtoBufCacheItem.cs
│ ├── ProtoBufConfigurationBuilderExtensions.cs
│ └── ProtoBufSerializer.cs
├── CacheManager.StackExchange.Redis
│ ├── CacheManager.StackExchange.Redis.csproj
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── RedisCacheBackplane.cs
│ ├── RedisCacheHandle.cs
│ ├── RedisConfiguration.cs
│ ├── RedisConfigurationBuilder.cs
│ ├── RedisConfigurationBuilderExtensions.cs
│ ├── RedisConfigurationSection.cs
│ ├── RedisConfigurations.cs
│ ├── RedisConnectionManager.cs
│ ├── RedisValueConverter.cs
│ ├── RetryHelper.cs
│ └── ScriptType.cs
└── CacheManager.SystemRuntimeCaching
│ ├── CacheManager.SystemRuntimeCaching.csproj
│ ├── MemoryCacheHandle`1.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── RuntimeCachingBuilderExtensions.cs
│ └── RuntimeMemoryCacheOptions.cs
├── test
├── CacheManager.MSConfiguration.TypeLoad.Tests
│ ├── CacheManager.MSConfiguration.TypeLoad.Tests.csproj
│ ├── MicrosoftConfigurationTests.cs
│ ├── Properties
│ │ └── launchSettings.json
│ └── xunit.runner.json
└── CacheManager.Tests
│ ├── BackplaneMessageTest.cs
│ ├── CacheFactoryTests.cs
│ ├── CacheItemValidation.cs
│ ├── CacheManager.Tests.csproj
│ ├── CacheManagerAdvancedUpdateTests.cs
│ ├── CacheManagerEventsTest.cs
│ ├── CacheManagerExpirationTest.cs
│ ├── CacheManagerRegionTests.cs
│ ├── CacheManagerSimpleTests.cs
│ ├── CacheManagerStatsTest.cs
│ ├── Configuration
│ ├── configuration.ExpireTest.config
│ ├── configuration.invalid.ExpirationWithoutTimeout.config
│ ├── configuration.invalid.InvalidEnablePerfCounters.config
│ ├── configuration.invalid.InvalidEnableStats.config
│ ├── configuration.invalid.InvalidExpMode.config
│ ├── configuration.invalid.InvalidRef.config
│ ├── configuration.invalid.InvalidTimeout.config
│ ├── configuration.invalid.InvalidUpdateMode.config
│ ├── configuration.invalid.MaxRetries.config
│ ├── configuration.invalid.RetryTimeout.config
│ ├── configuration.invalid.backplaneNameNoType.config
│ ├── configuration.invalid.backplaneTypeNoName.config
│ ├── configuration.invalid.emptyHandleDefinition.config
│ ├── configuration.invalid.invalidDefExpMode.config
│ ├── configuration.invalid.invalidDefTimeout.config
│ ├── configuration.invalid.invalidType.config
│ ├── configuration.invalid.managerWithoutHandles.config
│ ├── configuration.invalid.missingDefId.config
│ ├── configuration.invalid.missingName.config
│ ├── configuration.invalid.missingType.config
│ ├── configuration.invalid.noSection.config
│ ├── configuration.invalid.serializerType.config
│ └── configuration.valid.allFeatures.config
│ ├── ExcludeFromCodeCoverageAttribute.cs
│ ├── InvalidConfigurationValidationTests.cs
│ ├── LoggingTests.cs
│ ├── MemoryCacheTests.cs
│ ├── MicrosoftConfigurationTests.cs
│ ├── MicrosoftLoggingTests.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── RedisTestFixture.cs
│ ├── RedisTests.cs
│ ├── ReplaceCultureAttribute.cs
│ ├── SerializerTests.cs
│ ├── SystemWebCacheHandleWrapper.cs
│ ├── TestCacheManagers.cs
│ ├── TestConfigurationHelper.cs
│ ├── TestHelper.cs
│ ├── TestModel.cs
│ ├── ThreadRandomReadWriteTestBase.cs
│ ├── ThreadTestHelper.cs
│ ├── ValidConfigurationValidationTests.cs
│ ├── app.config
│ ├── testhost.dll.config
│ ├── testhost.x86.dll.config
│ └── xunit.runner.json
└── tools
├── CacheManagerCfg.xsd
├── CodeAnalysis.ruleset
├── RedisCfg.xsd
├── cacheManager.json
├── common.props
├── icon.png
├── key.snk
└── version.props
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: MichaCo
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: feature request
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 | *.lock.json
9 |
10 | /Documentation/_site
11 | /Documentation/api/*.yml
12 | /Documentation/api/*.manifest
13 | /Documentation/msdn.4.5.2
14 | /Documentation/packages
15 | /Documentation/.nuget
16 | /.nuget/nuget.exe
17 |
18 | # Build results
19 |
20 | [Dd]ebug/
21 | [Rr]elease/
22 | x64/
23 | build/
24 | [Bb]in/
25 | [Oo]bj/
26 |
27 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
28 | !packages/*/build/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | *_i.c
35 | *_p.c
36 | *.ilk
37 | *.meta
38 | *.obj
39 | *.pch
40 | *.pdb
41 | *.pgc
42 | *.pgd
43 | *.rsp
44 | *.sbr
45 | *.tlb
46 | *.tli
47 | *.tlh
48 | *.tmp
49 | *.tmp_proj
50 | *.log
51 | *.vspscc
52 | *.vssscc
53 | .builds
54 | *.pidb
55 | *.log
56 | *.scc
57 |
58 | # Visual C++ cache files
59 | ipch/
60 | *.aps
61 | *.ncb
62 | *.opensdf
63 | *.sdf
64 | *.cachefile
65 |
66 | # Visual Studio profiler
67 | *.psess
68 | *.vsp
69 | *.vspx
70 |
71 | # Guidance Automation Toolkit
72 | *.gpState
73 |
74 | # ReSharper is a .NET coding add-in
75 | _ReSharper*/
76 | *.[Rr]e[Ss]harper
77 |
78 | # TeamCity is a build add-in
79 | _TeamCity*
80 |
81 | # DotCover is a Code Coverage Tool
82 | *.dotCover
83 |
84 | # NCrunch
85 | *.ncrunch*
86 | .*crunch*.local.xml
87 |
88 | # Installshield output folder
89 | [Ee]xpress/
90 |
91 | # DocProject is a documentation generator add-in
92 | DocProject/buildhelp/
93 | DocProject/Help/*.HxT
94 | DocProject/Help/*.HxC
95 | DocProject/Help/*.hhc
96 | DocProject/Help/*.hhk
97 | DocProject/Help/*.hhp
98 | DocProject/Help/Html2
99 | DocProject/Help/html
100 |
101 | # Click-Once directory
102 | publish/
103 |
104 | # Publish Web Output
105 | *.Publish.xml
106 |
107 | # NuGet Packages Directory
108 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
109 | #packages/
110 |
111 | # Windows Azure Build Output
112 | csx
113 | *.build.csdef
114 |
115 | # Windows Store app package directory
116 | AppPackages/
117 |
118 | # Others
119 | sql/
120 | *.Cache
121 | ClientBin/
122 | [Ss]tyle[Cc]op.*
123 | ~$*
124 | *~
125 | *.dbmdl
126 | *.[Pp]ublish.xml
127 | *.pfx
128 | *.publishsettings
129 |
130 | # RIA/Silverlight projects
131 | Generated_Code/
132 |
133 | # Backup & report files from converting an old project file to a newer
134 | # Visual Studio version. Backup files are not needed, because we have git ;-)
135 | _UpgradeReport_Files/
136 | Backup*/
137 | UpgradeLog*.XML
138 | UpgradeLog*.htm
139 |
140 | # SQL Server files
141 | App_Data/*.mdf
142 | App_Data/*.ldf
143 |
144 |
145 | #LightSwitch generated files
146 | GeneratedArtifacts/
147 | _Pvt_Extensions/
148 | ModelManifest.xml
149 |
150 | # =========================
151 | # Windows detritus
152 | # =========================
153 |
154 | # Windows image file caches
155 | Thumbs.db
156 | ehthumbs.db
157 |
158 | # Folder config file
159 | Desktop.ini
160 |
161 | # Recycle Bin used on file shares
162 | $RECYCLE.BIN/
163 |
164 | # Mac desktop service store files
165 | .DS_Store
166 | /packages
167 | /samples/CacheManager.Examples/packages
168 | *.rdb
169 | /.vs/config/applicationhost.config
170 | /tools/redis/packages/Redis-64
171 | /tools/redis/.nuget
172 | /.build
173 | /.vs
174 | /Documentation/DocFxBin
175 | /Documentation/*.zip
176 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@michaconrad.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/COPYRIGHT.txt:
--------------------------------------------------------------------------------
1 | Copyright 2014 MichaConrad
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
--------------------------------------------------------------------------------
/Documentation/GetMsdn.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd %~dp0
3 |
4 | SETLOCAL
5 | SET NUGET_VERSION=latest
6 | SET CACHED_NUGET=%LocalAppData%\NuGet\nuget.%NUGET_VERSION%.exe
7 |
8 | IF EXIST %CACHED_NUGET% goto copynuget
9 |
10 | echo Downloading latest version of NuGet.exe...
11 | IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
12 | @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/%NUGET_VERSION%/nuget.exe' -OutFile '%CACHED_NUGET%'"
13 |
14 | :copynuget
15 | IF EXIST .nuget\nuget.exe goto restore
16 | md .nuget
17 | copy %CACHED_NUGET% .nuget\nuget.exe > nul
18 |
19 | :restore
20 | IF EXIST msdn.4.5.2 goto exit
21 | .nuget\nuget.exe install msdn.4.5.2 -pre -ExcludeVersion
22 |
23 | :exit
--------------------------------------------------------------------------------
/Documentation/api/index.md:
--------------------------------------------------------------------------------
1 | # Api Documentation
2 |
3 | Here you can find the CacheManager API reference documentation generated with [docfx](https://dotnet.github.io/docfx/).
--------------------------------------------------------------------------------
/Documentation/apispec/CacheManager_Core_CacheFactory_Build_System_String_System_Action_CacheManager_Core_ConfigurationBuilderCachePart__.md:
--------------------------------------------------------------------------------
1 | ---
2 | uid: CacheManager.Core.CacheFactory.Build(System.String,System.Action{CacheManager.Core.ConfigurationBuilderCachePart})
3 | remarks:
4 | ---
5 |
6 | The following example shows how to use this overload to build a CacheManagerConfiguration
7 | and pass it to the CacheFactory to create a new CacheManager instance.
8 |
9 | ```csharp
10 | var cache = cachefactory.build("mycachename", settings =>
11 | {
12 | settings
13 | .withupdatemode(cacheupdatemode.up)
14 | .withdictionaryhandle()
15 | .enableperformancecounters()
16 | .withexpiration(expirationmode.sliding, timespan.fromseconds(10));
17 | });
18 |
19 | cache.add("key", "value");
20 | ```
21 |
--------------------------------------------------------------------------------
/Documentation/apispec/CacheManager_Core_JsonConfigurationBuilderExtensions.md:
--------------------------------------------------------------------------------
1 | ---
2 | uid: CacheManager.Core.JsonConfigurationBuilderExtensions
3 | ---
4 |
5 | Configuring CacheManager to use the JSON serializer will replace the default Binary serializer.
6 |
7 | ##### **Usage**
8 |
9 | Basic usage example:
10 |
11 | ```csharp
12 | var builder = new Core.ConfigurationBuilder();
13 | builder.WithJsonSerializer();
14 | ```
15 |
16 | optionally, `Newtonsoft.Json.JsonSerializerSettings` can be specified for (de)serialization.
17 | See the [official documentation](http://www.newtonsoft.com/json/help/html/SerializationSettings.htm) for more details.
18 |
19 | ```csharp
20 | builder.WithJsonSerializer(new JsonSerializerSettings(), new JsonSerializerSettings());
21 | ```
22 |
23 |
--------------------------------------------------------------------------------
/Documentation/apispec/CacheManager_Core_MicrosoftConfigurationExtensions.md:
--------------------------------------------------------------------------------
1 | ---
2 | uid: CacheManager.Core.MicrosoftConfigurationExtensions
3 | remarks: 'To be able to use the different configuration providers like JSON or XML, you have to install the corresponding
4 | `Microsoft.Extensions.Configuration.*` package(s).'
5 | ---
6 |
7 | ##### **Usage**
8 |
9 | The following is a basic example of how to use the extensions. See the [configuration documentation](http://cachemanager.michaco.net/Documentation/Index/cachemanager_configuration) for more details.
10 |
11 | ```csharp
12 | // setting up the configuration providers
13 | var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
14 | .AddJsonFile("cache.json");
15 |
16 | // build the configuration
17 | this.Configuration = builder.Build();
18 |
19 | // retrieve the CacheManager configuration
20 | var jsonConfiguration =
21 | this.Configuration.GetCacheConfiguration();
22 | ```
23 |
24 | To create a JSON cache configuration, create a new `.json` file and use the [cachemanager.json](http://cachemanager.michaco.net/schemas/cachemanager.json) schema to
25 | get all the benefits of IntelliSense and validation.
26 |
27 | ```JSON
28 | {
29 | "$schema": "http://cachemanager.michaco.net/schemas/cachemanager.json",
30 | "cacheManagers": [
31 | {
32 | "name": "MyCache",
33 | "handles": [ { "knownType": "SystemRuntime" } ]
34 | }
35 | }
36 | ```
--------------------------------------------------------------------------------
/Documentation/apispec/CacheManager_Core_MicrosoftLoggingBuilderExtensions.md:
--------------------------------------------------------------------------------
1 | ---
2 | uid: CacheManager.Core.MicrosoftLoggingBuilderExtensions
3 | remarks: 'To use the different log providers, install the corresponding `Microsoft.Extensions.Logging.*` package.'
4 | ---
5 |
6 | ##### **Usage**
7 |
8 | Either configure a CacheManager specific logger factory:
9 |
10 | ```csharp
11 | var builder = new Core.ConfigurationBuilder("myCache");
12 | builder.WithMicrosoftLogging(f =>
13 | {
14 | f.AddConsole(LogLevel.Information);
15 | f.AddDebug(LogLevel.Verbose);
16 | });
17 | ```
18 |
19 | Or pass in an existing `ILoggerFactory`:
20 |
21 | ```csharp
22 | var builder = new Core.ConfigurationBuilder("myCache");
23 | builder.WithMicrosoftLogging(loggerFactory);
24 | ```
25 |
26 |
--------------------------------------------------------------------------------
/Documentation/build.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | cd %~dp0
3 |
4 | call GetMsdn.cmd
5 |
6 | SETLOCAL
7 | SET DOCFX_VERSION=2.16.7
8 | SET CACHED_ZIP=%LocalAppData%\DocFx\docfx.%DOCFX_VERSION%.zip
9 |
10 | IF EXIST %CACHED_ZIP% goto extract
11 | echo Downloading latest version of docfx...
12 | IF NOT EXIST %LocalAppData%\DocFx md %LocalAppData%\DocFx
13 | SET DWL_FILE=https://github.com/dotnet/docfx/releases/download/v%DOCFX_VERSION%/docfx.zip
14 | echo Downloading %DWL_FILE%
15 | @powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest '%DWL_FILE%' -OutFile '%CACHED_ZIP%'"
16 |
17 | :extract
18 |
19 | copy %CACHED_ZIP% docfx.zip > nul
20 |
21 | RMDIR /S /Q "DocFxBin"
22 | IF NOT EXIST \DocFxBin md \DocFxBin
23 | @powershell -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('docfx.zip', 'DocFxBin'); }"
24 |
25 | :restore
26 |
27 | :run
28 |
29 | rd /S /Q ..\..\cachemanager.net\website\docs
30 | rd /S /Q obj
31 | DocFxBin\docfx.exe
--------------------------------------------------------------------------------
/Documentation/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [
3 | {
4 | "src": [
5 | {
6 | "src": "../src",
7 | "files": "**/*.csproj"
8 | }
9 | ],
10 | "dest": "obj/api",
11 | "properties": {
12 | "TargetFramework": "net45"
13 | }
14 | }
15 | ],
16 | "build": {
17 | "content": [
18 | {
19 | "files": [
20 | "api/**.yml"
21 | ],
22 | "src": "obj"
23 | },
24 | {
25 | "files": [
26 | "api/*.md",
27 | "articles/**.md",
28 | "toc.yml",
29 | "index.md"
30 | ],
31 | "exclude": [
32 | "obj/**",
33 | "_site/**"
34 | ]
35 | }
36 | ],
37 | "resource": [
38 | {
39 | "files": [
40 | "images/**"
41 | ],
42 | "exclude": [
43 | "obj/**",
44 | "_site/**"
45 | ]
46 | }
47 | ],
48 | "overwrite": [
49 | {
50 | "files": [
51 | "apispec/*.md"
52 | ],
53 | "exclude": [
54 | "obj/**",
55 | "_site/**"
56 | ]
57 | }
58 | ],
59 |
60 | "globalMetadata": {
61 | "_gitContribute": {
62 | "branch": "dev",
63 | "apiSpecFolder": "Documentation/apispec"
64 | }
65 | },
66 | "postProcessors": [ "ExtractSearchIndex" ],
67 | "xref": "msdn.4.5.2/content/msdn.4.5.2.zip",
68 | "dest": "..\\..\\cachemanager.net\\website\\Docs",
69 | "template": [
70 | "default",
71 | "template"
72 | ]
73 | }
74 | }
--------------------------------------------------------------------------------
/Documentation/index.md:
--------------------------------------------------------------------------------
1 | # CacheManager Api Documentation
2 |
3 | The documentation starts [here](/Documentation/api/CacheManager.Core.html)
--------------------------------------------------------------------------------
/Documentation/template/ManagedReference.html.primary.tmpl:
--------------------------------------------------------------------------------
1 | {{#item}}
2 |
3 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}
4 |
5 |
6 |
7 |
8 | {{^_disableBreadcrumb}}
9 | {{>partials/breadcrumb}}
10 | {{/_disableBreadcrumb}}
11 |
12 | {{#_enableSearch}}
13 |
14 | {{>partials/searchResults}}
15 |
16 | {{/_enableSearch}}
17 |
18 | {{^_disableToc}}
19 | {{>partials/toc}}
20 |
21 | {{/_disableToc}}
22 | {{#_disableToc}}
23 |
24 | {{/_disableToc}}
25 | {{#_disableAffix}}
26 |
27 | {{/_disableAffix}}
28 | {{^_disableAffix}}
29 |
30 | {{/_disableAffix}}
31 |
32 | {{#isNamespace}}
33 | {{>partials/namespace}}
34 | {{/isNamespace}}
35 | {{#isClass}}
36 | {{>partials/class}}
37 | {{/isClass}}
38 | {{#isEnum}}
39 | {{>partials/enum}}
40 | {{/isEnum}}
41 | {{>partials/customMREFContent}}
42 |
43 |
44 | {{^_disableAffix}}
45 | {{>partials/affix}}
46 | {{/_disableAffix}}
47 |
48 |
49 |
50 | {{/item}}
51 |
--------------------------------------------------------------------------------
/Documentation/template/partials/enum.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 | {{>partials/class.header}}
4 | {{#children}}
5 |
{{>partials/classSubtitle}}
6 |
7 |
8 |
9 | {{__global.name}}
10 | {{__global.description}}
11 |
12 |
13 |
14 | {{#children}}
15 |
16 | {{name.0.value}}
17 | {{{summary}}}
18 | {{#seealso.0}}
19 | {{__global.seealso}}
20 |
21 | {{/seealso.0}}
22 | {{#seealso}}
23 | {{#isCref}}
24 |
{{{type.specName.0.value}}}
25 | {{/isCref}}
26 | {{^isCref}}
27 |
{{{url}}}
28 | {{/isCref}}
29 | {{/seealso}}
30 | {{#seealso.0}}
31 |
32 | {{/seealso.0}}
33 |
34 |
35 | {{/children}}
36 |
37 |
38 | {{/children}}
39 | {{#extensionMethods.0}}
40 |
{{__global.extensionMethods}}
41 | {{/extensionMethods.0}}
42 | {{#extensionMethods}}
43 |
44 | {{#definition}}
45 |
46 | {{/definition}}
47 | {{^definition}}
48 |
49 | {{/definition}}
50 |
51 | {{/extensionMethods}}
52 | {{#seealso.0}}
53 |
{{__global.seealso}}
54 |
55 | {{/seealso.0}}
56 | {{#seealso}}
57 | {{#isCref}}
58 |
{{{type.specName.0.value}}}
59 | {{/isCref}}
60 | {{^isCref}}
61 |
{{{url}}}
62 | {{/isCref}}
63 | {{/seealso}}
64 | {{#seealso.0}}
65 |
66 | {{/seealso.0}}
67 |
--------------------------------------------------------------------------------
/Documentation/template/toc.html.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
25 |
26 |
27 |
28 | {{^leaf}}
29 | {{>partials/li}}
30 | {{/leaf}}
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Documentation/toc.yml:
--------------------------------------------------------------------------------
1 |
2 | - name: CacheManager Api Documentation
3 | href: api/
4 |
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/azure-pipelines-ci.yml:
--------------------------------------------------------------------------------
1 | name: '$(Date:yyyyMMdd)$(Rev:.r)'
2 |
3 | trigger:
4 | - dev
5 | - master
6 |
7 | pr:
8 | autoCancel: false
9 | branches:
10 | include:
11 | - '*'
12 |
13 | # pool:
14 | # vmImage: 'windows-latest'
15 |
16 | variables:
17 | buildPlatform: 'Any CPU'
18 | buildConfiguration: 'Release'
19 | ${{ if not(eq(variables['Build.SourceBranch'], 'refs/heads/master')) }}:
20 | versionSuffix: 'beta-$(Build.BuildNumber)'
21 | ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}:
22 | versionSuffix: ''
23 |
24 | jobs:
25 | - job: Windows
26 | displayName: 'Build & Test'
27 | pool:
28 | vmImage: 'windows-latest'
29 |
30 | steps:
31 | - task: DotNetCoreCLI@2
32 | displayName: 'dotnet build'
33 | inputs:
34 | command: 'build'
35 | projects: |
36 | CacheManager.sln
37 | arguments: '-c Release'
38 | name: 'Build'
39 | - task: DotNetCoreCLI@2
40 | displayName: "dotnet test"
41 | inputs:
42 | command: 'test'
43 | projects: 'test/**/*.csproj'
44 | publishTestResults: true
45 | arguments: '-c Release --no-build --no-restore --filter category!=Unreliable'
46 | - script: 'dotnet pack src\CacheManager.Core\CacheManager.Core.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)'
47 | displayName: 'dotnet pack Core'
48 | - 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)'
49 | displayName: 'dotnet pack CacheManager.Microsoft.Extensions.Caching.Memory'
50 | - 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)'
51 | displayName: 'dotnet pack CacheManager.Microsoft.Extensions.Configuration'
52 | - 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)'
53 | displayName: 'dotnet pack CacheManager.Serialization.Bond'
54 | - 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)'
55 | displayName: 'dotnet pack CacheManager.Serialization.DataContract'
56 | - 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)'
57 | displayName: 'dotnet pack CacheManager.Serialization.Json'
58 | - 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)'
59 | displayName: 'dotnet pack CacheManager.Serialization.ProtoBuf'
60 | - 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)'
61 | displayName: 'dotnet pack CacheManager.StackExchange.Redis'
62 | - script: 'dotnet pack src\CacheManager.SystemRuntimeCaching\CacheManager.SystemRuntimeCaching.csproj -c Release --no-build --no-restore --version-suffix "$(versionSuffix)" -v normal -o $(Build.ArtifactStagingDirectory)'
63 | displayName: 'dotnet pack CacheManager.SystemRuntimeCaching'
64 | - task: PublishBuildArtifacts@1
65 | displayName: 'Publish Artifacts'
66 | inputs:
67 | pathtoPublish: '$(Build.ArtifactStagingDirectory)'
68 | artifactName: 'cachemanager'
69 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/.gitignore:
--------------------------------------------------------------------------------
1 | BenchmarkDotNet.Artifacts/
2 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/CacheManager.Benchmarks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | CacheManager.Benchmarks
5 | Exe
6 | CacheManager.Benchmarks
7 | false
8 | false
9 | false
10 | false
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | true
26 |
27 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/PlainDictionaryUpdateBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using BenchmarkDotNet.Attributes;
7 |
8 | namespace CacheManager.Benchmarks
9 | {
10 | [ExcludeFromCodeCoverage]
11 | public class PlainDictionaryUpdateBenchmark
12 | {
13 | private const int Threads = 6;
14 | private const int Iterations = 1000;
15 |
16 | private object _locke = new object();
17 | private ConcurrentDictionary
_dictionary;
18 |
19 | [Benchmark(Baseline = true)]
20 | public void UpdateWithoutLock()
21 | {
22 | _dictionary = new ConcurrentDictionary();
23 | _dictionary.TryAdd("key", 0);
24 | RunParallel(() => UpdateImpl((v) => v + 1), Threads, Iterations);
25 |
26 | if (_dictionary["key"] != Threads * Iterations)
27 | {
28 | throw new Exception(string.Format("Not updated correctly, expected '{0}' but found '{1}'.", Threads * Iterations, _dictionary["key"]));
29 | }
30 | }
31 |
32 | [Benchmark]
33 | public void UpdateWithLock()
34 | {
35 | _dictionary = new ConcurrentDictionary();
36 | _dictionary.TryAdd("key", 0);
37 | RunParallel(() => UpdateLockedImpl((v) => v + 1), Threads, Iterations);
38 |
39 | if (_dictionary["key"] != Threads * Iterations)
40 | {
41 | throw new Exception(string.Format("Not updated correctly, expected '{0}' but found '{1}'.", Threads * Iterations, _dictionary["key"]));
42 | }
43 | }
44 |
45 | // unfortunately we cannot use the non-lock implementation as pocos/reference type objects might be modified
46 | // in memory on each iteration/retry and changes are anyways applied no matter if the "update" was successful or not
47 | // depending on the version, I'd have to clone the value prior to updating it.
48 | public int UpdateImpl(Func updateFactory)
49 | {
50 | int value;
51 | var success = false;
52 | var tries = 0;
53 | do
54 | {
55 | tries++;
56 | if (!_dictionary.TryGetValue("key", out value))
57 | {
58 | throw new InvalidProgramException("Value not found");
59 | }
60 |
61 | success = _dictionary.TryUpdate("key", updateFactory(value), value);
62 | } while (!success);
63 |
64 | return value;
65 | }
66 |
67 | public int UpdateLockedImpl(Func updateFactory)
68 | {
69 | lock (_locke)
70 | {
71 | if (!_dictionary.TryGetValue("key", out int value))
72 | {
73 | throw new InvalidProgramException("Value not found");
74 | }
75 |
76 | _dictionary["key"] = updateFactory(value);
77 |
78 | return value;
79 | }
80 | }
81 |
82 | private void RunParallel(Action act, int threads, int iterations)
83 | {
84 | Action iter = () =>
85 | {
86 | for (var i = 0; i < iterations; i++)
87 | {
88 | act();
89 | }
90 | };
91 |
92 | var tasks = Enumerable.Repeat(iter, threads);
93 |
94 | Parallel.Invoke(tasks.ToArray());
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Net;
4 | using System.Reflection;
5 | using BenchmarkDotNet.Configs;
6 | using BenchmarkDotNet.Jobs;
7 | using BenchmarkDotNet.Running;
8 | using Garnet;
9 | using Garnet.server;
10 | using Microsoft.Extensions.Logging;
11 |
12 | namespace CacheManager.Benchmarks;
13 |
14 | [ExcludeFromCodeCoverage]
15 | public class Program
16 | {
17 | public static GarnetServer StartServer(ILoggerFactory loggerFactory = null)
18 | {
19 | var server = new GarnetServer(new GarnetServerOptions()
20 | {
21 | EnableLua = true,
22 | LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)),
23 | EndPoint = new IPEndPoint(IPAddress.Loopback, 6379)
24 | },
25 | loggerFactory: loggerFactory);
26 |
27 | server.Start();
28 |
29 | return server;
30 | }
31 |
32 | public static void Main(string[] args)
33 | {
34 | StartServer();
35 |
36 | do
37 | {
38 | var config = ManualConfig.CreateMinimumViable()
39 | .AddJob(Job.Default
40 | .WithIterationCount(10)
41 | .WithWarmupCount(2)
42 | .WithLaunchCount(1))
43 | .AddDiagnoser(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default);
44 |
45 | BenchmarkSwitcher
46 | .FromAssembly(typeof(Program).GetTypeInfo().Assembly)
47 | .Run(args, config);
48 |
49 | Console.WriteLine("done!");
50 | Console.WriteLine("Press escape to exit or any key to continue...");
51 | } while (Console.ReadKey().Key != ConsoleKey.Escape);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("CoreApp")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("987c4cd7-d162-4635-8c50-214a25494676")]
20 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/TestPoco.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Linq;
5 | using Newtonsoft.Json;
6 | using ProtoBuf;
7 |
8 | namespace CacheManager.Benchmarks
9 | {
10 | [ExcludeFromCodeCoverage]
11 | [Serializable]
12 | [JsonObject]
13 | [ProtoContract]
14 | [Bond.Schema]
15 | public class TestPoco
16 | {
17 | [JsonProperty]
18 | [ProtoMember(1)]
19 | [Bond.Id(1)]
20 | public long L { get; set; }
21 |
22 | [JsonProperty]
23 | [ProtoMember(2)]
24 | [Bond.Id(2)]
25 | public string S { get; set; }
26 |
27 | [JsonProperty]
28 | [ProtoMember(3)]
29 | [Bond.Id(3)]
30 | public List SList { get; set; }
31 |
32 | [JsonProperty]
33 | [ProtoMember(4)]
34 | [Bond.Id(4)]
35 | public List OList { get; set; }
36 | }
37 |
38 | [ExcludeFromCodeCoverage]
39 | [Serializable]
40 | [ProtoContract]
41 | [JsonObject]
42 | [Bond.Schema]
43 | public class TestSubPoco
44 | {
45 | [JsonProperty]
46 | [ProtoMember(1)]
47 | [Bond.Id(1)]
48 | public int Id { get; set; }
49 |
50 | [JsonProperty]
51 | [ProtoMember(2)]
52 | [Bond.Id(2)]
53 | public string Val { get; set; }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Benchmarks/UnixTimestampBenchmark.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using BenchmarkDotNet.Attributes;
4 |
5 | namespace CacheManager.Benchmarks
6 | {
7 | [ExcludeFromCodeCoverage]
8 | public class UnixTimestampBenchmark
9 | {
10 | [Benchmark(Baseline = true)]
11 | public long Framework()
12 | {
13 | return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
14 | }
15 |
16 | private static readonly DateTime _date1970 = new DateTime(1970, 1, 1);
17 |
18 | [Benchmark()]
19 | public long ManualCalcNaive()
20 | {
21 | return (long)(DateTime.UtcNow - _date1970).TotalMilliseconds;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Config.Tests/CacheManager.Config.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features.
5 | 2.0.0
6 | MichaConrad
7 | net8.0
8 | CacheManager.Config.Tests
9 | Exe
10 | ../../tools/key.snk
11 | true
12 | true
13 | CacheManager.Config.Tests
14 | false
15 |
16 |
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Config.Tests/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 | using CacheManager.Core;
6 | using Garnet;
7 | using Garnet.client;
8 | using Garnet.server;
9 | using Microsoft.Extensions.DependencyInjection;
10 | using Microsoft.Extensions.Logging;
11 |
12 | namespace CacheManager.Config.Tests;
13 |
14 | internal class Program
15 | {
16 | public static GarnetServer StartServer(ILoggerFactory loggerFactory)
17 | {
18 | var server = new GarnetServer(new GarnetServerOptions()
19 | {
20 | EnableLua = true,
21 | LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)),
22 | EndPoint = new IPEndPoint(IPAddress.Loopback, 6379)
23 | },
24 | loggerFactory: loggerFactory);
25 |
26 | server.Start();
27 |
28 | return server;
29 | }
30 |
31 | public static void Main(string[] args)
32 | {
33 | ThreadPool.SetMinThreads(100, 100);
34 |
35 | var iterations = 100;
36 | try
37 | {
38 | var services = new ServiceCollection();
39 |
40 | services.AddLogging(c =>
41 | {
42 | c.AddSystemdConsole();
43 | c.SetMinimumLevel(LogLevel.Information);
44 | });
45 |
46 | var provider = services.BuildServiceProvider();
47 | var loggerFactory = provider.GetRequiredService();
48 |
49 | using var server = StartServer(loggerFactory);
50 |
51 | var builder = new Core.CacheConfigurationBuilder("myCache");
52 |
53 | builder
54 | .WithRetryTimeout(500)
55 | .WithMaxRetries(3);
56 |
57 | builder
58 | .WithDictionaryHandle()
59 | .WithExpiration(ExpirationMode.Absolute, TimeSpan.FromSeconds(20))
60 | .DisableStatistics();
61 |
62 | builder
63 | .WithRedisCacheHandle("redis", true)
64 | .WithExpiration(ExpirationMode.Sliding, TimeSpan.FromSeconds(60))
65 | .DisableStatistics();
66 |
67 | builder.WithRedisBackplane("redis");
68 |
69 | builder.WithRedisConfiguration("redis", config =>
70 | {
71 | config
72 | //.UseTwemproxy()
73 | //.UseCompatibilityMode("2.4")
74 | .WithAllowAdmin()
75 | .WithDatabase(0)
76 | .WithConnectionTimeout(5000)
77 | .EnableKeyspaceEvents()
78 | .WithEndpoint("127.0.0.1", 6379);
79 | });
80 |
81 | //builder.WithRedisConfiguration("redis", "localhost:22121");
82 |
83 | builder.WithBondCompactBinarySerializer();
84 |
85 | var cacheA = new BaseCacheManager(builder.Build());
86 | cacheA.Clear();
87 |
88 | for (var i = 0; i < iterations; i++)
89 | {
90 | try
91 | {
92 | Tests.PumpData(cacheA).GetAwaiter().GetResult();
93 | break; // specified runtime (todo: rework this anyways)
94 | }
95 | catch (AggregateException ex)
96 | {
97 | ex.Handle((e) =>
98 | {
99 | Console.WriteLine(e);
100 | return true;
101 | });
102 | }
103 | catch (Exception e)
104 | {
105 | Console.WriteLine("Error: " + e.Message + "\n" + e.StackTrace);
106 | Thread.Sleep(1000);
107 | }
108 |
109 | Console.WriteLine("---------------------------------------------------------");
110 | }
111 | }
112 | catch (Exception ex)
113 | {
114 | Console.WriteLine(ex);
115 | }
116 |
117 | Console.ForegroundColor = ConsoleColor.DarkGreen;
118 | Console.WriteLine("We are done...");
119 | Console.ForegroundColor = ConsoleColor.Gray;
120 | Console.ReadKey();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Config.Tests/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "CacheManager.Config.Tests": {
4 | "commandName": "Project"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Config.Tests/Settings.StyleCop:
--------------------------------------------------------------------------------
1 |
2 |
3 | ..\..\Settings.StyleCop
4 | Linked
5 | False
6 |
7 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Config.Tests/cache.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://cachemanager.michaco.net/schemas/cachemanager.json#",
3 | "redis": [
4 | {
5 | "key": "redisConnection",
6 | "endpoints": [
7 | {
8 | "host": "localhost",
9 | "port": 6379
10 | }
11 | ],
12 | "allowAdmin": true,
13 | "database": 11
14 | }
15 | ],
16 | "cacheManagers": [
17 | {
18 | "maxRetries": 1000,
19 | "name": "cachename",
20 | "retryTimeout": 100,
21 | "updateMode": "Up",
22 | "backplane": {
23 | "key": "redisConnection",
24 | "knownType": "Redis",
25 | "channelName": "test"
26 | },
27 | "loggerFactory": {
28 | "knownType": "Microsoft"
29 | },
30 | "serializer": {
31 | "knownType": "Json"
32 | },
33 | "handles": [
34 | //{
35 | // "knownType": "Dictionary",
36 | // "enablePerformanceCounters": true,
37 | // "enableStatistics": true,
38 | // "expirationMode": "Absolute",
39 | // "expirationTimeout": "0:0:23",
40 | // "isBackplaneSource": false,
41 | // "name": "sys cache"
42 | //},
43 | {
44 | "knownType": "Redis",
45 | "key": "redisConnection",
46 | "isBackplaneSource": true,
47 | "expirationMode": "Sliding",
48 | "expirationTimeout": "00:10:00"
49 | }
50 | ]
51 | }
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/CacheEvent.cs:
--------------------------------------------------------------------------------
1 | namespace CacheManager.Events.Tests
2 | {
3 | public enum CacheEvent
4 | {
5 | Get,
6 | Add,
7 | Put,
8 | Rem,
9 | Upd,
10 | ClA,
11 | ClR,
12 | ReH
13 | }
14 | }
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/CacheManager.Events.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/EventHandling.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading;
5 | using CacheManager.Core;
6 | using CacheManager.Core.Internal;
7 |
8 | namespace CacheManager.Events.Tests
9 | {
10 | public class EventCounter
11 | {
12 | private object _locki = new object();
13 | private readonly Dictionary _updates = new Dictionary();
14 |
15 | public EventCounter(ICacheManager cache)
16 | {
17 | Cache = cache ?? throw new ArgumentNullException(nameof(cache));
18 |
19 | Cache.OnRemove += OnRemove;
20 | Cache.OnRemoveByHandle += OnRemoveByHandle;
21 | Cache.OnAdd += OnAdd;
22 | Cache.OnGet += OnGet;
23 | Cache.OnPut += OnPut;
24 | Cache.OnUpdate += OnUpdate;
25 |
26 | _updates.Add(CacheEvent.Add, new int[2]);
27 | _updates.Add(CacheEvent.Put, new int[2]);
28 | _updates.Add(CacheEvent.Rem, new int[2]);
29 | _updates.Add(CacheEvent.Get, new int[2]);
30 | _updates.Add(CacheEvent.ReH, new int[2]);
31 | _updates.Add(CacheEvent.Upd, new int[2]);
32 | }
33 |
34 | public Dictionary GetExpectedState()
35 | {
36 | var result = new Dictionary();
37 |
38 | foreach (var kv in _updates.ToArray())
39 | {
40 | result.Add(kv.Key, new[] { kv.Value[0], kv.Value[1] });
41 | }
42 |
43 | return result;
44 | }
45 |
46 | private void Update(CacheEvent ev, string key, CacheActionEventArgOrigin origin)
47 | {
48 | if (origin == CacheActionEventArgOrigin.Local)
49 | {
50 | Interlocked.Increment(ref _updates[ev][0]);
51 | }
52 | else
53 | {
54 | Interlocked.Increment(ref _updates[ev][1]);
55 | }
56 | }
57 |
58 | public ICacheManager Cache { get; }
59 |
60 | private void OnUpdate(object sender, CacheActionEventArgs e)
61 | {
62 | Update(CacheEvent.Upd, e.Key, e.Origin);
63 | }
64 |
65 | private void OnPut(object sender, CacheActionEventArgs e)
66 | {
67 | Update(CacheEvent.Put, e.Key, e.Origin);
68 | }
69 |
70 | private void OnGet(object sender, CacheActionEventArgs e)
71 | {
72 | Update(CacheEvent.Get, e.Key, e.Origin);
73 | }
74 |
75 | private void OnAdd(object sender, CacheActionEventArgs e)
76 | {
77 | Update(CacheEvent.Add, e.Key, e.Origin);
78 | }
79 |
80 | private void OnRemove(object sender, CacheActionEventArgs e)
81 | {
82 | Update(CacheEvent.Rem, e.Key, e.Origin);
83 | }
84 |
85 | private void OnRemoveByHandle(object sender, CacheItemRemovedEventArgs e)
86 | {
87 | Update(CacheEvent.ReH, e.Key, CacheActionEventArgOrigin.Local);
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using Garnet;
4 | using Garnet.server;
5 | using McMaster.Extensions.CommandLineUtils;
6 | using Microsoft.Extensions.DependencyInjection;
7 | using Microsoft.Extensions.Logging;
8 |
9 | namespace CacheManager.Events.Tests;
10 |
11 |
12 | internal class Program
13 | {
14 | public static GarnetServer StartServer(ILoggerFactory loggerFactory)
15 | {
16 | var server = new GarnetServer(new GarnetServerOptions()
17 | {
18 | EnableLua = true,
19 | LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)),
20 | EndPoint = new IPEndPoint(IPAddress.Loopback, 6379)
21 | },
22 | loggerFactory: loggerFactory);
23 |
24 | server.Start();
25 |
26 | return server;
27 | }
28 |
29 | private static void Main(string[] args)
30 | {
31 |
32 | var services = new ServiceCollection();
33 | services.AddLogging(c =>
34 | {
35 | c.AddConsole();
36 | c.SetMinimumLevel(LogLevel.Warning);
37 | });
38 |
39 | var provider = services.BuildServiceProvider();
40 | var loggerFactory = provider.GetRequiredService();
41 |
42 | using var server = StartServer(loggerFactory);
43 |
44 | var app = new CommandLineApplication();
45 | app.Command("redis", (cmdApp) => new RedisCommand(cmdApp, loggerFactory));
46 | app.Command("redisAndMemory", (cmdApp) => new RedisAndMemoryCommand(cmdApp, loggerFactory));
47 | app.Command("redisAndMemoryNoMessages", (cmdApp) => new RedisAndMemoryNoMessagingCommand(cmdApp, loggerFactory));
48 | app.Command("memoryOnly", (cmdApp) => new MemoryOnlyCommand(cmdApp, loggerFactory));
49 | app.HelpOption("-h|--help");
50 | if (args.Length == 0)
51 | {
52 | app.ShowHelp();
53 | }
54 |
55 | try
56 | {
57 | app.Execute(args);
58 | }
59 | catch (Exception ex)
60 | {
61 | Console.WriteLine(ex);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "CacheManager.Events.Tests": {
4 | "commandName": "Project",
5 | "commandLineArgs": "redisAndMemory -r 20 -j 10"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/RedisAndMemoryCommand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using CacheManager.Core;
4 | using CacheManager.Core.Internal;
5 | using McMaster.Extensions.CommandLineUtils;
6 | using Microsoft.Extensions.Logging;
7 | using StackExchange.Redis;
8 |
9 | namespace CacheManager.Events.Tests
10 | {
11 | public class RedisAndMemoryNoMessagingCommand : RedisAndMemoryCommand
12 | {
13 | public RedisAndMemoryNoMessagingCommand(CommandLineApplication app, ILoggerFactory loggerFactory) : base(app, loggerFactory)
14 | {
15 | }
16 |
17 | protected override void Configure()
18 | {
19 | base.Configure();
20 |
21 | _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true");
22 | _configuration = new CacheConfigurationBuilder()
23 | .WithMicrosoftMemoryCacheHandle("in-memory")
24 | .And
25 | .WithJsonSerializer()
26 | .WithRedisConfiguration("redisConfig", _multiplexer, enableKeyspaceNotifications: false)
27 | .WithRedisCacheHandle("redisConfig")
28 | .Build();
29 | }
30 | }
31 |
32 | public class RedisCommand : RedisAndMemoryCommand
33 | {
34 | public RedisCommand(CommandLineApplication app, ILoggerFactory loggerFactory) : base(app, loggerFactory)
35 | {
36 | }
37 |
38 | protected override void Configure()
39 | {
40 | base.Configure();
41 |
42 | _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true");
43 | _configuration = new CacheConfigurationBuilder()
44 | .WithRedisBackplane("redisConfig")
45 | .WithJsonSerializer()
46 | .WithRedisConfiguration("redisConfig", _multiplexer, enableKeyspaceNotifications: true)
47 | .WithRedisCacheHandle("redisConfig")
48 | .Build();
49 | }
50 | }
51 |
52 | public class RedisAndMemoryCommand : EventCommand
53 | {
54 | protected ICacheManagerConfiguration _configuration;
55 | protected ConnectionMultiplexer _multiplexer;
56 |
57 | public RedisAndMemoryCommand(CommandLineApplication app, ILoggerFactory loggerFactory) : base(app, loggerFactory)
58 | {
59 | }
60 |
61 | protected override void Configure()
62 | {
63 | base.Configure();
64 |
65 | _multiplexer = ConnectionMultiplexer.Connect("127.0.0.1,allowAdmin=true");
66 | _configuration = new CacheConfigurationBuilder()
67 | .WithMicrosoftMemoryCacheHandle("in-memory")
68 | .And
69 | .WithRedisBackplane("redisConfig")
70 | .WithJsonSerializer()
71 | .WithRedisConfiguration("redisConfig", _multiplexer, enableKeyspaceNotifications: true)
72 | .WithRedisCacheHandle("redisConfig")
73 | .Build();
74 | }
75 |
76 | public override async Task Execute()
77 | {
78 | var rnd = new Random(42);
79 |
80 | try
81 | {
82 | await RunWithConfigurationTwoCaches(
83 | _configuration,
84 | async (cacheA, cacheB, hA, hB) =>
85 | {
86 | var rndNumber = rnd.Next(42, 420);
87 | var key = Guid.NewGuid().ToString();
88 |
89 | cacheA.Add(key, rndNumber);
90 |
91 | cacheA.TryUpdate(key, (oldVal) => oldVal + 1, out int? newValue);
92 |
93 | _multiplexer.GetDatabase(0).KeyDelete(key);
94 |
95 | await Task.Delay(0);
96 | });
97 | }
98 | catch (Exception ex)
99 | {
100 | Console.WriteLine(ex);
101 | return 500;
102 | }
103 | return 0;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/benchmarks/CacheManager.Events.Tests/Spinner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 |
8 | namespace CacheManager.Events.Tests
9 | {
10 | public class Spinner
11 | {
12 | private int _msgLength = 4;
13 | private string _msg = string.Empty;
14 | private int _statusLength = 4;
15 | private string _status = string.Empty;
16 | private ConsoleColor _oldColor;
17 | private CancellationTokenSource _source;
18 | private CancellationToken _token;
19 |
20 | public string Message
21 | {
22 | get { return _msg; }
23 | set
24 | {
25 | if (value != null)
26 | {
27 | _msgLength = _msgLength > value.Length ? _msgLength : value.Length;
28 | }
29 |
30 | _msg = value;
31 | }
32 | }
33 |
34 | public string Status
35 | {
36 | get { return _status; }
37 | set
38 | {
39 | if (value != null)
40 | {
41 | _statusLength = _statusLength > value.Length ? _statusLength : value.Length;
42 | }
43 |
44 | _status = value;
45 | }
46 | }
47 |
48 | public void Start()
49 | {
50 | Console.CursorVisible = false;
51 | _oldColor = Console.ForegroundColor;
52 | Console.ForegroundColor = ConsoleColor.Yellow;
53 |
54 | _source = new CancellationTokenSource();
55 | _token = _source.Token;
56 | Task.Run(Spin, _token);
57 | }
58 |
59 | public void Stop()
60 | {
61 | _source.Cancel();
62 |
63 | Console.SetCursorPosition(0, Console.CursorTop);
64 | Console.Write(string.Join("", Enumerable.Repeat(" ", Console.BufferWidth)));
65 | Console.SetCursorPosition(0, Console.CursorTop);
66 | Console.CursorVisible = true;
67 | Console.ForegroundColor = _oldColor;
68 | }
69 |
70 | private async Task Spin()
71 | {
72 | var chars = new Queue(new[] { "|", "/", "-", "\\" });
73 |
74 | while (true)
75 | {
76 | _token.ThrowIfCancellationRequested();
77 | var chr = chars.Dequeue();
78 | chars.Enqueue(chr);
79 | Console.CursorVisible = false;
80 | Console.ForegroundColor = ConsoleColor.Yellow;
81 | var msg = string.Format("{{{0}}} {1,-" + _msgLength + "}{2,-" + _statusLength + "}", chr, Message, Status);
82 | if(msg.Length >= Console.BufferWidth)
83 | {
84 | msg = msg.Substring(0, Console.BufferWidth - 1);
85 | }
86 | Console.Write(msg);
87 | Console.SetCursorPosition(0, Console.CursorTop);
88 | Console.ForegroundColor = _oldColor;
89 | Console.CursorVisible = true;
90 | await Task.Delay(100, _token);
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Controllers/InfoController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace Web.Controllers
8 | {
9 | [Route("api/[controller]")]
10 | public class InfoController : Controller
11 | {
12 | [HttpGet("")]
13 | public IActionResult Index()
14 | {
15 | var result = new Dictionary();
16 | result.Add(nameof(Microsoft.Extensions.Configuration), typeof(Microsoft.Extensions.Configuration.ConfigurationProvider).Assembly.GetName().Version.ToString());
17 | result.Add(nameof(Microsoft.Extensions.Logging), typeof(Microsoft.Extensions.Logging.LoggerFactory).Assembly.GetName().Version.ToString());
18 | result.Add(nameof(Microsoft.Extensions.Caching), typeof(Microsoft.Extensions.Caching.Memory.MemoryCache).Assembly.GetName().Version.ToString());
19 | result.Add(nameof(Microsoft.Extensions.DependencyInjection), typeof(Microsoft.Extensions.DependencyInjection.ServiceProvider).Assembly.GetName().Version.ToString());
20 | result.Add(nameof(Microsoft.Extensions.Options), typeof(Microsoft.Extensions.Options.Options).Assembly.GetName().Version.ToString());
21 | result.Add(nameof(Microsoft.AspNetCore.Hosting), typeof(Microsoft.AspNetCore.Hosting.WebHostBuilder).Assembly.GetName().Version.ToString());
22 |
23 | return Json(result);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Controllers/ValuesController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using CacheManager.Core;
4 | using Microsoft.AspNetCore.Mvc;
5 |
6 | namespace AspnetCore.WebApp.Controllers
7 | {
8 | [Route("api/[controller]")]
9 | public class ValuesController : Controller
10 | {
11 | private readonly ICacheManager _cache;
12 |
13 | public ValuesController(ICacheManager valuesCache, ICacheManager nullableInts)
14 | {
15 | _cache = valuesCache;
16 | nullableInts.Add("key", 1);
17 | }
18 |
19 | // DELETE api/values/key
20 | [HttpDelete("{key}")]
21 | public IActionResult Delete(string key)
22 | {
23 | if (_cache.Remove(key))
24 | {
25 | return Ok();
26 | }
27 |
28 | return NotFound();
29 | }
30 |
31 | // GET api/values/key
32 | [HttpGet("{key}")]
33 | public IActionResult Get(string key)
34 | {
35 | var value = _cache.GetCacheItem(key);
36 | if (value == null)
37 | {
38 | return NotFound();
39 | }
40 |
41 | return Json(value.Value);
42 | }
43 |
44 | // POST api/values/key
45 | [HttpPost("{key}")]
46 | public IActionResult Post(string key, [FromBody]string value)
47 | {
48 | if (_cache.Add(key, value))
49 | {
50 | return Ok();
51 | }
52 |
53 | return BadRequest("Item already exists.");
54 | }
55 |
56 | // PUT api/values/key
57 | [HttpPut("{key}")]
58 | public IActionResult Put(string key, [FromBody]string value)
59 | {
60 | if (_cache.AddOrUpdate(key, value, (v) => value) != null)
61 | {
62 | return Ok();
63 | }
64 |
65 | return NotFound();
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Net;
4 | using Garnet;
5 | using Garnet.server;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Builder;
8 | using Microsoft.AspNetCore.Hosting;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.Hosting;
11 | using Microsoft.Extensions.Logging;
12 |
13 | namespace AspnetCore.WebApp;
14 |
15 | public class Program
16 | {
17 | public static GarnetServer StartServer(ILoggerFactory loggerFactory = null)
18 | {
19 | var server = new GarnetServer(new GarnetServerOptions()
20 | {
21 | EnableLua = true,
22 | LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(5)),
23 | EndPoint = new IPEndPoint(IPAddress.Loopback, 6379)
24 | },
25 | loggerFactory: loggerFactory);
26 |
27 | server.Start();
28 |
29 | return server;
30 | }
31 |
32 | public static void Main(string[] args)
33 | {
34 | using var server = StartServer();
35 | CreateHostBuilder(args).Build().Run();
36 | }
37 |
38 | public static IWebHostBuilder CreateHostBuilder(string[] args) =>
39 | WebHost.CreateDefaultBuilder(args)
40 | .UseStartup()
41 | .ConfigureAppConfiguration((ctx, builder) =>
42 | {
43 | builder.AddJsonFile("cache.json", optional: false);
44 | });
45 | }
46 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "AspnetCore.WebApp": {
4 | "commandName": "Project",
5 | "launchBrowser": false,
6 | "launchUrl": "http://localhost:5000/swagger/ui",
7 | "environmentVariables": {
8 | "ASPNETCORE_ENVIRONMENT": "Development"
9 | },
10 | "applicationUrl": "http://localhost:5000"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Startup.cs:
--------------------------------------------------------------------------------
1 | namespace AspnetCore.WebApp
2 | {
3 | using System;
4 | using CacheManager.Core;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.AspNetCore.Http;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.Extensions.Logging;
10 | using Microsoft.Extensions.Configuration;
11 | using Microsoft.Extensions.Hosting;
12 |
13 | public class Startup
14 | {
15 | public Startup(IWebHostEnvironment env, IConfiguration configuration, ILoggerFactory loggerFactory)
16 | {
17 | HostingEnvironment = env ?? throw new ArgumentNullException(nameof(env));
18 | Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
19 | LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
20 | }
21 |
22 | public IWebHostEnvironment HostingEnvironment { get; }
23 |
24 | public IConfiguration Configuration { get; }
25 |
26 | public ILoggerFactory LoggerFactory { get; }
27 |
28 | public void ConfigureServices(IServiceCollection services)
29 | {
30 | services.AddMvc();
31 |
32 | services.AddSwaggerGen(c =>
33 | {
34 | c.SwaggerDoc("v1",
35 | new Microsoft.OpenApi.Models.OpenApiInfo
36 | {
37 | Title = "My API - V1",
38 | Version = "v1"
39 | }
40 | );
41 | });
42 |
43 | // uses a refined configuration (this will not log, as we added the MS Logger only to the configuration above
44 | services.AddCacheManagerConfiguration(Configuration, configure: builder => builder
45 | .WithJsonSerializer()
46 | .WithRedisConfiguration("redis", c => c.WithEndpoint("localhost", 6379))
47 | .WithRedisCacheHandle("redis"));
48 |
49 | // creates a completely new configuration for this instance (also not logging)
50 | services.AddCacheManager(inline => inline.WithDictionaryHandle());
51 |
52 | // any other type will be this. Configuration used will be the one defined by AddCacheManagerConfiguration earlier.
53 | services.AddCacheManager();
54 | }
55 |
56 | public void Configure(IApplicationBuilder app)
57 | {
58 | // give some error details in debug mode
59 | if (HostingEnvironment.IsDevelopment())
60 | {
61 | app.Use(async (ctx, next) =>
62 | {
63 | try
64 | {
65 | await next.Invoke();
66 | }
67 | catch (Exception ex)
68 | {
69 | await ctx.Response.WriteAsync($"{{\"error\": \"{ex}\"}}");
70 | }
71 | });
72 | }
73 |
74 | // lets redirect to the swagger UI, there is nothing else to display otherwise ;)
75 | app.Use(async (ctx, next) =>
76 | {
77 | if (ctx.Request.Path.StartsWithSegments("/"))
78 | {
79 | ctx.Response.Redirect("/swagger/");
80 | }
81 | else
82 | {
83 | await next.Invoke();
84 | }
85 | });
86 |
87 | app.UseStaticFiles();
88 | app.UseRouting();
89 | app.UseCors();
90 | app.UseAuthentication();
91 | app.UseAuthorization();
92 | app.UseEndpoints(b => b.MapControllers());
93 |
94 | app.UseSwagger();
95 | app.UseSwaggerUI(c =>
96 | {
97 | c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
98 | });
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/samples/AspNetCore/Web.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | true
6 | AspnetCore.WebApp
7 | Exe
8 | AspnetCore.WebApp
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/AspNetCore/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Debug",
5 | "CacheManager": "Trace",
6 | "System": "Error",
7 | "Microsoft": "Error"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/samples/AspNetCore/cache.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://cachemanager.michaco.net/schemas/cachemanager.json#",
3 | "cacheManagers": [
4 | {
5 | "name": "simpleMemoryCache",
6 | "handles": [
7 | {
8 | "knownType": "Dictionary"
9 | }
10 | ]
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/samples/AspNetCore/web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/CacheManager.Examples/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/CacheManager.Examples/CacheManager.Examples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CacheManager.Examples Console Application
5 | MICHA
6 | net8.0
7 | CacheManager.Examples
8 | Exe
9 | CacheManager.Examples
10 | false
11 | false
12 | false
13 | false
14 | false
15 | false
16 | false
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/samples/CacheManager.Examples/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("CacheManager.Examples")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CacheManager.Examples")]
13 | [assembly: AssemblyCopyright("Copyright © 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("8f8e0f73-f11a-4f9a-91f5-9c8e798752d9")]
24 |
--------------------------------------------------------------------------------
/src/CacheManager.Core/CacheManager.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | net472;netstandard2.0;netstandard2.1;net80
6 | False
7 | Caching;Cache;CacheManager;Distributed Cache;Redis;
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/CacheManager.Core/CacheUpdateMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace CacheManager.Core
4 | {
5 | ///
6 | /// Defines the possible update modes of the cache manager.
7 | ///
8 | /// Update mode works on Get operations. If the cache manager finds the cache item in one of the
9 | /// cache handles, and other cache handles do not have that item, it might add the item to the
10 | /// other cache handles depending on the mode.
11 | ///
12 | ///
13 | public enum CacheUpdateMode
14 | {
15 | ///
16 | /// Instructs the cache manager not to synchronize cache items with other cache handles (on for example).
17 | ///
18 | None,
19 |
20 | ///////
21 | /////// Full instructs the cache manager to add the cache item found to all cache
22 | /////// handles, except the one the item was found in.
23 | ///////
24 | ////[Obsolete("Will be removed in 1.0.0. I don't really see any actual value using this setting and it might actually cause issues.")]
25 | ////Full,
26 |
27 | ///
28 | /// Instructs the cache manager to synchronize cache items with other cache handles above in the list of cache handles.
29 | /// The order of cache handles is defined by the configuration.
30 | ///
31 | /// This is the default behavior and should only be turned off if really needed.
32 | ///
33 | ///
34 | Up
35 | }
36 | }
--------------------------------------------------------------------------------
/src/CacheManager.Core/ExpirationMode.cs:
--------------------------------------------------------------------------------
1 | namespace CacheManager.Core
2 | {
3 | ///
4 | /// Defines the supported expiration modes for cache items.
5 | /// Value None will indicate that no expiration should be set.
6 | ///
7 | public enum ExpirationMode
8 | {
9 | ///
10 | /// Default value for the expiration mode enum.
11 | /// CacheManager will default to None . The Default
entry in the enum is used as separation from the other values
12 | /// and to make it possible to explicitly set the expiration to None .
13 | ///
14 | Default = 0,
15 |
16 | ///
17 | /// Defines no expiration.
18 | ///
19 | None = 1,
20 |
21 | ///
22 | /// Defines sliding expiration. The expiration timeout will be refreshed on every access.
23 | ///
24 | Sliding = 2,
25 |
26 | ///
27 | /// Defines absolute expiration. The item will expire after the expiration timeout.
28 | ///
29 | Absolute = 3
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/CacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using CacheManager.Core.Utility;
4 |
5 | namespace CacheManager.Core.Internal
6 | {
7 | ///
8 | /// Base implementation for cache serializers.
9 | ///
10 | public abstract class CacheSerializer : ICacheSerializer
11 | {
12 | ///
13 | /// Returns the open generic type of this class.
14 | ///
15 | /// The type.
16 | protected abstract Type GetOpenGeneric();
17 |
18 | ///
19 | /// Creates a new instance of the serializer specific cache item.
20 | /// Items should implement and the implementation should call
21 | /// the second constructor taking exactly these two arguments.
22 | ///
23 | /// The item properties to copy from.
24 | /// The actual cache item value.
25 | /// The serializer specific cache item instance.
26 | /// The cache value type.
27 | protected abstract object CreateNewItem(ICacheItemProperties properties, object value);
28 |
29 | ///
30 | public abstract byte[] Serialize(T value);
31 |
32 | ///
33 | public abstract object Deserialize(byte[] data, Type target);
34 |
35 | ///
36 | public virtual byte[] SerializeCacheItem(CacheItem value)
37 | {
38 | Guard.NotNull(value, nameof(value));
39 | var item = CreateFromCacheItem(value);
40 | return Serialize(item);
41 | }
42 |
43 | ///
44 | public virtual CacheItem DeserializeCacheItem(byte[] value, Type valueType)
45 | {
46 | var targetType = GetOpenGeneric().MakeGenericType(valueType);
47 | var item = (ICacheItemConverter)Deserialize(value, targetType);
48 |
49 | return item?.ToCacheItem();
50 | }
51 |
52 | private object CreateFromCacheItem(CacheItem source)
53 | {
54 | var tType = typeof(TCacheValue);
55 |
56 | if (tType != source.ValueType || tType == TypeCache.ObjectType)
57 | {
58 | var targetType = GetOpenGeneric().MakeGenericType(source.ValueType);
59 | return Activator.CreateInstance(targetType, (ICacheItemProperties)source, source.Value);
60 | }
61 | else
62 | {
63 | return CreateNewItem((ICacheItemProperties)source, source.Value);
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/CacheStatsCounter.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 |
3 | namespace CacheManager.Core.Internal
4 | {
5 | internal sealed class CacheStatsCounter
6 | {
7 | private volatile long[] _counters = new long[9];
8 |
9 | public void Add(CacheStatsCounterType type, long value)
10 | {
11 | Interlocked.Add(ref _counters[(int)type], value);
12 | }
13 |
14 | public void Decrement(CacheStatsCounterType type)
15 | {
16 | Interlocked.Decrement(ref _counters[(int)type]);
17 | }
18 |
19 | public long Get(CacheStatsCounterType type) => _counters[(int)type];
20 |
21 | public void Increment(CacheStatsCounterType type)
22 | {
23 | Interlocked.Increment(ref _counters[(int)type]);
24 | }
25 |
26 | public void Set(CacheStatsCounterType type, long value)
27 | {
28 | Interlocked.Exchange(ref _counters[(int)type], value);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/CacheStatsCounterType.cs:
--------------------------------------------------------------------------------
1 | namespace CacheManager.Core.Internal
2 | {
3 | ///
4 | /// Defines the different counter types the cache manager supports.
5 | ///
6 | public enum CacheStatsCounterType
7 | {
8 | ///
9 | /// The number of hits.
10 | ///
11 | Hits,
12 |
13 | ///
14 | /// The number of misses.
15 | ///
16 | Misses,
17 |
18 | ///
19 | /// The total number of items.
20 | ///
21 | /// This might not be accurate in distribute cache scenarios because we count only the items
22 | /// added or removed locally.
23 | ///
24 | ///
25 | Items,
26 |
27 | ///
28 | /// The number of remove calls.
29 | ///
30 | RemoveCalls,
31 |
32 | ///
33 | /// The number of add calls.
34 | ///
35 | AddCalls,
36 |
37 | ///
38 | /// The number of put calls.
39 | ///
40 | PutCalls,
41 |
42 | ///
43 | /// The number of get calls.
44 | ///
45 | GetCalls,
46 |
47 | ///
48 | /// The number of clear calls.
49 | ///
50 | ClearCalls,
51 |
52 | ///
53 | /// The number of clear region calls.
54 | ///
55 | ClearRegionCalls
56 | }
57 | }
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/ICacheItemProperties.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace CacheManager.Core.Internal
4 | {
5 | ///
6 | /// Contract which exposes only the properties of the without T value.
7 | ///
8 | public interface ICacheItemProperties
9 | {
10 | ///
11 | /// Gets the creation date of the cache item.
12 | ///
13 | /// The creation date.
14 | DateTime CreatedUtc { get; }
15 |
16 | ///
17 | /// Gets the expiration mode.
18 | ///
19 | /// The expiration mode.
20 | ExpirationMode ExpirationMode { get; }
21 |
22 | ///
23 | /// Gets the expiration timeout.
24 | ///
25 | /// The expiration timeout.
26 | TimeSpan ExpirationTimeout { get; }
27 |
28 | ///
29 | /// Gets the cache key.
30 | ///
31 | /// The cache key.
32 | string Key { get; }
33 |
34 | ///
35 | /// Gets or sets the last accessed date of the cache item.
36 | ///
37 | /// The last accessed date.
38 | DateTime LastAccessedUtc { get; set; }
39 |
40 | ///
41 | /// Gets the cache region.
42 | ///
43 | /// The cache region.
44 | string Region { get; }
45 |
46 | ///
47 | /// Gets a value indicating whether the cache item uses the cache handle's configured expiration.
48 | ///
49 | bool UsesExpirationDefaults { get; }
50 |
51 | ///
52 | /// Gets the type of the cache value.
53 | /// This might be used for serialization and deserialization.
54 | ///
55 | /// The type of the cache value.
56 | Type ValueType { get; }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/ICacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace CacheManager.Core.Internal
4 | {
5 | ///
6 | /// Defines the contract for serialization of the cache value and cache items.
7 | /// The cache item serialization should be separated in case the serialization
8 | /// technology does not support immutable objects; in that case might not
9 | /// be serializable directly and the implementation has to wrap the cache item.
10 | ///
11 | public interface ICacheSerializer
12 | {
13 | ///
14 | /// Serializes the given and returns the serialized data as byte array.
15 | ///
16 | /// The type of the value.
17 | /// The value to serialize.
18 | /// The serialization result
19 | byte[] Serialize(T value);
20 |
21 | ///
22 | /// Deserializes the into the given Type .
23 | ///
24 | /// The data which should be deserialized.
25 | /// The type of the object to deserialize into.
26 | /// The deserialized object.
27 | object Deserialize(byte[] data, Type target);
28 |
29 | ///
30 | /// Serializes the given .
31 | ///
32 | /// The type of the cache value.
33 | /// The value to serialize.
34 | /// The serialized result.
35 | byte[] SerializeCacheItem(CacheItem value);
36 |
37 | ///
38 | /// Deserializes the into a .
39 | /// The must not match the in case
40 | /// is object for example, the
41 | /// might be the real type of the value. This is needed to properly deserialize in some cases.
42 | ///
43 | /// The type of the cache value.
44 | /// The data to deserialize from.
45 | /// The type of the actual serialized cache value.
46 | /// The deserialized cache item.
47 | CacheItem DeserializeCacheItem(byte[] value, Type valueType);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/CacheManager.Core/Internal/RequiresSerializerAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace CacheManager.Core.Internal
5 | {
6 | ///
7 | /// Can be used to decorate cache handles which require serialization
8 | ///
9 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
10 | public sealed class RequiresSerializerAttribute : Attribute
11 | {
12 | }
13 | }
--------------------------------------------------------------------------------
/src/CacheManager.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | [assembly: CLSCompliant(true)]
3 |
--------------------------------------------------------------------------------
/src/CacheManager.Microsoft.Extensions.Caching.Memory/CacheManager.Microsoft.Extensions.Caching.Memory.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | MichaConrad;AuroraDysis
6 | netstandard2.0;net8.0
7 | true
8 | true
9 | Caching;Cache;CacheManager;MemoryCache
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/CacheManager.Microsoft.Extensions.Caching.Memory/MemoryCacheExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Concurrent;
2 | using Microsoft.Extensions.Caching.Memory;
3 |
4 | namespace CacheManager.MicrosoftCachingMemory
5 | {
6 | ///
7 | /// Extensions for the configuration builder specific to Microsoft.Extensions.Caching.Memory cache handle.
8 | ///
9 | internal static class MemoryCacheExtensions
10 | {
11 | ///
12 | /// Extension method to check if a key exists in the given instance.
13 | ///
14 | /// The cache instance.
15 | /// The key.
16 | /// True if the key exists.
17 | public static bool Contains(this MemoryCache cache, object key)
18 | {
19 | object temp;
20 | return cache.TryGetValue(key, out temp);
21 | }
22 |
23 | internal static void RegisterChild(this MemoryCache cache, object parentKey, object childKey)
24 | {
25 | if (cache.TryGetValue(parentKey, out var keys))
26 | {
27 | var keySet = (ConcurrentDictionary)keys;
28 | keySet.TryAdd(childKey, true);
29 | }
30 | }
31 |
32 | internal static void RemoveChilds(this MemoryCache cache, object region)
33 | {
34 | if (cache.TryGetValue(region, out var keys))
35 | {
36 | var keySet = (ConcurrentDictionary)keys;
37 | foreach (var key in keySet.Keys)
38 | {
39 | cache.Remove(key);
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/CacheManager.Microsoft.Extensions.Caching.Memory/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | [assembly: CLSCompliant(true)]
5 | [assembly: InternalsVisibleTo("CacheManager.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051a13aa6dd4e78f62051f0d2608ba1e1e50f7038dad1e72f6a2233ec77ec58d49eec5ba13b0f7508d11fbbcd79ee39b0322b58873962771396ec08096f5d4bd2d1622ed9cad79016c154397390336a4a5a619aeec126f8d54b9ea884c510267d1d413ab5afc3c1aea86c199e57ecb23bd39458528328d2de90050e11d4649ec3")]
--------------------------------------------------------------------------------
/src/CacheManager.Microsoft.Extensions.Configuration/CacheManager.Microsoft.Extensions.Configuration.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | netstandard2.0;net8.0
6 | true
7 | true
8 | Caching;Cache;CacheManager;Distributed Cache;Configuration
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondCacheItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Bond;
4 | using CacheManager.Core;
5 | using CacheManager.Core.Internal;
6 |
7 | namespace CacheManager.Serialization.Bond
8 | {
9 | [Schema]
10 | internal class BondCacheItem : SerializerCacheItem
11 | {
12 | public BondCacheItem()
13 | {
14 | }
15 |
16 | public BondCacheItem(ICacheItemProperties properties, object value) : base(properties, value)
17 | {
18 | }
19 |
20 | [Id(1)]
21 | public override long CreatedUtc { get; set; }
22 |
23 | [Id(2)]
24 | public override ExpirationMode ExpirationMode { get; set; }
25 |
26 | [Id(3)]
27 | public override double ExpirationTimeout { get; set; }
28 |
29 | [Id(4)]
30 | public override string Key { get; set; }
31 |
32 | [Id(5)]
33 | public override long LastAccessedUtc { get; set; }
34 |
35 | [Id(6)]
36 | public override string Region { get; set; }
37 |
38 | [Id(7)]
39 | public override string ValueType { get; set; }
40 |
41 | [Id(8)]
42 | public override bool UsesExpirationDefaults { get; set; }
43 |
44 | [Id(9)]
45 | public override T Value { get; set; }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondCompactBinaryCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Bond;
4 | using Bond.IO.Unsafe;
5 | using Bond.Protocols;
6 | using CacheManager.Core.Internal;
7 |
8 | namespace CacheManager.Serialization.Bond
9 | {
10 | ///
11 | /// Implements the contract using Microsoft.Bond .
12 | ///
13 | public class BondCompactBinaryCacheSerializer : BondSerializerBase
14 | {
15 | private readonly BinarySerializerCache _cache;
16 |
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | public BondCompactBinaryCacheSerializer() : base()
21 | {
22 | _cache = new BinarySerializerCache();
23 | }
24 |
25 | ///
26 | /// Initializes a new instance of the class.
27 | ///
28 | /// The default buffer size.
29 | public BondCompactBinaryCacheSerializer(int defaultBufferSize) : base(defaultBufferSize)
30 | {
31 | _cache = new BinarySerializerCache();
32 | }
33 |
34 | ///
35 | public override byte[] Serialize(T value)
36 | {
37 | var serializer = _cache.GetSerializer(value.GetType());
38 | var buffer = OutputBufferPool.Get();
39 | var writer = _cache.CreateWriter(buffer);
40 |
41 | serializer.Serialize(value, writer);
42 |
43 | var bytes = new byte[buffer.Data.Count];
44 | Buffer.BlockCopy(buffer.Data.Array, 0, bytes, 0, buffer.Data.Count);
45 | OutputBufferPool.Return(buffer);
46 | return bytes;
47 | }
48 |
49 | ///
50 | public override object Deserialize(byte[] data, Type target)
51 | {
52 | var deserializer = _cache.GetDeserializer(target);
53 | var buffer = new InputBuffer(data);
54 | var reader = _cache.CreateReader(buffer);
55 |
56 | return deserializer.Deserialize(reader);
57 | }
58 |
59 | private class BinarySerializerCache : SerializerCache, CompactBinaryReader>
60 | {
61 | public override CompactBinaryReader CreateReader(InputBuffer buffer)
62 | {
63 | return new CompactBinaryReader(buffer);
64 | }
65 |
66 | public override CompactBinaryWriter CreateWriter(OutputBuffer buffer)
67 | {
68 | return new CompactBinaryWriter(buffer);
69 | }
70 |
71 | protected override Deserializer> CreateDeserializer(Type type)
72 | {
73 | return new Deserializer>(type);
74 | }
75 |
76 | protected override Serializer> CreateSerializer(Type type)
77 | {
78 | return new Serializer>(type);
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CacheManager.Serialization.Bond;
3 |
4 | namespace CacheManager.Core
5 | {
6 | ///
7 | /// Extensions for the configuration builder for the Microsoft.Bond
based .
8 | ///
9 | public static class BondConfigurationBuilderExtensions
10 | {
11 | ///
12 | /// Configures the cache manager to use the Microsoft.Bond
based cache serializer.
13 | /// This version uses and .
14 | ///
15 | /// The configuration part.
16 | /// The buffer size used to serialize objects. Can be used to tune Bond performance.
17 | /// The builder instance.
18 | public static ConfigurationBuilderCachePart WithBondCompactBinarySerializer(this ConfigurationBuilderCachePart part, int defaultWriteBufferSize = 1024)
19 | {
20 | if (part is null)
21 | {
22 | throw new ArgumentNullException(nameof(part));
23 | }
24 |
25 | return part.WithSerializer(typeof(BondCompactBinaryCacheSerializer), defaultWriteBufferSize);
26 | }
27 |
28 | ///
29 | /// Configures the cache manager to use the Microsoft.Bond
based cache serializer.
30 | /// This version uses and .
31 | ///
32 | /// The configuration part.
33 | /// The buffer size used to serialize objects. Can be used to tune Bond performance.
34 | /// The builder instance.
35 | public static ConfigurationBuilderCachePart WithBondFastBinarySerializer(this ConfigurationBuilderCachePart part, int defaultWriteBufferSize = 1024)
36 | {
37 | if (part is null)
38 | {
39 | throw new ArgumentNullException(nameof(part));
40 | }
41 |
42 | return part.WithSerializer(typeof(BondFastBinaryCacheSerializer), defaultWriteBufferSize);
43 | }
44 |
45 | ///
46 | /// Configures the cache manager to use the Microsoft.Bond
based cache serializer.
47 | /// This version uses and .
48 | ///
49 | /// The configuration part.
50 | /// The builder instance.
51 | public static ConfigurationBuilderCachePart WithBondSimpleJsonSerializer(this ConfigurationBuilderCachePart part)
52 | {
53 | if (part is null)
54 | {
55 | throw new ArgumentNullException(nameof(part));
56 | }
57 |
58 | return part.WithSerializer(typeof(BondSimpleJsonCacheSerializer));
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondFastBinaryCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using Bond;
4 | using Bond.IO.Unsafe;
5 | using Bond.Protocols;
6 | using CacheManager.Core.Internal;
7 |
8 | namespace CacheManager.Serialization.Bond
9 | {
10 | ///
11 | /// Implements the contract using Microsoft.Bond .
12 | ///
13 | public class BondFastBinaryCacheSerializer : BondSerializerBase
14 | {
15 | private readonly FastBinarySerializerCache _cache;
16 |
17 | ///
18 | /// Initializes a new instance of the class.
19 | ///
20 | public BondFastBinaryCacheSerializer() : base()
21 | {
22 | _cache = new FastBinarySerializerCache();
23 | }
24 |
25 | ///
26 | /// Initializes a new instance of the class.
27 | ///
28 | /// The default buffer size.
29 | public BondFastBinaryCacheSerializer(int defaultWriteBufferSize) : base(defaultWriteBufferSize)
30 | {
31 | _cache = new FastBinarySerializerCache();
32 | }
33 |
34 | ///
35 | public override byte[] Serialize(T value)
36 | {
37 | var serializer = _cache.GetSerializer(value.GetType());
38 | var buffer = OutputBufferPool.Get();
39 | var writer = _cache.CreateWriter(buffer);
40 |
41 | serializer.Serialize(value, writer);
42 |
43 | var bytes = new byte[buffer.Data.Count];
44 | Buffer.BlockCopy(buffer.Data.Array, 0, bytes, 0, buffer.Data.Count);
45 | OutputBufferPool.Return(buffer);
46 | return bytes;
47 | }
48 |
49 | ///
50 | public override object Deserialize(byte[] data, Type target)
51 | {
52 | var deserializer = _cache.GetDeserializer(target);
53 | var buffer = new InputBuffer(data);
54 | var reader = _cache.CreateReader(buffer);
55 |
56 | return deserializer.Deserialize(reader);
57 | }
58 |
59 | private class FastBinarySerializerCache : SerializerCache, FastBinaryReader>
60 | {
61 | public override FastBinaryReader CreateReader(InputBuffer buffer)
62 | {
63 | return new FastBinaryReader(buffer);
64 | }
65 |
66 | public override FastBinaryWriter CreateWriter(OutputBuffer buffer)
67 | {
68 | return new FastBinaryWriter(buffer);
69 | }
70 |
71 | protected override Deserializer> CreateDeserializer(Type type)
72 | {
73 | return new Deserializer>(type);
74 | }
75 |
76 | protected override Serializer> CreateSerializer(Type type)
77 | {
78 | return new Serializer>(type);
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondSerializerBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using Bond.IO.Unsafe;
4 | using CacheManager.Core.Internal;
5 | using Microsoft.Extensions.ObjectPool;
6 |
7 | namespace CacheManager.Serialization.Bond
8 | {
9 | ///
10 | /// Base class for Bond based serializers
11 | ///
12 | public abstract class BondSerializerBase : CacheSerializer
13 | {
14 | private static readonly Type _openItemType = typeof(BondCacheItem<>);
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | public BondSerializerBase()
20 | : this(1024)
21 | {
22 | }
23 |
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | /// The default buffer size.
28 | public BondSerializerBase(int defaultBufferSize)
29 | {
30 | OutputBufferPool = new DefaultObjectPool(new OutputBufferPoolPolicy(defaultBufferSize));
31 | StringBuilderPool = new DefaultObjectPool(new StringBuilderPoolPolicy(defaultBufferSize));
32 | }
33 |
34 | ///
35 | /// Gets a pool handling s.
36 | ///
37 | [CLSCompliant(false)]
38 | protected ObjectPool OutputBufferPool { get; }
39 |
40 | ///
41 | /// Gets a pool handling s.
42 | ///
43 | [CLSCompliant(false)]
44 | protected ObjectPool StringBuilderPool { get; }
45 |
46 | ///
47 | protected override Type GetOpenGeneric()
48 | {
49 | return _openItemType;
50 | }
51 |
52 | ///
53 | protected override object CreateNewItem(ICacheItemProperties properties, object value)
54 | {
55 | return new BondCacheItem(properties, value);
56 | }
57 |
58 | private class OutputBufferPoolPolicy : IPooledObjectPolicy
59 | {
60 | private readonly int _defaultBufferSize;
61 |
62 | public OutputBufferPoolPolicy(int defaultBufferSize)
63 | {
64 | _defaultBufferSize = defaultBufferSize;
65 | }
66 |
67 | public OutputBuffer Create()
68 | {
69 | return new OutputBuffer(_defaultBufferSize);
70 | }
71 |
72 | public bool Return(OutputBuffer value)
73 | {
74 | ////if (value.Data.Count > _defaultBufferSize * 1000)
75 | ////{
76 | //// return false;
77 | ////}
78 |
79 | value.Position = 0;
80 | return true;
81 | }
82 | }
83 |
84 | private class StringBuilderPoolPolicy : IPooledObjectPolicy
85 | {
86 | private readonly int _defaultBufferSize;
87 |
88 | public StringBuilderPoolPolicy(int defaultBufferSize)
89 | {
90 | _defaultBufferSize = defaultBufferSize;
91 | }
92 |
93 | public StringBuilder Create()
94 | {
95 | return new StringBuilder(_defaultBufferSize);
96 | }
97 |
98 | public bool Return(StringBuilder value)
99 | {
100 | ////if (value.Data.Count > _defaultBufferSize * 1000)
101 | ////{
102 | //// return false;
103 | ////}
104 |
105 | value.Clear();
106 | return true;
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/BondSimpleJsonCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Text;
5 | using Bond;
6 | using Bond.IO.Unsafe;
7 | using Bond.Protocols;
8 | using CacheManager.Core.Internal;
9 |
10 | namespace CacheManager.Serialization.Bond
11 | {
12 | ///
13 | /// Implements the contract using Microsoft.Bond .
14 | ///
15 | public class BondSimpleJsonCacheSerializer : BondSerializerBase
16 | {
17 | private readonly SimpleJsonSerializerCache _cache;
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | public BondSimpleJsonCacheSerializer() : base()
23 | {
24 | _cache = new SimpleJsonSerializerCache();
25 | }
26 |
27 | ///
28 | /// Initializes a new instance of the class.
29 | ///
30 | /// The default buffer size.
31 | public BondSimpleJsonCacheSerializer(int defaultWriteBufferSize) : base(defaultWriteBufferSize)
32 | {
33 | _cache = new SimpleJsonSerializerCache();
34 | }
35 |
36 | ///
37 | public override byte[] Serialize(T value)
38 | {
39 | var serializer = _cache.GetSerializer(value.GetType());
40 | var buffer = StringBuilderPool.Get();
41 |
42 | using (var stringWriter = new StringWriter(buffer))
43 | {
44 | var writer = new SimpleJsonWriter(stringWriter);
45 | serializer.Serialize(value, writer);
46 |
47 | var bytes = Encoding.UTF8.GetBytes(buffer.ToString());
48 | StringBuilderPool.Return(buffer);
49 | return bytes;
50 | }
51 | }
52 |
53 | ///
54 | public override object Deserialize(byte[] data, Type target)
55 | {
56 | var deserializer = _cache.GetDeserializer(target);
57 |
58 | var value = Encoding.UTF8.GetString(data, 0, data.Length);
59 | using (var reader = new StringReader(value))
60 | {
61 | var jsonReader = new SimpleJsonReader(reader);
62 | return deserializer.Deserialize(jsonReader);
63 | }
64 | }
65 |
66 | private class SimpleJsonSerializerCache : SerializerCache
67 | {
68 | public override SimpleJsonReader CreateReader(InputBuffer buffer)
69 | {
70 | throw new NotImplementedException();
71 | }
72 |
73 | public override SimpleJsonWriter CreateWriter(OutputBuffer buffer)
74 | {
75 | throw new NotImplementedException();
76 | }
77 |
78 | protected override Deserializer CreateDeserializer(Type type)
79 | {
80 | return new Deserializer(type);
81 | }
82 |
83 | protected override Serializer CreateSerializer(Type type)
84 | {
85 | return new Serializer(type);
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/CacheManager.Serialization.Bond.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | netstandard2.0;net8.0
6 | true
7 | true
8 | Caching;Cache;CacheManager;Serialization;Bond
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | [assembly: CLSCompliant(true)]
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Bond/SerializerCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Linq;
4 | using Bond;
5 | using Bond.IO.Unsafe;
6 |
7 | namespace CacheManager.Serialization.Bond
8 | {
9 | internal abstract class SerializerCache
10 | {
11 | private static readonly ConcurrentDictionary> _serializers = new ConcurrentDictionary>();
12 | private static readonly ConcurrentDictionary> _deserializers = new ConcurrentDictionary>();
13 |
14 | public Serializer GetSerializer(Type type)
15 | {
16 | Serializer serializer;
17 | if (!_serializers.TryGetValue(type, out serializer))
18 | {
19 | serializer = CreateSerializer(type);
20 | _serializers.TryAdd(type, serializer);
21 | }
22 |
23 | return serializer;
24 | }
25 |
26 | public Deserializer GetDeserializer(Type type)
27 | {
28 | Deserializer deserializer;
29 | if (!_deserializers.TryGetValue(type, out deserializer))
30 | {
31 | deserializer = CreateDeserializer(type);
32 | _deserializers.TryAdd(type, deserializer);
33 | }
34 |
35 | return deserializer;
36 | }
37 |
38 | public abstract TWriter CreateWriter(OutputBuffer buffer);
39 |
40 | public abstract TReader CreateReader(InputBuffer buffer);
41 |
42 | protected abstract Serializer CreateSerializer(Type type);
43 |
44 | protected abstract Deserializer CreateDeserializer(Type type);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/CacheManager.Serialization.DataContract.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | netstandard2.0
6 | true
7 | true
8 | Caching;Cache;CacheManager;Serialization;DataContract
9 | rebulanyum, MichaConrad
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/DataContractBinaryCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.Serialization;
4 | using System.Xml;
5 |
6 | namespace CacheManager.Serialization.DataContract
7 | {
8 | ///
9 | /// This class (de)serializes objects with binary format via using DataContractSerializer .
10 | ///
11 | public class DataContractBinaryCacheSerializer : DataContractCacheSerializer
12 | {
13 | ///
14 | /// Creates instance of DataContractBinaryCacheSerializer .
15 | ///
16 | public DataContractBinaryCacheSerializer() : this(new DataContractSerializerSettings())
17 | {
18 | }
19 |
20 | ///
21 | /// Creates instance of DataContractBinaryCacheSerializer .
22 | ///
23 | /// The settings for DataContractSerializer .
24 | public DataContractBinaryCacheSerializer(DataContractSerializerSettings serializerSettings = null) : base(serializerSettings)
25 | {
26 | }
27 |
28 | ///
29 | protected override object ReadObject(XmlObjectSerializer serializer, Stream stream)
30 | {
31 | var binaryDictionaryReader = XmlDictionaryReader.CreateBinaryReader(stream, new XmlDictionaryReaderQuotas());
32 | return serializer.ReadObject(binaryDictionaryReader);
33 | }
34 |
35 | ///
36 | protected override void WriteObject(XmlObjectSerializer serializer, Stream stream, object graph)
37 | {
38 | var binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream);
39 | serializer.WriteObject(binaryDictionaryWriter, graph);
40 | binaryDictionaryWriter.Flush();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/DataContractCacheItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 | using CacheManager.Core;
4 | using CacheManager.Core.Internal;
5 |
6 | namespace CacheManager.Serialization.DataContract
7 | {
8 | ///
9 | /// The data contract cache item will be used to serialize a .
10 | /// A cannot be deserialized by DataContractSerializer because of the private setters.
11 | ///
12 | [DataContract]
13 | internal class DataContractCacheItem : SerializerCacheItem
14 | {
15 | public DataContractCacheItem()
16 | {
17 | }
18 |
19 | public DataContractCacheItem(ICacheItemProperties properties, object value) : base(properties, value)
20 | {
21 | }
22 |
23 | [DataMember(Name = "createdUtc")]
24 | public override long CreatedUtc { get; set; }
25 |
26 | [DataMember(Name = "expirationMode")]
27 | public override ExpirationMode ExpirationMode { get; set; }
28 |
29 | [DataMember(Name = "expirationTimeout")]
30 | public override double ExpirationTimeout { get; set; }
31 |
32 | [DataMember(Name = "key")]
33 | public override string Key { get; set; }
34 |
35 | [DataMember(Name = "lastAccessedUtc")]
36 | public override long LastAccessedUtc { get; set; }
37 |
38 | [DataMember(Name = "region")]
39 | public override string Region { get; set; }
40 |
41 | [DataMember(Name = "value")]
42 | public override T Value { get; set; }
43 |
44 | [DataMember(Name = "usesExpirationDefaults")]
45 | public override bool UsesExpirationDefaults { get; set; }
46 |
47 | [DataMember(Name = "valueType")]
48 | public override string ValueType { get; set; }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/DataContractCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 |
4 | namespace CacheManager.Serialization.DataContract
5 | {
6 | ///
7 | /// This class uses DataContractSerializer for (de)serialization.
8 | ///
9 | public class DataContractCacheSerializer : DataContractCacheSerializerBase
10 | {
11 | ///
12 | /// Creates instance of DataContractCacheSerializer .
13 | ///
14 | public DataContractCacheSerializer() : this(new DataContractSerializerSettings())
15 | {
16 | }
17 |
18 | ///
19 | /// Creates instance of DataContractCacheSerializer .
20 | ///
21 | /// The settings for DataContractSerializer .
22 | public DataContractCacheSerializer(DataContractSerializerSettings serializerSettings = null) : base(serializerSettings)
23 | {
24 | }
25 |
26 | ///
27 | protected override XmlObjectSerializer GetSerializer(Type target)
28 | {
29 | if (SerializerSettings == null)
30 | {
31 | return new DataContractSerializer(target);
32 | }
33 | else
34 | {
35 | return new DataContractSerializer(target, SerializerSettings);
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/DataContractGzJsonCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.IO.Compression;
4 | using System.Runtime.Serialization;
5 | using System.Runtime.Serialization.Json;
6 |
7 | namespace CacheManager.Serialization.DataContract
8 | {
9 | ///
10 | /// This class (de)compresses the (de)serialized output of DataContractJsonCacheSerializer .
11 | ///
12 | public class DataContractGzJsonCacheSerializer : DataContractJsonCacheSerializer
13 | {
14 | ///
15 | /// Creates instance of DataContractGzJsonCacheSerializer .
16 | ///
17 | public DataContractGzJsonCacheSerializer() : this(new DataContractJsonSerializerSettings())
18 | {
19 | }
20 |
21 | ///
22 | /// Creates instance of DataContractGzJsonCacheSerializer .
23 | ///
24 | /// Serializer's settings
25 | public DataContractGzJsonCacheSerializer(DataContractJsonSerializerSettings serializerSettings = null) : base(serializerSettings)
26 | {
27 | }
28 |
29 | ///
30 | protected override void WriteObject(XmlObjectSerializer serializer, Stream stream, object graph)
31 | {
32 | using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, true))
33 | {
34 | base.WriteObject(serializer, gzipStream, graph);
35 | gzipStream.Flush();
36 | }
37 | }
38 |
39 | ///
40 | protected override object ReadObject(XmlObjectSerializer serializer, Stream stream)
41 | {
42 | using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress))
43 | {
44 | return base.ReadObject(serializer, gzipStream);
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/DataContractJsonCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.Serialization;
3 | using System.Runtime.Serialization.Json;
4 |
5 | namespace CacheManager.Serialization.DataContract
6 | {
7 | ///
8 | /// This class uses DataContractJsonSerialzer for (de)serialization.
9 | ///
10 | public class DataContractJsonCacheSerializer : DataContractCacheSerializerBase
11 | {
12 | ///
13 | /// Creates instance of DataContractJsonCacheSerializer .
14 | ///
15 | public DataContractJsonCacheSerializer() : this(new DataContractJsonSerializerSettings())
16 | {
17 | }
18 |
19 | ///
20 | /// Creates instance of DataContractJsonCacheSerializer .
21 | ///
22 | /// Serializer's settings
23 | public DataContractJsonCacheSerializer(DataContractJsonSerializerSettings serializerSettings = null) : base(serializerSettings)
24 | {
25 | }
26 |
27 | ///
28 | protected override XmlObjectSerializer GetSerializer(Type target)
29 | {
30 | if (SerializerSettings == null)
31 | {
32 | return new DataContractJsonSerializer(target);
33 | }
34 | else
35 | {
36 | return new DataContractJsonSerializer(target, SerializerSettings);
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.DataContract/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | [assembly: CLSCompliant(true)]
4 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Json/CacheManager.Serialization.Json.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | netstandard2.0;net8.0
6 | true
7 | true
8 | Caching;Cache;CacheManager;Distributed Cache;JSON;Serialization
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Json/GzJsonCacheSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.IO.Compression;
4 | using Newtonsoft.Json;
5 |
6 | namespace CacheManager.Serialization.Json
7 | {
8 | ///
9 | /// Implements the ICacheSerializer contract using Newtonsoft.Json and the lossless compression.
10 | ///
11 | public class GzJsonCacheSerializer : JsonCacheSerializer
12 | {
13 | ///
14 | /// Initializes a new instance of the class.
15 | ///
16 | public GzJsonCacheSerializer()
17 | : base(new JsonSerializerSettings(), new JsonSerializerSettings())
18 | {
19 | }
20 |
21 | ///
22 | /// Initializes a new instance of the class.
23 | /// With this overload the settings for de-/serialization can be set independently.
24 | ///
25 | /// The settings which should be used during serialization.
26 | /// The settings which should be used during deserialization.
27 | public GzJsonCacheSerializer(JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings)
28 | : base(serializationSettings, deserializationSettings)
29 | {
30 | }
31 |
32 | ///
33 | public override object Deserialize(byte[] data, Type target)
34 | {
35 | if (data is null)
36 | {
37 | throw new ArgumentNullException(nameof(data));
38 | }
39 |
40 | var compressedData = Decompression(data);
41 |
42 | return base.Deserialize(compressedData, target);
43 | }
44 |
45 | ///
46 | public override byte[] Serialize(T value)
47 | {
48 | var data = base.Serialize(value);
49 |
50 | return Compression(data);
51 | }
52 |
53 | ///
54 | /// Compress the serialized using .
55 | ///
56 | /// The data which should be compressed.
57 | /// The compressed data.
58 | protected virtual byte[] Compression(byte[] data)
59 | {
60 | using (var bytesBuilder = new MemoryStream())
61 | {
62 | using (var gzWriter = new GZipStream(bytesBuilder, CompressionLevel.Fastest, true))
63 | {
64 | gzWriter.Write(data, 0, data.Length);
65 | bytesBuilder.Flush();
66 | }
67 |
68 | return bytesBuilder.ToArray();
69 | }
70 | }
71 |
72 | ///
73 | /// Decompress the into the base serialized data.
74 | ///
75 | /// The data which should be decompressed.
76 | /// The uncompressed data.
77 | protected virtual byte[] Decompression(byte[] compressedData)
78 | {
79 | var buffer = new byte[compressedData.Length * 2];
80 | using (var inputStream = new MemoryStream(compressedData, 0, compressedData.Length))
81 | using (var gzReader = new GZipStream(inputStream, CompressionMode.Decompress))
82 | using (var stream = new MemoryStream(compressedData.Length * 2))
83 | {
84 | var readBytes = 0;
85 | while ((readBytes = gzReader.Read(buffer, 0, buffer.Length)) > 0)
86 | {
87 | stream.Write(buffer, 0, readBytes);
88 | }
89 |
90 | return stream.ToArray();
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Json/JsonCacheItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CacheManager.Core.Internal;
3 | using Newtonsoft.Json;
4 |
5 | namespace CacheManager.Core
6 | {
7 | internal class JsonCacheItem : SerializerCacheItem
8 | {
9 | [JsonConstructor]
10 | public JsonCacheItem()
11 | {
12 | }
13 |
14 | public JsonCacheItem(ICacheItemProperties properties, object value) : base(properties, value)
15 | {
16 | }
17 |
18 | [JsonProperty("createdUtc")]
19 | public override long CreatedUtc { get; set; }
20 |
21 | [JsonProperty("expirationMode")]
22 | public override ExpirationMode ExpirationMode { get; set; }
23 |
24 | [JsonProperty("expirationTimeout")]
25 | public override double ExpirationTimeout { get; set; }
26 |
27 | [JsonProperty("key")]
28 | public override string Key { get; set; }
29 |
30 | [JsonProperty("lastAccessedUtc")]
31 | public override long LastAccessedUtc { get; set; }
32 |
33 | [JsonProperty("region")]
34 | public override string Region { get; set; }
35 |
36 | [JsonProperty("usesDefaultExpiration")]
37 | public override bool UsesExpirationDefaults { get; set; }
38 |
39 | [JsonProperty("valueType")]
40 | public override string ValueType { get; set; }
41 |
42 | [JsonProperty("value")]
43 | public override T Value { get; set; }
44 | }
45 | }
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Json/JsonConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CacheManager.Serialization.Json;
3 | using Newtonsoft.Json;
4 |
5 | namespace CacheManager.Core
6 | {
7 | ///
8 | /// Extensions for the configuration builder for the Newtonsoft.Json based ICacheSerializer .
9 | ///
10 | public static class JsonConfigurationBuilderExtensions
11 | {
12 | ///
13 | /// Configures the cache manager to use the Newtonsoft.Json
based cache serializer.
14 | ///
15 | /// The configuration part.
16 | /// The builder instance.
17 | public static ConfigurationBuilderCachePart WithJsonSerializer(this ConfigurationBuilderCachePart part)
18 | {
19 | if (part is null)
20 | {
21 | throw new ArgumentNullException(nameof(part));
22 | }
23 |
24 | return part.WithSerializer(typeof(JsonCacheSerializer));
25 | }
26 |
27 | ///
28 | /// Configures the cache manager to use the Newtonsoft.Json
based cache serializer.
29 | ///
30 | /// The configuration part.
31 | /// The settings to be used during serialization.
32 | /// The settings to be used during deserialization.
33 | /// The builder instance.
34 | public static ConfigurationBuilderCachePart WithJsonSerializer(this ConfigurationBuilderCachePart part, JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings)
35 | {
36 | if (part is null)
37 | {
38 | throw new ArgumentNullException(nameof(part));
39 | }
40 |
41 | return part.WithSerializer(typeof(JsonCacheSerializer), serializationSettings, deserializationSettings);
42 | }
43 |
44 | ///
45 | /// Configures the cache manager to use the Newtonsoft.Json
based cache serializer with compression.
46 | ///
47 | /// The configuration part.
48 | /// The builder instance.
49 | public static ConfigurationBuilderCachePart WithGzJsonSerializer(this ConfigurationBuilderCachePart part)
50 | {
51 | if (part is null)
52 | {
53 | throw new ArgumentNullException(nameof(part));
54 | }
55 |
56 | return part.WithSerializer(typeof(GzJsonCacheSerializer));
57 | }
58 |
59 | ///
60 | /// Configures the cache manager to use the Newtonsoft.Json
based cache serializer with compression.
61 | ///
62 | /// The configuration part.
63 | /// The settings to be used during serialization.
64 | /// The settings to be used during deserialization.
65 | /// The builder instance.
66 | public static ConfigurationBuilderCachePart WithGzJsonSerializer(this ConfigurationBuilderCachePart part, JsonSerializerSettings serializationSettings, JsonSerializerSettings deserializationSettings)
67 | {
68 | if (part is null)
69 | {
70 | throw new ArgumentNullException(nameof(part));
71 | }
72 |
73 | return part.WithSerializer(typeof(GzJsonCacheSerializer), serializationSettings, deserializationSettings);
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.Json/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | [assembly: CLSCompliant(true)]
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.ProtoBuf/CacheManager.Serialization.ProtoBuf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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
5 | Wenisman;MichaConrad
6 | netstandard2.0;net6.0;net8.0
7 | true
8 | true
9 | Caching;Cache;CacheManager;Distributed Cache;Serialization;Protobuf
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.ProtoBuf/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | [assembly: CLSCompliant(true)]
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.ProtoBuf/ProtoBufCacheItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CacheManager.Core;
3 | using CacheManager.Core.Internal;
4 | using ProtoBuf;
5 |
6 | namespace CacheManager.Serialization.ProtoBuf
7 | {
8 | [ProtoContract]
9 | internal class ProtoBufCacheItem : SerializerCacheItem
10 | {
11 | // needed so the serializer can deserialize the item using the empty ctor.
12 | public ProtoBufCacheItem()
13 | {
14 | }
15 |
16 | public ProtoBufCacheItem(ICacheItemProperties properties, object value) : base(properties, value)
17 | {
18 | }
19 |
20 | [ProtoMember(1)]
21 | public override long CreatedUtc { get; set; }
22 |
23 | [ProtoMember(2)]
24 | public override long LastAccessedUtc { get; set; }
25 |
26 | [ProtoMember(3)]
27 | public override ExpirationMode ExpirationMode { get; set; }
28 |
29 | [ProtoMember(4)]
30 | public override double ExpirationTimeout { get; set; }
31 |
32 | [ProtoMember(5)]
33 | public override string Key { get; set; }
34 |
35 | [ProtoMember(6)]
36 | public override string Region { get; set; }
37 |
38 | [ProtoMember(7)]
39 | public override T Value { get; set; }
40 |
41 | [ProtoMember(8)]
42 | public override string ValueType { get; set; }
43 |
44 | [ProtoMember(9)]
45 | public override bool UsesExpirationDefaults { get; set; }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.ProtoBuf/ProtoBufConfigurationBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using CacheManager.Serialization.ProtoBuf;
3 |
4 | namespace CacheManager.Core
5 | {
6 | ///
7 | /// Configuration builder extensions for the ProtoBuf based .
8 | ///
9 | public static class ProtoBufConfigurationBuilderExtensions
10 | {
11 | ///
12 | /// Configures the cache manager to use the ProtoBuf
based cache serializer.
13 | ///
14 | /// The configuration part.
15 | /// The builder instance.
16 | public static ConfigurationBuilderCachePart WithProtoBufSerializer(this ConfigurationBuilderCachePart part)
17 | {
18 | if (part is null)
19 | {
20 | throw new ArgumentNullException(nameof(part));
21 | }
22 |
23 | return part.WithSerializer(typeof(ProtoBufSerializer));
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/CacheManager.Serialization.ProtoBuf/ProtoBufSerializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using CacheManager.Core.Internal;
4 | using ProtoBuf;
5 |
6 | namespace CacheManager.Serialization.ProtoBuf
7 | {
8 | ///
9 | /// Implements the contract using ProtoBuf .
10 | ///
11 | public class ProtoBufSerializer : CacheSerializer
12 | {
13 | private static readonly Type _openGenericItemType = typeof(ProtoBufCacheItem<>);
14 |
15 | ///
16 | public override object Deserialize(byte[] data, Type target)
17 | {
18 | var offset = 0;
19 | if (data.Length > 0)
20 | {
21 | offset = 1;
22 | }
23 |
24 | using (var stream = new MemoryStream(data, offset, data.Length - offset))
25 | {
26 | return Serializer.Deserialize(target, stream);
27 | }
28 | }
29 |
30 | ///
31 | public override byte[] Serialize(T value)
32 | {
33 | using (var stream = new MemoryStream())
34 | {
35 | // Protobuf returns an empty byte array {} which would be treated as Null value in redis
36 | // this is not allowed in cache manager and would cause issues (would look like the item does not exist)
37 | // we'll simply add a prefix byte and remove it before deserialization.
38 | stream.WriteByte(0);
39 | Serializer.Serialize(stream, value);
40 | return stream.ToArray();
41 | }
42 | }
43 |
44 | ///
45 | protected override object CreateNewItem(ICacheItemProperties properties, object value)
46 | {
47 | return new ProtoBufCacheItem(properties, value);
48 | }
49 |
50 | ///
51 | protected override Type GetOpenGeneric()
52 | {
53 | return _openGenericItemType;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/CacheManager.StackExchange.Redis/CacheManager.StackExchange.Redis.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | net472;netstandard2.0;net80
6 | true
7 | true
8 | Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | $(DefineConstants);NETSTANDARD2_0
22 |
23 |
--------------------------------------------------------------------------------
/src/CacheManager.StackExchange.Redis/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | [assembly: CLSCompliant(true)]
5 |
6 | [assembly: InternalsVisibleTo("CacheManager.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051a13aa6dd4e78f62051f0d2608ba1e1e50f7038dad1e72f6a2233ec77ec58d49eec5ba13b0f7508d11fbbcd79ee39b0322b58873962771396ec08096f5d4bd2d1622ed9cad79016c154397390336a4a5a619aeec126f8d54b9ea884c510267d1d413ab5afc3c1aea86c199e57ecb23bd39458528328d2de90050e11d4649ec3")]
--------------------------------------------------------------------------------
/src/CacheManager.StackExchange.Redis/RetryHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Extensions.Logging;
3 | using StackExchange.Redis;
4 |
5 | namespace CacheManager.Redis
6 | {
7 | internal static class RetryHelper
8 | {
9 | private const string ErrorMessage = "Maximum number of tries exceeded to perform the action: {0}.";
10 | private const string WarningMessage = "Exception occurred performing an action. Retrying... {0}/{1}";
11 |
12 | public static T Retry(Func retryme, int timeOut, int retries, ILogger logger)
13 | {
14 | var tries = 0;
15 | do
16 | {
17 | tries++;
18 |
19 | try
20 | {
21 | return retryme();
22 | }
23 |
24 | // might occur on lua script execution on a readonly slave because the master just died.
25 | // Should recover via fail over
26 | catch (RedisServerException ex)
27 | {
28 | if (ex.Message.Contains("unknown command"))
29 | {
30 | throw;
31 | }
32 | if (tries >= retries)
33 | {
34 | logger.LogError(ex, ErrorMessage, retries);
35 | throw;
36 | }
37 |
38 | logger.LogWarning(ex, WarningMessage, tries, retries);
39 | }
40 | catch (RedisConnectionException ex)
41 | {
42 | if (tries >= retries)
43 | {
44 | logger.LogError(ex, ErrorMessage, retries);
45 | throw;
46 | }
47 |
48 | logger.LogWarning(ex, WarningMessage, tries, retries);
49 | }
50 | catch (TimeoutException ex)
51 | {
52 | if (tries >= retries)
53 | {
54 | logger.LogError(ex, ErrorMessage, retries);
55 | throw;
56 | }
57 |
58 | logger.LogWarning(ex, WarningMessage, tries, retries);
59 | }
60 | catch (AggregateException aggregateException)
61 | {
62 | if (tries >= retries)
63 | {
64 | logger.LogError(aggregateException, ErrorMessage, retries);
65 | throw;
66 | }
67 |
68 | aggregateException.Handle(e =>
69 | {
70 | if(e is RedisServerException serverEx && serverEx.Message.Contains("unknown command"))
71 | {
72 | return false;
73 | }
74 |
75 | if (e is RedisConnectionException || e is System.TimeoutException || e is RedisServerException)
76 | {
77 | logger.LogWarning(e, WarningMessage, tries, retries);
78 |
79 | return true;
80 | }
81 |
82 | logger.LogCritical(aggregateException, "Unhandled exception occurred.");
83 | return false;
84 | });
85 | }
86 | }
87 | while (tries < retries);
88 |
89 | return default(T);
90 | }
91 |
92 | public static void Retry(Action retryme, int timeOut, int retries, ILogger logger)
93 | {
94 | Retry(
95 | () =>
96 | {
97 | retryme();
98 | return true;
99 | },
100 | timeOut,
101 | retries,
102 | logger);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/CacheManager.StackExchange.Redis/ScriptType.cs:
--------------------------------------------------------------------------------
1 | namespace CacheManager.Redis
2 | {
3 | internal enum ScriptType
4 | {
5 | Put,
6 | Add,
7 | Update,
8 | Get
9 | }
10 | }
--------------------------------------------------------------------------------
/src/CacheManager.SystemRuntimeCaching/CacheManager.SystemRuntimeCaching.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 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.
5 | net472;netstandard2.0;net8.0
6 | true
7 | true
8 | Caching;Cache;CacheManager;Distributed Cache;StackExchange Redis;Azure AppFabric;Memcached
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/CacheManager.SystemRuntimeCaching/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | [assembly: CLSCompliant(true)]
--------------------------------------------------------------------------------
/src/CacheManager.SystemRuntimeCaching/RuntimeMemoryCacheOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Specialized;
4 | using System.Globalization;
5 | using System.Linq;
6 | using System.Text;
7 |
8 | namespace CacheManager.SystemRuntimeCaching
9 | {
10 | ///
11 | /// configuration options
12 | ///
13 | public class RuntimeMemoryCacheOptions
14 | {
15 | ///
16 | /// 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.
17 | ///
18 | public int CacheMemoryLimitMegabytes { get; set; } = 0;
19 |
20 | ///
21 | /// 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.
22 | ///
23 | public int PhysicalMemoryLimitPercentage { get; set; } = 0;
24 |
25 | ///
26 | /// 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.
27 | ///
28 | public TimeSpan PollingInterval { get; set; } = TimeSpan.FromMinutes(2);
29 |
30 | ///
31 | /// Gets the configuration as a
32 | ///
33 | /// A with the current configuration.
34 | public NameValueCollection AsNameValueCollection()
35 | {
36 | return new NameValueCollection(3)
37 | {
38 | { nameof(CacheMemoryLimitMegabytes), CacheMemoryLimitMegabytes.ToString(CultureInfo.InvariantCulture) },
39 | { nameof(PhysicalMemoryLimitPercentage), PhysicalMemoryLimitPercentage.ToString(CultureInfo.InvariantCulture) },
40 | { nameof(PollingInterval), PollingInterval.ToString("c") }
41 | };
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/test/CacheManager.MSConfiguration.TypeLoad.Tests/CacheManager.MSConfiguration.TypeLoad.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CacheManager.MSConfiguration.TypeLoad.Tests Class Library
5 | net8.0
6 | CacheManager.MSConfiguration.TypeLoad.Tests
7 | CacheManager.MSConfiguration.TypeLoad.Tests
8 | true
9 | $(NoWarn);CA2021
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | all
26 | runtime; build; native; contentfiles; analyzers; buildtransitive
27 |
28 |
29 | all
30 | runtime; build; native; contentfiles; analyzers
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/test/CacheManager.MSConfiguration.TypeLoad.Tests/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {}
3 | }
--------------------------------------------------------------------------------
/test/CacheManager.MSConfiguration.TypeLoad.Tests/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "parallelizeTestCollections": false,
3 | "methodDisplay": "method",
4 | "preEnumerateTheories": false
5 | }
6 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/CacheManager.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ;net8.0
6 |
7 | 1.0.0
8 | CacheManager.Tests
9 | ../../tools/key.snk
10 | true
11 | true
12 | CacheManager.Tests
13 | true
14 | $(NoWarn);CA2021
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | PreserveNewest
24 |
25 |
26 |
27 |
28 |
29 |
30 | Always
31 | App.config
32 |
33 |
34 | Always
35 | App.config
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | all
54 | runtime; build; native; contentfiles; analyzers; buildtransitive
55 |
56 |
57 | all
58 | runtime; build; native; contentfiles; analyzers
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.ExpireTest.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.ExpirationWithoutTimeout.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnablePerfCounters.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidEnableStats.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidExpMode.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidRef.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidTimeout.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.InvalidUpdateMode.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.MaxRetries.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.RetryTimeout.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.backplaneNameNoType.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.backplaneTypeNoName.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.emptyHandleDefinition.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.invalidDefExpMode.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.invalidDefTimeout.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
15 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.invalidType.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.managerWithoutHandles.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.missingDefId.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.missingName.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.missingType.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.noSection.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Configuration/configuration.invalid.serializerType.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/ExcludeFromCodeCoverageAttribute.cs:
--------------------------------------------------------------------------------
1 | ////namespace System.Diagnostics.CodeAnalysis
2 | ////{
3 | //// [Conditional("DEBUG")]
4 | //// [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
5 | //// internal sealed class ExcludeFromCodeCoverageAttribute : Attribute
6 | //// {
7 | //// }
8 | ////}
9 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/LoggingTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics.CodeAnalysis;
4 | using System.Linq;
5 | using FluentAssertions;
6 | using Microsoft.Extensions.Logging;
7 | using Xunit;
8 |
9 | namespace CacheManager.Tests
10 | {
11 | [ExcludeFromCodeCoverage]
12 | public class TestLoggerFactory : ILoggerFactory
13 | {
14 | private readonly TestLogger useLogger;
15 |
16 | public TestLoggerFactory(TestLogger useLogger)
17 | {
18 | this.useLogger = useLogger;
19 | }
20 |
21 | public void AddProvider(ILoggerProvider provider)
22 | {
23 | }
24 |
25 | public ILogger CreateLogger(string categoryName)
26 | {
27 | return this.useLogger;
28 | }
29 |
30 | public ILogger CreateLogger(T instance)
31 | {
32 | return this.useLogger;
33 | }
34 |
35 | public void Dispose()
36 | {
37 | }
38 | }
39 |
40 | [ExcludeFromCodeCoverage]
41 | public class TestLogger : ILogger
42 | {
43 | public TestLogger()
44 | {
45 | this.LogMessages = new List();
46 | }
47 |
48 | public IList LogMessages { get; }
49 |
50 | public LogMessage Last => this.LogMessages.Last();
51 |
52 | public IDisposable BeginScope(TState state) => null;
53 |
54 | public bool IsEnabled(LogLevel logLevel)
55 | {
56 | return true;
57 | }
58 |
59 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter)
60 | {
61 | this.LogMessages.Add(new LogMessage(logLevel, eventId, formatter(state, exception), exception));
62 | }
63 | }
64 |
65 | [ExcludeFromCodeCoverage]
66 | public class LogMessage
67 | {
68 | public LogMessage(LogLevel level, EventId eventId, object message, Exception exception)
69 | {
70 | this.LogLevel = level;
71 | this.EventId = eventId;
72 | this.Message = message;
73 | this.Exception = exception;
74 | }
75 |
76 | public LogLevel LogLevel { get; }
77 |
78 | public EventId EventId { get; }
79 |
80 | public object Message { get; }
81 |
82 | public Exception Exception { get; }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
--------------------------------------------------------------------------------
/test/CacheManager.Tests/RedisTestFixture.cs:
--------------------------------------------------------------------------------
1 | #if NET8_0_OR_GREATER
2 |
3 | using System;
4 | using System.Threading.Tasks;
5 | using System.Threading;
6 | using Garnet;
7 | using Garnet.server;
8 | using System.Net;
9 | using Microsoft.Extensions.Logging;
10 |
11 | #endif
12 |
13 | namespace CacheManager.Tests
14 | {
15 | public class RedisTestFixture : IDisposable
16 | {
17 | #if NET8_0_OR_GREATER
18 |
19 | private static Lazy server = new Lazy(() => StartServer());
20 |
21 | private static int InstanceCount = 0;
22 |
23 | public static GarnetServer StartServer(int port = 6379, ILoggerFactory loggerFactory = null)
24 | {
25 | var server = new GarnetServer(new GarnetServerOptions()
26 | {
27 | EnableLua = true,
28 | LuaOptions = new LuaOptions(LuaMemoryManagementMode.Native, string.Empty, TimeSpan.FromSeconds(20)),
29 | EndPoint = new IPEndPoint(IPAddress.Loopback, port),
30 | },
31 | loggerFactory: loggerFactory);
32 | try
33 | {
34 | server.Start();
35 | Task.Delay(1000).GetAwaiter().GetResult();
36 | }
37 | catch(Exception ex)
38 | {
39 | Console.WriteLine(ex);
40 | }
41 |
42 | return server;
43 | }
44 |
45 | public RedisTestFixture()
46 | {
47 | Interlocked.Increment(ref InstanceCount);
48 |
49 | var info = server.Value.Metrics.GetInfoMetrics();
50 | }
51 |
52 | public void Dispose()
53 | {
54 | Task.Delay(5000).GetAwaiter().GetResult();
55 | var current = Interlocked.Decrement(ref InstanceCount);
56 |
57 | // Console.WriteLine($"Disposing... {current}");
58 | if (current == 0)
59 | {
60 | server.Value.Dispose();
61 | server = new Lazy(() => StartServer());
62 | }
63 | }
64 |
65 | #else
66 |
67 | public void Dispose()
68 | {
69 | }
70 |
71 | #endif
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/ReplaceCultureAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Globalization;
4 | using System.Reflection;
5 | using System.Threading;
6 | using Xunit.Sdk;
7 |
8 | namespace CacheManager.Tests
9 | {
10 | [ExcludeFromCodeCoverage]
11 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "nope")]
12 | [AttributeUsage(AttributeTargets.Method)]
13 | public sealed class ReplaceCultureAttribute : BeforeAfterTestAttribute
14 | {
15 | private const string DefaultCultureName = "en-GB";
16 | private const string DefaultUICultureName = "en-US";
17 | private CultureInfo originalCulture;
18 | private CultureInfo originalUICulture;
19 |
20 | public ReplaceCultureAttribute()
21 | : this(DefaultCultureName, DefaultUICultureName)
22 | {
23 | }
24 |
25 | public ReplaceCultureAttribute(string currentCulture, string currentUICulture)
26 | {
27 | this.CurrentCulture = new CultureInfo(currentCulture);
28 | this.CurrentUICulture = new CultureInfo(currentUICulture);
29 | }
30 |
31 | public CultureInfo CurrentCulture { get; }
32 |
33 | public CultureInfo CurrentUICulture { get; }
34 |
35 | public override void Before(MethodInfo methodUnderTest)
36 | {
37 | this.originalCulture = CultureInfo.CurrentCulture;
38 | this.originalUICulture = CultureInfo.CurrentUICulture;
39 |
40 | Thread.CurrentThread.CurrentCulture = this.CurrentCulture;
41 | Thread.CurrentThread.CurrentUICulture = this.CurrentUICulture;
42 | }
43 |
44 | public override void After(MethodInfo methodUnderTest)
45 | {
46 | Thread.CurrentThread.CurrentCulture = this.originalCulture;
47 | Thread.CurrentThread.CurrentUICulture = this.originalUICulture;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/SystemWebCacheHandleWrapper.cs:
--------------------------------------------------------------------------------
1 | ////// disabling it for builds on Mono because setting the HttpContext.Current causes all kinds of strange exceptions
2 | ////#if MOCK_HTTPCONTEXT_ENABLED
3 | ////using System.Diagnostics.CodeAnalysis;
4 | ////using System.IO;
5 | ////using System.Web;
6 | ////using CacheManager.Core;
7 |
8 | ////using CacheManager.Web;
9 |
10 | ////namespace CacheManager.Tests
11 | ////{
12 | //// [ExcludeFromCodeCoverage]
13 | //// internal class SystemWebCacheHandleWrapper : SystemWebCacheHandle
14 | //// {
15 | //// public SystemWebCacheHandleWrapper(CacheManagerConfiguration managerConfiguration, CacheHandleConfiguration configuration, ILoggerFactory loggerFactory)
16 | //// : base(managerConfiguration, configuration, loggerFactory)
17 | //// {
18 | //// }
19 |
20 | //// protected override HttpContextBase Context
21 | //// {
22 | //// get
23 | //// {
24 | //// if (HttpContext.Current == null)
25 | //// {
26 | //// HttpContext.Current = new HttpContext(new HttpRequest("test", "http://test", string.Empty), new HttpResponse(new StringWriter()));
27 | //// }
28 |
29 | //// return new HttpContextWrapper(HttpContext.Current);
30 | //// }
31 | //// }
32 | //// }
33 | ////}
34 | ////#endif
35 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/TestConfigurationHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Linq;
4 | using static CacheManager.Core.Utility.Guard;
5 |
6 | namespace CacheManager.Tests
7 | {
8 | [ExcludeFromCodeCoverage]
9 | public static class TestConfigurationHelper
10 | {
11 | public static string GetCfgFileName(string fileName)
12 | {
13 | NotNullOrWhiteSpace(fileName, nameof(fileName));
14 | var basePath = Environment.CurrentDirectory;
15 | return basePath + (fileName.StartsWith("/") ? fileName : "/" + fileName);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/TestHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace CacheManager.Tests
7 | {
8 | public static class TestHelper
9 | {
10 | public static async Task WaitUntilCancel(Action act, int timeoutInMillis = 5000)
11 | {
12 | var source = new CancellationTokenSource();
13 | act(source);
14 | try
15 | {
16 | await Task.Delay(timeoutInMillis, source.Token);
17 | }
18 | catch
19 | {
20 | // do nothing
21 | }
22 | }
23 |
24 | ///
25 | /// Retries the for a maximum of or until returns True .
26 | ///
27 | /// Number of tries.
28 | /// The action to retry.
29 | /// The condition to signal to stop retrying.
30 | public static void RetryWithCondition(int tries, Action action, Func condition)
31 | {
32 | var currentTry = 0;
33 | while (currentTry < tries)
34 | {
35 | currentTry++;
36 | Console.WriteLine("RetryWithCondition try " + currentTry);
37 | action();
38 | if (condition())
39 | {
40 | Console.WriteLine("RetryWithCondition break for condition after try " + currentTry);
41 | break;
42 | }
43 | }
44 | }
45 |
46 | ///
47 | /// Retries the for a maximum of or until returns True .
48 | ///
49 | /// Number of tries.
50 | /// The action to retry.
51 | /// The condition to signal to stop retrying.
52 | public static async Task RetryWithCondition(int tries, Func action, Func condition)
53 | {
54 | var currentTry = 0;
55 | while (currentTry < tries)
56 | {
57 | currentTry++;
58 | Console.WriteLine("RetryWithCondition try " + currentTry);
59 | await action();
60 | if (condition())
61 | {
62 | Console.WriteLine("RetryWithCondition break for condition after try " + currentTry);
63 | break;
64 | }
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/TestModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using ProtoBuf;
4 |
5 | namespace CacheManager.Tests
6 | {
7 | [Serializable]
8 | [ExcludeFromCodeCoverage]
9 | [ProtoContract]
10 | [Bond.Schema]
11 | public class RaceConditionTestElement
12 | {
13 | public RaceConditionTestElement()
14 | {
15 | }
16 |
17 | [ProtoMember(1)]
18 | [Bond.Id(1)]
19 | public long Counter { get; set; }
20 | }
21 |
22 | [ExcludeFromCodeCoverage]
23 | public class IAmNotSerializable
24 | {
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/ThreadRandomReadWriteTestBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics.CodeAnalysis;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using CacheManager.Core;
7 | using FluentAssertions;
8 | using Xunit;
9 |
10 | namespace CacheManager.Tests
11 | {
12 | [ExcludeFromCodeCoverage]
13 | public class ThreadRandomReadWriteTestBase : IClassFixture
14 | {
15 | [Theory(Skip = "Not really good test")]
16 | [Trait("category", "Unreliable")]
17 | [ClassData(typeof(TestCacheManagers))]
18 | public async Task Thread_Update(ICacheManager cache)
19 | {
20 | using (cache)
21 | {
22 | var key = Guid.NewGuid().ToString();
23 | var handleInfo = string.Join("\nh: ", cache.CacheHandles.Select(p => p.Configuration.Name + ":" + p.GetType().Name));
24 |
25 | cache.Remove(key);
26 | cache.Add(key, new RaceConditionTestElement() { Counter = 0 });
27 | int numThreads = 5;
28 | int iterations = 10;
29 | int numInnerIterations = 10;
30 | int countCasModifyCalls = 0;
31 |
32 | // act
33 | await ThreadTestHelper.RunAsync(
34 | async () =>
35 | {
36 | for (int i = 0; i < numInnerIterations; i++)
37 | {
38 | cache.Update(
39 | key,
40 | (value) =>
41 | {
42 | var val = value as RaceConditionTestElement;
43 | if (val == null)
44 | {
45 | throw new InvalidOperationException("WTF invalid object result");
46 | }
47 |
48 | val.Counter++;
49 | Interlocked.Increment(ref countCasModifyCalls);
50 | return value;
51 | },
52 | int.MaxValue);
53 | }
54 |
55 | await Task.Delay(0);
56 | },
57 | numThreads,
58 | iterations);
59 |
60 | // assert
61 | await Task.Delay(10);
62 | for (var i = 0; i < cache.CacheHandles.Count(); i++)
63 | {
64 | var handle = cache.CacheHandles.ElementAt(i);
65 | var result = (RaceConditionTestElement)handle.Get(key);
66 | if (i < cache.CacheHandles.Count() - 1)
67 | {
68 | // only the last one should have the item
69 | result.Should().BeNull();
70 | }
71 | else
72 | {
73 | result.Should().NotBeNull(handleInfo + "\ncurrent: " + handle.Configuration.Name + ":" + handle.GetType().Name);
74 | result.Counter.Should().Be(numThreads * numInnerIterations * iterations, handleInfo + "\ncounter should be exactly the expected value.");
75 | countCasModifyCalls.Should().BeGreaterOrEqualTo((int)result.Counter, handleInfo + "\nexpecting no (if synced) or some version collisions.");
76 | }
77 | }
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/test/CacheManager.Tests/ThreadTestHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Diagnostics.CodeAnalysis;
5 | using System.Linq;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace CacheManager.Tests
10 | {
11 | [ExcludeFromCodeCoverage]
12 | public class ThreadTestHelper
13 | {
14 | public static async Task RunAsync(Func test, int tasks, int iterations)
15 | {
16 | var threadList = new List();
17 |
18 | var exceptions = new List();
19 | for (int i = 0; i < tasks; i++)
20 | {
21 | threadList.Add(Task.Run(async () =>
22 | {
23 | for (var iter = 0; iter < iterations; iter++)
24 | {
25 | try
26 | {
27 | await test();
28 | }
29 | catch (Exception ex)
30 | {
31 | exceptions.Add(ex);
32 | }
33 | }
34 |
35 | await Task.Delay(1);
36 | }));
37 | }
38 |
39 | await Task.WhenAll(threadList.ToArray());
40 |
41 | if (exceptions.Count > 0)
42 | {
43 | throw new Exception(exceptions.Count + " Exceptions thrown", exceptions.First());
44 | }
45 | }
46 |
47 | public static void Run(Action test, int threads, int iterations)
48 | {
49 | var threadList = new List();
50 |
51 | Exception exceptionResult = null;
52 | for (int i = 0; i < threads; i++)
53 | {
54 | var t = new Thread(new ThreadStart(() =>
55 | {
56 | for (var iter = 0; iter < iterations; iter++)
57 | {
58 | try
59 | {
60 | test();
61 | }
62 | catch (Exception ex)
63 | {
64 | exceptionResult = ex;
65 | }
66 | }
67 | }));
68 | threadList.Add(t);
69 | }
70 |
71 | threadList.ForEach(p => p.Start());
72 | threadList.ForEach(p => p.Join());
73 |
74 | if (exceptionResult != null)
75 | {
76 | throw exceptionResult;
77 | }
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/test/CacheManager.Tests/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "parallelizeTestCollections": true,
3 | "methodDisplay": "method",
4 | "preEnumerateTheories": true,
5 | "diagnosticMessages": false
6 | }
7 |
--------------------------------------------------------------------------------
/tools/CacheManagerCfg.xsd:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/tools/CodeAnalysis.ruleset:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tools/RedisCfg.xsd:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/tools/common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Copyright (c) 2025 Michael Conrad
6 | MichaConrad
7 | CacheManager.NET
8 |
9 | icon.png
10 | README.md
11 | Apache-2.0
12 | https://cachemanager.michaco.net
13 | http://cachemanager.michaco.net
14 | true
15 | true
16 | true
17 | true
18 |
19 | true
20 | snupkg
21 | portable
22 |
23 | $(MSBuildThisFileDirectory)key.snk
24 | true
25 | true
26 |
27 | $(VersionSuffix)-$(BuildNumber)
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/tools/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichaCo/CacheManager/5aedc81b3caa0811433544277168964f4203e319/tools/icon.png
--------------------------------------------------------------------------------
/tools/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichaCo/CacheManager/5aedc81b3caa0811433544277168964f4203e319/tools/key.snk
--------------------------------------------------------------------------------
/tools/version.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2.0.0
4 |
5 |
6 |
--------------------------------------------------------------------------------