Releases: ZiggyCreatures/FusionCache
v0.1.10-alpha1
Finally, this is the first (alpha) release containing the Backplane #11 🎉.
📢 Backplane (alpha)
FusionCache finally has a fully functioning backplane: see here for more.
⚠ Removed CacheKeyPrefix
The FusionCacheOptions.CacheKeyPrefix
option is now fully obsolete: it has been marked with the [Obsolete]
attribute including the additional error
flag, so its use will not compile anymore (see #33 for more).
🙏 Tell me what you think
Please try it and let me know so I can push the final version out!
v0.1.9
This is a small release, in preparation of the big one where the Backplane #11 will be added 🎉.
🆕 Added CacheName
It is now possible to specify a cache name, namely a logical name that identify a cache.
It can be used for identification, and in a multi-node scenario it is typically shared between nodes to create a logical association that may be useful to have them communicate together (ref Backplane).
It is possible to specify it in the FusionCacheOptions
, and is acessible as a read-only prop directly on any FusionCache instance.
🆕 Added InstanceId
Each time a new FusionCache instance is created (eg: via a new FusionCache(...)
directly or via DI) a new id will be generated, globally and uniquely identifying that specific instance.
It can be useful to uniquely identify a single instance in a multi-node scenario, for example to precisely route notifications to each one (ref Backplane).
It is acessible as a read-only prop directly on any FusionCache instance.
🆕 Added Evict
method
A new Evict
method has been added: this method evicts an entry from the cache, like the Remove
method, but with 2 very important differencs:
- it only act on the primary layer (memory cache) and does not propagate the removal in the distributed cache, if any
- it does not raise a Remove event
Again, this is useful in the Backplane that is coming.
It is only available in a sync fashion and not in an async one, since it acts only locally and there's nothing to do asynchronously.
⚠ Marked CacheKeyPrefix as [Obsolete]
for future removal
The CacheKeyPrefix option is now obsolete: it still works, but will be kinda removed in the next version.
See here for more info.
🚀 Performance
Added a couple of small perf optimizations here and there.
v0.1.7
🔀 New option
A new FusionCacheOptions.DistributedCacheKeyModifierMode
option has been added, so that you can now control how the cache key will be modified to be used in the distributed cache (Prefix
, Suffix
or None
).
The default value is Prefix
but, if for example you are having problems with Redis ACLs (which are prefix-based), you can change this to Suffix
(or even None
) to solve them.
🙏 Thanks
Thanks to RogerSep for the hint about Redis ACLs, I hope this will solve your problem!
v0.1.6
🚀 Switch from Task<T>
to ValueTask<T>
The async part of the api surface area has been migrated from using the Task<T>
type to the ValueTask<T>
type.
This allows saving a good amount of memory allocations, making our apps more performant.
Is this a breaking change? In short, no.
To expand on it a little bit more, it could be if you directly used a Task<T>
returned from one of the async methods, instead of await
ing it normally. In that case simply add .AsTask()
to turn the ValueTask<T>
into a Task<T>
and everything will be fine.
In all other normal usage scenarios, just await
ing on one of the async methods would work absolutely the same, while also allocating less memory 🎉
⚠️ Breaking changes
I've finally removed the TryGetResult<T>
type, marked as [Obsolete]
from a lot of time now.
It has been replaced a long ago with the MaybeValue<T>
type, which is better designed and used also as an input, and not just an output.
For more information about the change please read the "Breaking change" section of the v0.1.3 release.
The same goes for the Success
prop in the MaybeValue<T>
type, also marked as [Obsolete]
since the beginning and added just to allow a more pleasant transition from the old type to the new one.
🙏 Thanks
Thanks to the the great Marc Gravell and Stephen Toub for their writings on this subject, in particular this and this which helped clear my mind on the subject.
v0.1.5
🧩 Plugins (more)
FusionCache now has an extensibility mechanism thanks to a plugins subsystem: you can easily create your own plugin and subscribe to core events to do whatever you want.
There's an introductory guide and a complete sample available.
v0.1.4
📞 Events (more)
FusionCache now has a comprehensive set of events to subscribe to, so you can be notified of core events when they happen.
Example:
// SUBSCRIBE TO CACHE MISS EVENTS
cache.Events.Miss += (s, e) => {
// REACT TO THE EVENT HERE, WITH THE RELATED CACHE KEY AVAILABLE VIA e.Key
};
This is also a stepping stone towards the next step: plugins (#15).
And thanks to @JoeShook for the invaluable help!
🚀 Performance
Added some perf optimizations.
v0.1.3
🤷 Introducing MaybeValue<T>
(more)
A new type has been introduced to model a value that may be there or not, just like the standard .NET nullables but for both reference and value types.
It supports implicit convesion to/from T
and is used in a couple of places (see below).
🕹️ Better TryGet[Async]
(more)
The TryGet[Async]
return type is now MaybeValue<T>
for better ease of use (more like the standard .NET nullables).
Example:
var maybeFoo = cache.TryGet<int>("foo");
if (maybeFoo.HasValue) {
// EXPLICIT ACCESS
var foo = maybeFoo.Value;
// OR IMPLICIT CONVERSION
int foo = maybeFoo;
}
🕹️ Better GetOrSet[Async]
(more)
The GetOrSet[Async]
methods now has an additional failSafeDefaultValue
param to handle factory failures (with fail-safe enabled) in case there's no expired/stale value to use (eg: cold start, first use, etc).
Example:
// WITH FAIL-SAFE ENABLED
cache.GetOrSet<int>("foo", _ => GetFooFromDb(), 42);
There's also a new GetOrSet[Async]
overload available that accepts a value directly instead of a factory: this covers the cases when you already have a default value to use so you don't have to allocate a useless lambda.
Example:
// BEFORE
cache.GetOrSet<int>("foo", _ => 42);
// FROM v0.1.3
cache.GetOrSet<int>("foo", 42);
⚠️ Breaking changes
The TryGet[Async]
methods now returns a MaybeValue<T>
instead of a TryGetResult<T>
.
This new type also contains the Success
prop present in the old TryGetResult<T>
type, but marked as [Obsolete]
to better ease the transition.
Also, the old TryGetResult<T>
type is still there, in case you've used that somewhere, but the type as a whole has been marked as [Obsolete]
to warn of the usage.
The only case of an actual breaking change is if you were doing something like this:
// USING IMPLICIT bool CONVERSION
if (cache.TryGet<int>("foo")) {
[...]
}
but it should have been rare, since the value would have been discarded.
Anyway, in that case, you simply have to do this now:
if (cache.TryGet<int>("foo").HasValue) {
[...]
}
or, even better:
var maybeFoo = cache.TryGet<int>("foo");
if (maybeFoo.HasValue) {
// EXPLICIT ACCESS
var foo = maybeFoo.Value;
// OR IMPLICIT CONVERSION
int foo = maybeFoo;
}
🚀 Performance
Optimized cpu and memory usage so that common scenarios will consume less resources.
v0.1.2
v0.1.1
💫 More flexible type handling
Better support for caching flows with flexible types.
Previously, doing this:
var data = (object)42;
cache.Set("foo", data);
cache.GetOrDefault<int>("foo");
would not have resulted in getting back 42
.
Thanks to type inference the Set
method call in the 2nd line in reality is a Set<object>
and this, in addition to various internal details to support advanced features (fail-safe, etc), made it incompatible to transparently swich from one type to the other.
Now this scenario is fully supported 🎉
⚠️ Namespace change
The first and last namespace change: the general namespace changed from ZiggyCreatures.FusionCaching
to ZiggyCreatures.Caching.Fusion
.
The fix should be very easy: update the packages, compile, see where it fails and change a couple of using
s, that's it.
Sorry for this hassle 🙏 , it will be the last time.
🚀 Performance
Optimized cpu and memory usage so that common scenarios will consume less resources.
v0.1.0
Initial release.
Almost all the main features currently planned are there, with tests, documentation and whatnot.