ZiggyCreatures.FusionCache
0.1.3
Prefix Reserved
See the version list below for details.
dotnet add package ZiggyCreatures.FusionCache --version 0.1.3
NuGet\Install-Package ZiggyCreatures.FusionCache -Version 0.1.3
<PackageReference Include="ZiggyCreatures.FusionCache" Version="0.1.3" />
paket add ZiggyCreatures.FusionCache --version 0.1.3
#r "nuget: ZiggyCreatures.FusionCache, 0.1.3"
// Install ZiggyCreatures.FusionCache as a Cake Addin #addin nuget:?package=ZiggyCreatures.FusionCache&version=0.1.3 // Install ZiggyCreatures.FusionCache as a Cake Tool #tool nuget:?package=ZiggyCreatures.FusionCache&version=0.1.3
FusionCache
FusionCache is an easy to use, high performance and robust cache with an optional distributed 2nd layer and some advanced features.
It was born after years of dealing with all sorts of different types of caches: memory caching, distributed caching, http caching, CDNs, browser cache, offline cache, you name it. So I've tried to put togheter these experiences and came up with FusionCache.
It uses a memory cache (any impl of the standard IMemoryCache
interface) as the primary backing store and optionally a distributed, 2nd level cache (any impl of the standard IDistributedCache
interface) as a secondary backing store for better resilience and higher performance, for example in a multi-node scenario or to avoid the typical effects of a cold start (initial empty cache, maybe after a restart).
FusionCache also includes some advanced features like a fail-safe mechanism, concurrent factory calls optimization for the same cache key, fine grained soft/hard timeouts with background factory completion, customizable extensive logging and more (see below).
✔ Features
These are the key features of FusionCache:
- 🚀 Optimized factory calls: using the optimized
GetOrSet[Async]
method prevents multiple concurrent factory calls per key, with a guarantee that only 1 factory will be called at the same time for the same key (this avoids overloading the data source when no data is in the cache or when a cache entry expires) - 🔀 Optional 2nd level: FusionCache can transparently handle an optional 2nd level cache: anything that implements the standard
IDistributedCache
interface is supported (eg: Redis, MongoDB, SqlServer, etc) - 💣 Fail-Safe: enabling the fail-safe mechanism prevents throwing an exception when a factory or a distributed cache call would fail, by reusing an expired entry as a temporary fallback, all transparently and with no additional code required
- ⏱ Soft/Hard timeouts: advanced timeouts management prevents waiting for too long when calling a factory or the distributed cache. This is done to avoid that such slow calls would hang your application. It is possible to specify both soft and hard timeouts that will be used depending on whether there's a fallback value to use for the specific call or not
- 🕶 Background factory completion: when you specify a factory timeout and it actually occurs, the timed-out factory can keep running in the background and, if and when it successfully complete, the cache will be immediately updated with the new value to be used right away
- ⚡ High performance: FusionCache is optimized to minimize CPU usage and memory allocations to get better performance and lower the cost of your infrastructure all while obtaining a more stable, error resilient application
- 💫 Natively sync/async: full native support for both the synchronous and asynchronous programming model, with sync/async methods working togheter harmoniously
- 📃 Extensive logging: comprehensive, structured, detailed and customizable logging via the standard
ILogger
interface (you can use Serilog, NLog, etc)
Also, FusionCache has some other nice additional features:
- Portable: targets .NET Standard 2.0
- Null caching: explicitly supports caching of null values differently than "no value". This creates a less ambiguous usage, and typically leads to better performance because it avoids the classic problem of not being able to differentiate between "the value was not in the cache, go check the database" and "the value was in the cache, and it was
null
" - Distributed cache circuit-breaker: it is possible to enable a simple circuit-breaker for when a distributed cache becomes temporarily unavailable. This will prevent the distributed cache to be hit with an additional load of requests (that would probably fail anyway) in a problematic moment, so it can gracefully get back on its feet. More advanced scenarios can be covered using a dedicated solution, like Polly
- Dynamic Jittering: setting
JitterMaxDuration
will add a small randomized extra duration to a cache entry's normal duration. This is useful to prevent variations of the Thundering Herd problem in a multi-node scenario - Hot Swap: supports thread-safe changes of the entire distributed cache implementation (add/swap/removal)
- Code comments: every property and method is fully documented in code, with useful informations provided via IntelliSense or similar technologies
- Fully annotated for nullability: every usage of nullable references has been annotated for a better flow analysis by the compiler
⭐ Quick Start
FusionCache can be installed via the nuget UI (search for the ZiggyCreatures.FusionCache
package) or via the nuget package manager console:
PM> Install-Package ZiggyCreatures.FusionCache
As an example, imagine having a method that retrieves a product from your database:
Product GetProductFromDb(int id) {
// YOUR DATABASE CALL HERE
}
💡 This is using the sync programming model, but it would be equally valid with the newer async one for even better performance.
To start using FusionCache the first thing is create a cache instance:
var cache = new FusionCache(new FusionCacheOptions());
If instead you are using DI (Dependency Injection) use this:
services.AddFusionCache();
We can also specify some global options, like a default FusionCacheEntryOptions
object to serve as a default for each call we'll make, with a duration of 2 minutes
and a Low
priority:
var cache = new FusionCache(new FusionCacheOptions() {
DefaultEntryOptions = new FusionCacheEntryOptions {
Duration = TimeSpan.FromMinutes(2),
Priority = CacheItemPriority.Low
}
});
Or, using DI, like this:
services.AddFusionCache(options => {
options.DefaultEntryOptions = new FusionCacheEntryOptions {
Duration = TimeSpan.FromMinutes(2),
Priority = CacheItemPriority.Low
}
});
Now, to get the product from the cache and, if not there, get it from the database in an optimized way and cache it for 30 sec
simply do this:
var id = 42;
cache.GetOrSet<Product>(
$"product:{id}",
_ => GetProductFromDb(id),
TimeSpan.FromSeconds(30)
);
That's it 🎉
🧰 Supported Platforms
FusionCache targets .NET Standard 2.0, so any compatible .NET implementation is fine.
NOTE: if you are running on .NET Framework 4.6.1 and want to use .NET Standard packages Microsoft suggests to upgrade to .NET Framework 4.7.2 or higher (see the .NET Standard Documentation) to avoid some known dependency issues.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Caching.Memory (>= 3.1.10)
NuGet packages (25)
Showing the top 5 NuGet packages that depend on ZiggyCreatures.FusionCache:
Package | Downloads |
---|---|
ZiggyCreatures.FusionCache.Backplane.StackExchangeRedis
FusionCache backplane for Redis based on the StackExchange.Redis library |
|
ZiggyCreatures.FusionCache.Serialization.NewtonsoftJson
FusionCache serializer based on Newtonsoft Json.NET |
|
ZiggyCreatures.FusionCache.Serialization.SystemTextJson
FusionCache serializer based on System.Text.Json |
|
Auth0Net.DependencyInjection
Dependency Injection, HttpClientFactory & ASP.NET Core extensions for Auth0.NET |
|
ZiggyCreatures.FusionCache.OpenTelemetry
Add native OpenTelemetry support to FusionCache. |
GitHub repositories (7)
Showing the top 5 popular GitHub repositories that depend on ZiggyCreatures.FusionCache:
Repository | Stars |
---|---|
Azure/data-api-builder
Data API builder provides modern REST and GraphQL endpoints to your Azure Databases and on-prem stores.
|
|
neozhu/CleanArchitectureWithBlazorServer
This is a repository for creating a Blazor Server dashboard application following the principles of Clean Architecture
|
|
TurnerSoftware/CacheTower
An efficient multi-layered caching system for .NET
|
|
ikyriak/IdempotentAPI
A .NET library that handles the HTTP write operations (POST and PATCH) that can affect only once for the given request data and idempotency-key by using an ASP.NET Core attribute (filter).
|
|
LANCommander/LANCommander
|
Version | Downloads | Last updated | |
---|---|---|---|
2.0.0-preview-2 | 314 | 11/14/2024 | |
2.0.0-preview-1 | 508 | 11/10/2024 | |
1.4.1 | 57,570 | 10/27/2024 | |
1.4.0 | 201,795 | 9/15/2024 | |
1.3.0 | 228,466 | 8/4/2024 | |
1.2.0 | 338,751 | 6/2/2024 | |
1.2.0-preview1 | 871 | 5/19/2024 | |
1.1.0 | 151,803 | 4/24/2024 | |
1.0.0 | 239,002 | 2/29/2024 | |
1.0.0-preview2 | 4,428 | 2/23/2024 | |
1.0.0-preview1 | 1,260 | 2/11/2024 | |
0.26.0 | 132,759 | 2/11/2024 | |
0.25.0 | 6,862 | 2/4/2024 | |
0.25.0-preview1 | 1,346 | 1/14/2024 | |
0.24.0 | 302,323 | 11/12/2023 | |
0.24.0-preview1 | 1,924 | 9/3/2023 | |
0.23.0 | 354,198 | 8/1/2023 | |
0.22.0 | 53,769 | 7/9/2023 | |
0.21.0 | 801,993 | 5/28/2023 | |
0.21.0-preview2 | 1,810 | 5/21/2023 | |
0.21.0-preview1 | 1,769 | 5/1/2023 | |
0.20.0 | 154,160 | 4/8/2023 | |
0.20.0-preview2 | 1,663 | 3/29/2023 | |
0.20.0-preview1 | 1,968 | 3/3/2023 | |
0.19.0 | 168,186 | 2/12/2023 | |
0.18.0 | 111,674 | 12/18/2022 | |
0.17.0 | 18,585 | 12/4/2022 | |
0.16.0 | 20,340 | 11/12/2022 | |
0.15.0 | 223,829 | 10/26/2022 | |
0.14.0 | 10,735 | 10/18/2022 | |
0.13.0 | 107,025 | 8/14/2022 | |
0.12.0 | 8,607 | 7/19/2022 | |
0.11.1 | 2,972 | 7/15/2022 | |
0.11.0 | 3,009 | 7/12/2022 | |
0.10.0 | 159,504 | 5/1/2022 | |
0.10.0-preview1 | 1,644 | 4/23/2022 | |
0.9.0 | 68,814 | 2/17/2022 | |
0.1.10-beta3 | 3,378 | 2/14/2022 | |
0.1.10-beta2 | 1,684 | 2/11/2022 | |
0.1.10-beta1 | 1,629 | 2/9/2022 | |
0.1.10-alpha2 | 1,705 | 1/30/2022 | |
0.1.10-alpha1 | 1,518 | 1/27/2022 | |
0.1.9 | 52,135 | 11/23/2021 | |
0.1.8 | 7,324 | 11/23/2021 | |
0.1.7 | 19,364 | 10/16/2021 | |
0.1.6 | 36,499 | 8/1/2021 | |
0.1.5 | 5,073 | 6/29/2021 | |
0.1.4 | 4,652 | 6/5/2021 | |
0.1.3 | 4,230 | 4/3/2021 | |
0.1.2 | 14,801 | 2/26/2021 | |
0.1.1 | 2,788 | 1/19/2021 | |
0.1.0 | 2,870 | 12/31/2020 |
- Introduced a generic MaybeValue<T> type
- Better TryGet<T>
- Added a fail-safe default value to GetOrSet<T>
- Added a GetOrSet<T> overload with a direct value (instead of a factory)
- Perf optimizations