Description
Fusion is a .NET Core library providing a new change tracking abstraction built in assumption that every piece of data you have is a part of the observable state / model. And since there is no way to fit such a huge state in RAM, Fusion spawns the observed part of this state on-demand, holds the dependency graph of any observed state in memory to make sure every dependency of this state triggers cascading invalidation once it gets changed, and finally, it does all of this automatically and transparently for you.
This is quite similar to what any MMORPG game engine does: even though the complete game state is huge, it's still possible to run the game in real time for 1M+ players, because every player observes a tiny fraction of a complete game state, and thus all you need is to ensure this part of the state fits in RAM + you have enough computing power to process state changes for every player.
Fusion alternatives and similar packages
Based on the "Application Frameworks" category.
Alternatively, view Fusion alternatives based on common mentions on social networks and blogs.
-
CoreFX
The corefx repo contains the library implementation (called "CoreFX") for .NET Core. It includes System.Collections, System.IO, System.Xml and many other components. It builds and runs on Windows. You can 'watch' the repo to see Linux and Mac support being added over the next few months. -
ASP.NET Boilerplate
A starting point for new modern ASP.NET MVC web applications with best practices and most popular tools. -
Orleans
Orleans is a framework that provides a straight-forward approach to building distributed high-scale computing applications, without the need to learn and apply complex concurrency or other scaling patterns -
Introducing .NET Multi-platform App UI (MAUI)
.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop. -
Uno Platform
Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported. -
DotNetty
DotNetty is a port of Netty, asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. -
AspectCore Framework
AspectCore Framework is an Aspect-Oriented Programming based cross platform framework for .NET Core and .NET Framework. Core support for aspect-interceptor,dependency injection integration , web applications , data validation , and more. -
Kentor Authentication Services
Saml2 Authentication services for ASP.NET -
Spring.Net
Spring.NET is an open source application framework that makes building enterprise .NET applications easier -
peasy
Peasy is a middle tier framework that offers an easy to use and flexible rules engine and was designed to address common challenges such as concurrency handling, transactional support, fault tolerance, threading, scalability, async and multiple client support, and easy testability, all without a huge learning curve! -
Mono-Addins
Mono.Addins is a generic framework for creating extensible applications, and for creating add-ins which extend those applications -
Newbe.Claptrap
This is a set of server-side development frameworks with reactive, event sourcing and Actor pattern as basic theories. On top of this, developers can develop "distributed", "scale out", and "easy to test" application more simply. -
Database scaffolding platform
Database scaffolding tool -
PersianDataAnnotations
PersianDataAnnotations is ASP.NET Core MVC & ASP.NET MVC Custom Localization DataAnnotations (Localized MVC Errors) for Persian(Farsi) language -
HopFramework
HopFramework is a framework to create projects easily applying Domain Driven Design and a lot of patterns to delivery a better solution. -
Simplify.Web
Simplify.Web is a lightweight and fast server-side .NET web-framework based on MVC and OWIN for building HTTP based web-applications, RESTful APIs etc. -
MVCExtensibleRoleManagement
ASP.NET MVC Role-Based Security Example -
Ether.Network
Ether.Network is an open source networking library that allow developers to create simple, fast and scalable socket server or client applications over the TCP/IP protocol.
Pixel-Perfect Multi-Platform Applications with C# and XAML
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest. Visit our partner's website for more details.
Do you think we are missing an alternative of Fusion or a related project?
README
[](docs/img/Banner.gif)
All project updates are published on its Discord Server; it's also the best place for Q/A.\
![]()
![]()
What is Fusion?
Fusion is a .NET 5 / .NET Core 3.1 library providing a new change tracking abstraction built in assumption that every piece of data you have is a part of the observable state / model, and since there is no way to fit such a huge state in RAM, Fusion:
- Spawns the observed part of this state on-demand
- Holds the dependency graph of any observed state in memory to make sure every dependency of this state triggers cascading invalidation once it gets changed.
- And finally, it does all of this automatically and transparently for you, so Fusion-based code is almost identical to the code you'd write without it.
This is quite similar to what any MMORPG game engine does: even though the complete game state is huge, it's still possible to run the game in real time for 1M+ players, because every player observes a tiny fraction of a complete game state, and thus all you need is to ensure this part of the state fits in RAM + you have enough computing power to process state changes for every player.
Under the hood, Fusion turns any response of your internal and public API
into ~ (Result<T> Response, Task Invalidated)
pair, where the second part tells
when this pair has to be recomputed. But you rarely need to deal with this –
Fusion-based services return regular result types, and these pairs
(actually, IComputed<T>
instances) are created, consumed, and composed into
complex dependency graphs transparently for you.
Build a Real-Time UI
This is Fusion+Blazor Sample, delivering real-time updates to 3 browser windows:
[](docs/img/Stl-Fusion-Chat-Sample.gif)
The sample supports both (!) Server-Side Blazor and Blazor WebAssembly hosting modes – you can switch the mode on its "Home" page.
Play with these samples hosted in a small 1-core K8s cluster right now!
Check out "Why real-time UI is inevitable future for web apps?" to learn why "Refresh" action is getting obsolete.
Speedup Your Service By Caching Everything
A small benchmark in Fusion test suite
compares "raw" Entity Framework Core -
based Data Access Layer (DAL) against its version relying on Fusion.
Both tests run almost identical code - in fact, the only difference is that Fusion
version of this test uses Fusion-provided proxy wrapping the
UserService
(the DAL used in this test) instead of the actual type.
The performance difference looks shocking at first:
[](docs/img/Performance.gif)
The speedup is:
- ~31,500x for Sqlite EF Core Provider
- ~1,000x for In-memory EF Core Provider
Such a speedup is possible because Fusion ensures that every output Fusion service produces or consumes – even the intermediate one – is computed just once and reused without recomputation while it stays consistent with the ground truth.
In other words, Fusion acts as a transparent cache + incremental build system for any computation your code runs, and as you can see, it's fast enough to be able to speed up even a code relying on in-memory EF Core provider by 1000x!
Note that:
- Similarly to real-time updates, you get this speedup for free in terms of extra code.
- You also get almost always consistent cache. It's still an eventually consistent cache, of course, but the inconsistency periods for cache entries are so short that normally don't need to worry about the inconsistencies.
- The speedup you're expected to see in production may differ from these numbers a lot. Even though the results presented here are absolutely real, they are produced on a synthetic test.
"The Ungreen Web: Why our web apps are terribly inefficient?" lits more light on why this matters.
How Fusion works?
Fusion provides three key abstractions:
- Compute Services are services exposing methods "backed" by Fusion's version of "computed observables". Compute Services are responsible for "spawning" parts of the state on-demand.
- Replica Services - remote proxies of Compute Services. They allow remote clients to consume ("observe") the parts of server-side state. They typically "substitute" similar Compute Services on the client side.
- And finally,
IComputed<T>
– an observable Computed Value that's in some ways similar to the one you can find in Knockout, MobX, or Vue.js, but very different, if you look at its fundamental properties.
IComputed<T>
is:
- Thread-safe
- Asynchronous – any Computed Value is computed asynchronously; Fusion APIs dependent on this feature are also asynchronous.
- Almost immutable – once created, the only change that may happen to it is transition
to
IsConsistent() == false
state - GC-friendly – if you know about
Pure Computed Observables
from Knockout, you understand the problem.
IComputed<T>
solves it even better – dependent-dependency relationships are explicit there, and the reference pointing from dependency to dependent is weak, so any dependent Computed Value is available for GC unless it's referenced by something else (i.e. used).
All above make it possible to use IComputed<T>
on the server side –
you don't have to synchronize access to it, you can use it everywhere, including
async functions, and you don't need to worry about GC.
But there is more – any Computed Value:
- Is computed just once – when you request the same Computed Value at the same time from multiple (async) threads and it's not cached yet, just one of these threads will actually run the computation. Every other async thread will await till its completion and return the newly cached instance.
- Updated on demand – once you have an
IComputed<T>
, you can ask for its consistent version at any time. If the current version is consistent, you'll get the same object, otherwise you'll get a newly computed consistent version, and every other version of it is guaranteed to be marked inconsistent. At glance, it doesn't look like a useful property, but together with immutability and "computed just once" model, it de-couples invalidations (change notifications) from updates, so ultimately, you are free to decide for how long to delay the update once you know certain state is inconsistent. - Supports remote replicas – any Computed Value instance can be published,
which allows any other code that knows the publication endpoint and publication ID
to create a replica of this
IComputed<T>
instance in their own process. Replica Services mentioned above rely on this feature.
Why these features are game changing?
Real-time typically implies you need one or another flavor of event-driven architecture (CQRS, event sourcing, actors, etc.). And all these options are more complex than a simple and familiar request-response model, which Fusion allows you to use.
Besides that, Fusion solves a complex problem of identifying and tracking dependencies automatically for any method that uses Fusion-based services (+ its own logic) to produce the output, and implementing this without Fusion is not only hard, but quite error prone problem.
Of course you still can use events, event sourcing, CQRS, etc. - you'll just need maybe 100× fewer event types.
Check out how Fusion differs from SignalR – this post takes a real app example (Slack-like chat) and describes what has to be done in both these cases to implement it.
Does Fusion scale?
Yes. MMORPG example provided earlier hints on how Fusion-based apps scale. But contrary to games, web apps rarely have a strong upper limit on update delay – at least for a majority of content they present. This means you can always increase these delays to throttle down the rate of outgoing invalidation and update messages, and vice versa. In other words, Fusion-based web apps should scale much better than MMORPG.
Check out "Scaling Fusion Services" part of the Tutorial to see a much more robust description on how Fusion scales.
Enough talk. Show me the code!
Compute Services is where a majority of Fusion-based code is supposed to live. CounterService from HelloBlazorServer sample is a good example of such a service:
[](docs/img/CounterService.gif)
Lime-colored parts show additions to a similar singleton service you'd probably have in case when real-time updates aren't needed:
[ComputeMethod]
indicates that anyGetCounterAsync
result should be "backed" by Computed Value. This attribute works only when you register a service as Compute Service in IoC container and the method it is applied to is virtual.Computed.Invalidate
call finds a Computed Value "backing" the most recentGetCounterAsync
call with the same arguments (no arguments in this case) and invalidates it - unless it doesn't exist or was invalidated earlier. We have to manually invalidate this value becauseGetCounterAsync
doesn't call any other Compute Services, and thus its result doesn't have any dependencies which otherwise would auto-invalidate it.
Counter.razor is a Blazor Component that uses
CounterService
:
[](docs/img/CounterRazor.gif)
Again, lime-colored parts show additions to a similar Blazor Component without real-time updates:
- It inherits from LiveComponentBase - a small wrapper over
ComponentBase
(base class for any Blazor component), which addsState
property and abstractComputeStateAsync
method allowing to (re)compute theState.Value
once any of its dependencies changes. LiveComponent<T>.State
property is a Live State - an object exposing the most current Computed Value produced by a computation (Func<...>
) and making sure it gets recomputed with a controllable delay after any of its dependencies change.- As you might guess,
ComputeStateAsync
definesState.Value
computation logic in anyLiveComponentBase<T>
descendant.
Blue-colored parts show how State
is used:
State.LastValue
is the most recent non-error value produced by the computation. It's a "safe pair" toState.Value
(true most recent computation result), which throws an error ifState.Error != null
.State.Error
contains an exception thrown byComputeStateAsync
when it fails, otherwisenull
.
That's almost literally (minus IoC registration) all you need to have this: [](docs/img/Stl-Fusion-HelloBlazorServer-Counter-Sample.gif)
And if you're curious how "X seconds ago" gets updated,
notice that ComputeStateAsync
invokes TimeService.GetMomentsAgoAsync
,
which looks as follows:
[](docs/img/TimeService.gif)
In other words, ComputeStateAsync
becomes dependent on "moments ago"
value, and this value self-invalidates ~ at the right moment triggering
cascading ComputeStateAsync
invalidation.
"Simple Chat" is a bit more complex example showing another interesting aspect of this approach:
Since any event describes a change, Fusion's only "invalidated" event ("the output of f(...) changed") allows you to implement a reaction to nearly any change without a need for a special event!
"Simple Chat" features a chat bot that listens to new chat messages and responds to them:
[](docs/img/Stl-Fusion-HelloBlazorServer-SimpleChat-Sample.gif)
ChatService
source code doesn't have any special logic to support chat bots -
similarly to CounterService
, it's almost the same as a similar service that
doesn't support any kind of real-time behavior at all:
[](docs/img/ChatService.gif)
But since ChatService
is a Compute Service, you can implement a "listener"
reacting to changes in GetMessagesAsync
output relying on e.g. Live State -
and
that's exactly what ChatBotService
does.
Next Steps
- Check out Tutorial, Samples, or go to [Documentation Home]
- Join our Discord Server or Gitter to ask questions and track project updates.
Posts And Other Content
- Fusion: Current State and Upcoming Features
- The Ungreen Web: Why our web apps are terribly inefficient?
- Why real-time UI is inevitable future for web apps?
- How similar is Fusion to SignalR?
- How similar is Fusion to Knockout / MobX?
- Fusion In Simple Terms
P.S. If you've already spent some time learning about Fusion, please help us to make it better by completing [Fusion Feedback Form] (1…3 min).
*Note that all licence references and agreements mentioned in the Fusion README section above
are relevant to that project's source code only.