Skip to content

Commit

Permalink
v0.24.0 (#183)
Browse files Browse the repository at this point in the history
* Backplane auto-recovery is now Auto-Recovery
* New shared abstract base class
* Better MemoryBackplane
* Xml docs
* Docs
* Better backpressure handling for backplane + tests
* Bug fix for #168
* Add support for inspecting a value being evicted (to support disposability)
* Superior backplane auto-recovery handling, like, new super dooper version, like mega awesome
* Make Simulator fully interactive + add chaos-related functions
* Better backplane tests
* Add support for testing ReThrowBackplaneExceptions when duplicating
* Benchmarks update
* Dependencies update
* Fix links
* Add cancellation support to chaos components
* A lot of internal refactoring
* Add snapshot testing for v0.23.0
* Add distributed cache background execution tests
* Add SetAlwaysDelay(...) overload
* Mega refactoring of the entire distributed management
* General cleanup
* Add Timestamp to AutoRecoveryItem + minor action fix
* Major refactoring, cleanup, speed up and more edge cases handled
* More cleanup
* Add support for splitted background run of background operations (distributed cache vs backplane)
* Better tests
* Small fix
* Cleanup
* Simulator: add random updates
* Add ConnectionMultiplexerFactory to RedisBackplane
* Add EditorBrowsable attribute
* Add ReThrowOriginalExceptions and some specific exceptions for serialization, distributed cache and backplane errors
* Make some of the classes sealed for better perf
* File-scoped namespaces
* Split auto-recovery code into the new AutoRecoveryService
* Better auto-recovery log levels + some refactoring
* Add backplane wire format modifier for
* Simulator stuff
* More sealed stuff
* Better simulator UI
* Small memory optimization
* Add FromByteArray/ToByteArray static methods to BackplaneMessage
* Start using the new native binary serialization methods for BackplaneMessage
* Better logging
* Add v0.23.0 payload samples
* Start using message serialization to better mimic real backplanes
* Add PhysicalExpiration to FusionCacheMemoryEntry
* V0.24.0 metadata
  • Loading branch information
jodydonetti committed Nov 12, 2023
1 parent 1be828a commit 24d5d0b
Show file tree
Hide file tree
Showing 180 changed files with 14,059 additions and 10,453 deletions.
36 changes: 11 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
![Nuget](https://img.shields.io/nuget/dt/ZiggyCreatures.FusionCache)
[![Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=flat&logo=twitter)](https://twitter.com/intent/tweet?hashtags=fusioncache,caching,cache,dotnet,oss,csharp&text=🚀+FusionCache:+a+new+cache+with+an+optional+2nd+layer+and+some+advanced+features&url=https%3A%2F%2Fgithub.com%2Fjodydonetti%2FZiggyCreatures.FusionCache&via=jodydonetti)
[![Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=flat&logo=twitter)](https://twitter.com/intent/tweet?hashtags=fusioncache,caching,cache,dotnet,oss,csharp&text=🚀+FusionCache:+a+new+cache+with+an+optional+2nd+layer+and+some+advanced+features&url=https%3A%2F%2Fgithub.com%2FZiggyCreatures%2FFusionCache&via=jodydonetti)

</div>

| 🙋‍♂️ Updating from before `v0.20.0` ? please [read here](docs/Update_v0_20_0.md). |
| 🙋‍♂️ Updating from before `v0.24.0` ? please [read here](docs/Update_v0_24_0.md). |
|:-------|

### FusionCache is an easy to use, fast and robust cache with advanced resiliency features and an optional distributed 2nd layer.
Expand Down Expand Up @@ -66,10 +66,11 @@ These are the **key features** of FusionCache:
- [**🔀 Optional 2nd level**](docs/CacheLevels.md): an optional 2nd level handled transparently, with any implementation of `IDistributedCache`
- [**💣 Fail-Safe**](docs/FailSafe.md): a mechanism to avoids transient failures, by reusing an expired entry as a temporary fallback
- [**⏱ Soft/Hard timeouts**](docs/Timeouts.md): a slow factory (or distributed cache) will not slow down your application, and no data will be wasted
- [**📢 Backplane**](docs/Backplane.md): in a multi-node scenario, it can notify the other nodes about changes in the cache, so all will be in-sync
- [**↩️ Auto-Recovery**](docs/AutoRecovery.md): automatic handling of transient issues with retries and sync logic
- [**🧙‍♂️ Adaptive Caching**](docs/AdaptiveCaching.md): for when you don't know upfront the cache duration, as it depends on the value being cached itself
- [**🔂 Conditional Refresh**](docs/ConditionalRefresh.md): like HTTP Conditional Requests, but for caching
- [**🦅 Eager Refresh**](docs/EagerRefresh.md): start a non-blocking background refresh before the expiration occurs
- [**📢 Backplane**](docs/Backplane.md): in a multi-node scenario, it can notify the other nodes about changes in the cache, so all will be in-sync
- [**🔃 Dependency Injection**](docs/DependencyInjection.md): native support for Dependency Injection, with a nice fluent interface including a Builder support
- [**📛 Named Caches**](docs/NamedCaches.md): easily work with multiple named caches, even if differently configured
- [**💫 Natively sync/async**](docs/CoreMethods.md): native support for both the synchronous and asynchronous programming model
Expand Down Expand Up @@ -255,28 +256,6 @@ The `DefaultEntryOptions` we did set before will be duplicated and only the dura

</details>

## 📖 Documentation

The documentation is available in the :open_file_folder: [docs](docs/README.md) folder, with:

- [**🦄 A Gentle Introduction**](docs/AGentleIntroduction.md): what you need to know first
- [**🔀 Cache Levels**](docs/CacheLevels.md): a bried description of the 2 available caching levels and how to setup them
- [**📢 Backplane**](docs/Backplane.md): how to get an always synchronized cache, even in a multi-node scenario
- [**🚀 Cache Stampede prevention**](docs/CacheStampede.md): no more overloads during a cold start or after an expiration
- [**💣 Fail-Safe**](docs/FailSafe.md): an explanation of how the fail-safe mechanism works
- [**⏱ Timeouts**](docs/Timeouts.md): the various types of timeouts at your disposal (calling a factory, using the distributed cache, etc)
- [**📛 Named Caches**](docs/NamedCaches.md): how to work with multiple named FusionCache instances
- [**🧙‍♂️ Adaptive Caching**](docs/AdaptiveCaching.md): how to adapt cache duration (and more) based on the object being cached itself
- [**🔂 Conditional Refresh**](ConditionalRefresh.md): how to save resources when the remote data is not changed
- [**🦅 Eager Refresh**](EagerRefresh.md): how to start a background refresh eagerly, before the expiration occurs
- [**🔃 Dependency Injection**](docs/DependencyInjection.md): how to work with FusionCache + DI in .NET
- [**🎚 Options**](docs/Options.md): everything about the available options, both cache-wide and per-call
- [**🕹 Core Methods**](docs/CoreMethods.md): what you need to know about the core methods available
- [**📞 Events**](docs/Events.md): the events hub and how to use it
- [**🧩 Plugins**](docs/Plugins.md): how to create and use plugins
- [**📜 Logging**](docs/Logging.md): logging configuration and usage


## **👩‍🏫 Step By Step**
If you are in for a ride you can read a complete [step by step example](docs/StepByStep.md) of why a cache is useful, why FusionCache could be even more so, how to apply most of the options available and what **results** you can expect to obtain.

Expand All @@ -286,6 +265,13 @@ If you are in for a ride you can read a complete [step by step example](docs/Ste

</div>

## 🖥️ Simulator

Distributed systems are, in general, quite complex to understand.

When using FusionCache with the [distributed cache](docs/CacheLevels.md), the [backplane](docs/Backplane.md) and [auto-recovery](docs/AutoRecovery.md) the Simulator can help us **seeing** the whole picture.

[![FusionCache Simulator](https://img.youtube.com/vi/6jGX6ePgD3Q/maxresdefault.jpg)](docs/Simulator.md)

## 🆎 Comparison

Expand Down
9 changes: 8 additions & 1 deletion ZiggyCreatures.FusionCache.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZiggyCreatures.FusionCache.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZiggyCreatures.FusionCache.Serialization.ServiceStackJson", "src\ZiggyCreatures.FusionCache.Serialization.ServiceStackJson\ZiggyCreatures.FusionCache.Serialization.ServiceStackJson.csproj", "{CE437FB2-510F-4DCE-8A1F-AED747DAA4EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SerializerPayloadGenerator", "tests\SerializerPayloadGenerator\SerializerPayloadGenerator.csproj", "{5B1AF24E-90FC-4C21-AF9C-090FE32027E3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerializerPayloadGenerator", "tests\SerializerPayloadGenerator\SerializerPayloadGenerator.csproj", "{5B1AF24E-90FC-4C21-AF9C-090FE32027E3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZiggyCreatures.FusionCache.Simulator", "tests\ZiggyCreatures.FusionCache.Simulator\ZiggyCreatures.FusionCache.Simulator.csproj", "{BDB46997-84D1-4CB5-B967-7F820820CB8E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -105,6 +107,10 @@ Global
{5B1AF24E-90FC-4C21-AF9C-090FE32027E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B1AF24E-90FC-4C21-AF9C-090FE32027E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B1AF24E-90FC-4C21-AF9C-090FE32027E3}.Release|Any CPU.Build.0 = Release|Any CPU
{BDB46997-84D1-4CB5-B967-7F820820CB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BDB46997-84D1-4CB5-B967-7F820820CB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BDB46997-84D1-4CB5-B967-7F820820CB8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BDB46997-84D1-4CB5-B967-7F820820CB8E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -124,6 +130,7 @@ Global
{919CDF8C-463A-4E82-AFFD-DF8A6B904600} = {34B53F49-F5C5-4850-B79E-59AD130379C6}
{CE437FB2-510F-4DCE-8A1F-AED747DAA4EB} = {34B53F49-F5C5-4850-B79E-59AD130379C6}
{5B1AF24E-90FC-4C21-AF9C-090FE32027E3} = {C6F3C570-C68C-4A95-960E-82778306BDBA}
{BDB46997-84D1-4CB5-B967-7F820820CB8E} = {C6F3C570-C68C-4A95-960E-82778306BDBA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {92916FA2-FCAC-406E-BF3F-0A2CE9512EF0}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using ZiggyCreatures.Caching.Fusion.Internals;

namespace ZiggyCreatures.Caching.Fusion.Benchmarks
{
[MemoryDiagnoser]
[Config(typeof(Config))]
public class ExecutionBenchmarkAsync
{
private class Config : ManualConfig
{
public Config()
{
AddColumn(
StatisticColumn.P95
);
}
}

private async Task ExecutorAsync()
{
for (int i = 0; i < 1_000_000_000; i++)
{
i++;
}
}

[Benchmark(Baseline = true)]
public async Task WithTimeout()
{
await RunUtils.RunAsyncActionAdvancedAsync(
async _ => await ExecutorAsync(),
TimeSpan.FromSeconds(2),
false,
true
);
}

[Benchmark]
public async Task WithTimeout2()
{
await RunUtils.RunAsyncActionAdvancedAsync(
async _ => await ExecutorAsync(),
TimeSpan.FromSeconds(2),
true,
true
);
}

[Benchmark]
public async Task WithoutTimeout()
{
await RunUtils.RunAsyncActionAdvancedAsync(
async _ => await ExecutorAsync(),
Timeout.InfiniteTimeSpan,
true,
true
);
}

[Benchmark]
public async Task Raw()
{
await ExecutorAsync();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Threading;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using ZiggyCreatures.Caching.Fusion.Internals;

namespace ZiggyCreatures.Caching.Fusion.Benchmarks
{
[MemoryDiagnoser]
[Config(typeof(Config))]
public class ExecutionBenchmarkSync
{
private class Config : ManualConfig
{
public Config()
{
AddColumn(
StatisticColumn.P95
);
}
}

private void Executor()
{
for (int i = 0; i < 1_000_000_000; i++)
{
i++;
}
}

[Benchmark(Baseline = true)]
public void WithTimeout()
{
RunUtils.RunSyncActionAdvanced(
_ => Executor(),
TimeSpan.FromSeconds(2),
false,
true
);
}

[Benchmark]
public void WithTimeout2()
{
RunUtils.RunSyncActionAdvanced(
_ => Executor(),
TimeSpan.FromSeconds(2),
true,
true
);
}

[Benchmark]
public void WithoutTimeout()
{
RunUtils.RunSyncActionAdvanced(
_ => Executor(),
Timeout.InfiniteTimeSpan,
true,
true
);
}

[Benchmark]
public void Raw()
{
Executor();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public Config()
[Params(1, 10)]
public int Rounds;

private List<string> Keys;
private List<string> Keys = null!;
private TimeSpan CacheDuration = TimeSpan.FromDays(10);
private IServiceProvider ServiceProvider;
private IServiceProvider ServiceProvider = null!;

[GlobalSetup]
public void Setup()
Expand Down Expand Up @@ -263,7 +263,7 @@ public void CacheManager()
[Benchmark]
public async Task CacheTower()
{
await using (var cache = new CacheStack(new[] { new MemoryCacheLayer() }, new[] { new AutoCleanupExtension(TimeSpan.FromMinutes(5)) }))
await using (var cache = new CacheStack(null, new CacheStackOptions(new[] { new MemoryCacheLayer() }) { Extensions = new[] { new AutoCleanupExtension(TimeSpan.FromMinutes(5)) } }))
{
var cacheSettings = new CacheSettings(CacheDuration, CacheDuration);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public Config()
[Params(1, 50)]
public int Rounds;

private List<string> Keys;
private List<string> Keys = null!;
private TimeSpan CacheDuration = TimeSpan.FromDays(10);
private IServiceProvider ServiceProvider;
private IServiceProvider ServiceProvider = null!;

[GlobalSetup]
public void Setup()
Expand Down Expand Up @@ -82,7 +82,7 @@ public async Task FusionCache()
[Benchmark]
public async Task CacheTower()
{
await using (var cache = new CacheStack(new[] { new MemoryCacheLayer() }, new[] { new AutoCleanupExtension(TimeSpan.FromMinutes(5)) }))
await using (var cache = new CacheStack(null, new CacheStackOptions(new[] { new MemoryCacheLayer() }) { Extensions = new[] { new AutoCleanupExtension(TimeSpan.FromMinutes(5)) } }))
{
var cacheSettings = new CacheSettings(CacheDuration, CacheDuration);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ public Config()
[Params(1, 50)]
public int Rounds;

private List<string> Keys;
private List<string> Keys = null!;
private TimeSpan CacheDuration = TimeSpan.FromDays(10);
private IServiceProvider ServiceProvider;
private IServiceProvider ServiceProvider = null!;

[GlobalSetup]
public void Setup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<RootNamespace>ZiggyCreatures.Caching.Fusion.Benchmarks</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.6" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
<PackageReference Include="CacheManager.Microsoft.Extensions.Caching.Memory" Version="1.2.0" />
<PackageReference Include="CacheTower" Version="0.13.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.0" />
<PackageReference Include="CacheTower" Version="0.14.0" />
<PackageReference Include="EasyCaching.InMemory" Version="1.9.2" />
<PackageReference Include="LazyCache" Version="2.4.0" />
</ItemGroup>

Expand Down
11 changes: 11 additions & 0 deletions docs/AGentleIntroduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ In both cases it is possible (and enabled *by default*, so we don't have to do a

Read more [**here**](Timeouts.md), or enjoy the complete [**step by step**](StepByStep.md) guide.

## ↩️ Auto-Recovery([more](AutoRecovery.md))

As we know from the [Fallacies Of Distributed Computing](https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing), something may go wrong while we are using distributed components like the distributed cache or the backplane, even if only in a transient way.

Without some extra care what can happen is that data would not be saved in the distributed cache or other nodes may not be notified of changes: this would result in out-of-sync issues.

wouldn't it be nice if FusionCache would help us is some way when transient error happens?

Enter **Auto-Recovery**.: everything is done automatically, and it just works.

Read more [**here**](AutoRecovery.md).

## 🎚️ Options ([more](Options.md))

Expand Down
6 changes: 3 additions & 3 deletions docs/AdaptiveCaching.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ In the ones **with** the context you can simply change the context's `Options` p
Here are 2 examples, with and without the *context* object.


### Example: without adaptive caching
### 👩‍💻 Example: without adaptive caching

As you can see we are specifying the factory as a lambda that takes as input only a cancellation token `ct` (of type `CancellationToken`) and nothing else.

Expand All @@ -45,7 +45,7 @@ var product = cache.GetOrSet<Product>(
);
```

### Example: with adaptive caching
### 👩‍💻 Example: with adaptive caching

As you can see we are specifying the factory as a lambda that takes as input both a context `ctx` (of type `FusionCacheFactoryExecutionContext`) and a cancellation token `ct` (of type `CancellationToken`), so that we are able to change the options inside the factory itself.

Expand Down Expand Up @@ -83,7 +83,7 @@ You may change other options too, like the `Priority` for example.
Of course ther are some changes that wouldn't make much sense: if for example we change the `FactorySoftTimeout` after the factory has been already executed we shouldn't expect much to happen, right 😅 ?


## ⏱ Timeouts & Background factory completion
## ⏱ Timeouts & Background Factory Completion

Short version: everything works as expected!

Expand Down
Loading

0 comments on commit 24d5d0b

Please sign in to comment.