🎯 Changes in multi-targeting
Some time ago I started enabling multi-targeting on FusionCache: I didn't do that because I needed to special case some parts of the code, but just because I wanted to reduce the amount of explicit dependencies for certain TFMs after a request from the community.
But recently community user @nick-randal noticed in #416 some potential issues: long story short, from now on FusionCache will have explicit targeting only for currently supported TFMs (which today means no more .NET 3.1, .NET 6 or .NET 7) and for them it will have the minimum set of explicit dependencies.
But wait: does this mean that those older versions of .NET wil not be able to use FusionCache anymore?
Absolutely not: since FusionCache targets .NET Standard 2.0, this means that ANY version of .NET compatible with .NET Standard 2.0 (meaning: all versions) will still be able to use FusionCache, just without an explicit "support statement", since those versions are anyway not supported anymore, not even by Microsoft itself.
See here and here for the original issues.
🚀 Make the AOT support official
FusionCache has been AOT compatible for a long time, which is already good.
I just need to make that more "official" by declaring it in the csproj, enabling analyzers, create a test console app and, in general, do everything that's needed. And that's what I did.
Thanks to community user @digital88 for pointing that out.
See here and here for the original issues.
🔀 Expose the current distributed cache, if any
Currently, given a FusionCache
instance, it's only possible to know if there is a distributed cache level (L2) via the bool HasDistributedCache { get; }
property, not which one it is.
Community user @angularsen asked to expose it in #443 .
Historically I've been hesitant to expose internals, but at this point I think I can let this one go.
So now there's a new IDistributedCache? DistributedCache { get; }
property that expose the IDistributedCache
instance being used, if any.
See here and here for the original issues.
Warning
This is technically a breaking change, but since nobody has custom IFusionCache
implementations and I updated both (FusionCache
and NullFusionCache
), I think this is fine.
📢 Expose the current backplane, if any
Same as above, but for the backplane.
So now there's a new a new IFusionCacheBackplane? Backplane { get; }
property that expose the IFusionCacheBackplane
instance being used, if any.
See here and here for the original issues.
Warning
This is technically a breaking change, but since nobody has custom IFusionCache
implementations and I updated both (FusionCache
and NullFusionCache
), I think this is fine.
😶 Add DI support for NullFusionCache
Community user @eskild-th noted it was not possible to specify to use a NullFusionCache
implementation via DI.
And now it is.
See here and here for the original issues.
🧼 Better perf for Clear(true)
Since I added Clear()
support in v2, it has become one of the favourite features by the community (including, of course, Tagging).
Recently community user @ctyar noted something seemingly strange, which I then clarified, so all was good.
But this sparked an optimization idea so, even though the implementation for Clear()
has been highly optimized since day 1, now it is even more in cases when Raw Clear is possible (eg: L1 only, no shared).
This, in reality, translates to better Clear checks,which means better perf for any method call in the mentioned scenario (eg: GetOrSet
, TryGet
, etc), not just when calling Clear()
itself: yeah 🥳
See here for the issue that sparked the idea for the optimization.
📢 More async backplane
Community user @pil0t suggested to look into some backplane code, and proposed some changes, which I merged and then added some others on top of them.
The result is that now the backplane should work better, in a more async way, anytime possible: this allows for even less thread blocking than before.
See here for the original issue.
📜 Better logging
Community user @gmij pointed out that there was not much use of the INFO logging level, and that most log entries were at the DEBUG level: that is a good thing to point out, so now all the "entry/exit points" are marked at INFO level.
This means there's more differentiation between the different levels used, which is better to get more visibility into FusionCache internals but without immediately getting too much visibility.
On a different note, but still about logging, distributed cache errors related to internal FusionCache operations now log with a WARNING level instead of an ERROR level: this should avoid triggering some alarms in observability scenarios where that is configured.
See here and here for the original issues.
🔓 New memory locker based on the 3rd party AsyncKeyedLock library
Community user @MarkCiliaVincenti asked in #134 (yup, quite some time ago 😅) to switch FusionCache internal locking mechanism to his own library, AsyncKeyedLock.
Now, I don't want to have a direct dependency to something external for something so core, but since v0.26.0
there's a new IFusionCacheMemoryLocker
abstraction which allows the creation of 3rd party implementations, so I decided to give it a try and added support for it.
How good is it? How does it compare to the standard one included in FusionCache? It depends on your own scenario, so the best thing is to try it out, measure everything, and see for yourself.
See here for the original issue.
🐞Fix for Eager Refresh in high concurrency scenarios
Community user @HannaHromenko noted that sometimes, in highly concurrent scenarios, a null reference exception was being thrown, who knows why.
Well damn, I knew why, and that is now fixed.
See here for the original issue.
🐞 Small fix when jittering + fail-safe
It has been noted by @fabianmenges that, when using both jittering and fail-safe, something unexpected could happen: now this has been fixed.
See here for the original issue.
🐞 Small fix when setting a value with AutoClone
Community user @nlconor noted that when using AutoClone the serialization was being done lazily, and this fact may create problems when putting something in the the cache, keeping a reference to it, then change it.
Now this has been fixed.
See here for the original issue.