ZiggyCreatures / FusionCache

FusionCache is an easy to use, fast and robust hybrid cache with advanced resiliency features.
MIT License
1.92k stars 97 forks source link

[FEATURE] Add MessagePack support #82

Closed jodydonetti closed 2 years ago

jodydonetti commented 2 years ago

Is your feature request related to a problem? Please describe. FusionCache provides a way to add custom serialization format support, by implementing the IFusionCacheSerializer interface.

It already provides 2 implementations, both for the JSON format:

It would be great to add support for the MessagePack serialization format, too.

Describe the solution you'd like A new package that add supports for the MessagePack format, probably based on the most used implementation on .NET, the one by Neuecc.

Describe alternatives you've considered Everyone that needs it should implement their own, which is meh 😐

jodydonetti commented 2 years ago

⚡ Implementation

The implementation has been done, and has been pushed to the main branch since it seems already working quite well.

To make it work I had to change FusionCacheDistributedEntry<TValue> class and make it public (it was internal), since this seems the only way in which the MessagePack serializer is able to work with it. It is still in the Internals namespace, so it should be quite clear for the users not to mess with it.

Another option would be to enable serialization of private data in the MessagePack serializer, but that would also include private members, which doesn't sound that good honestly.

✅ Testing Suite

I've recently refactored the testing suite to better handle multiple serializers, so in the future it should be easier to add a new one and automatically test it with every test already there and possible future tests (thanks to the [ClassData] attribute in the amazing BenchmarkDotNet).

I've also cleaned up the tests themselves and added more scenarios, including:

All in all it seems to work well.

🙏 Halp

It would be amazing if someone in the community would like to try it out and let me know what they think: any suggestion is more than welcome.

One thing in particular I'd like to know is what do you think about the way I handled the whole MessagePackSerializerOptions thing, that is what is the best way to specify it.

What I mean is that since the class that will be serialized (FusionCacheDistributedEntry<TValue>) cannot be decorated with MessagePack attribute, in theory the serializer should be instructed on how to do that (with like a mapping or similar), but I haven't found a nice way to do that in an imperative way, instead of a declarative one with attributes.

The way I made it work is by allowing users to specify which MessagePackSerializerOptions to use (either directly in the ctor or via the DI-related extension method), but the problem is that, if not specified, the default would be used which would not be able to serialize that class, since it is not mapped.

In the test suite I've manually specified to use MessagePack.Resolvers.ContractlessStandardResolver.Options which handles any type automatically (and looking at its docs it seems to be better than the old Typeless approach).

So the problem basically is that we have 2 options:

Do you have any idea? I would really like to know.

Thanks!

jodydonetti commented 2 years ago

Update: @neuecc (the creator of the underlying serializer used here) has been so kind to pass me a couple of suggestions, which I happily applied:

The code is already update with these suggestions, so everyone interested can check it out.

Thanks Neuecc!

jodydonetti commented 2 years ago

The new serializer has been published with v0.15.0 🎉