Comments (12)
just want to add that hearing your thoughts about Fusion on conceptual level would be super valuable too - i.e. this "like KO, but distributed & spawning whatever is needed on demand" aspect.
OK cool! My best understanding of this project at a conceptual level is that you're doing distributed reactive computing. That is, it has the reactive concepts of KO/MobX/Vue/etc (observables, computeds, auto dependency tracking), but you've gone to the next level and done it to span multiple servers and clients from a single dependency graph. Some parts of the dependency graph live on servers, some parts on independent clients, but conceptually it's all one global graph of data flow for your app.
This is interesting to me because, when SignalR first came out and KO was still young, I once had a long conversation in Redmond with SignalR creators @davidfowl and @DamianEdwards about what kind of tech you'd get if you combined the two. We imagined some kind of server-to-client reactivity mechanism, and envisioned UIs that automatically update and sync without developers writing explicit code to subscribe to anything. In the end it wasn't something we pursued because SignalR and KO were still novel on their own, and we didn't have a clear vision about what actual developer pain points (e.g., in mainstream web apps) would be solved via a new library versus people just writing code with SignalR and KO by hand.
So my top point of interest is what specific customer groups and app types you intend to target with Stl.Fusion. Most web app developers are building "CRUD with streamlined UX for certain predefined business operations". Which part of that should use Stl.Fusion? Or are you focused on more specialized scenarios like "live monitoring/management dashboard", or "collaborative document editing", or "MMORPG"? Those are definitely valid scenarios, but individually are way more niche than "CRUD with business-specific UX". Showing how Stl.Fusion can be used for recognisable scenarios, each with 50-line-max examples, would help a lot with persuading people it's better than the existing ways they know how to do them.
from stl.fusion.
OK cool! My best understanding of this project at a conceptual level is that you're doing distributed reactive computing. That is, it has the reactive concepts of KO/MobX/Vue/etc (observables, computeds, auto dependency tracking), but you've gone to the next level and done it to span multiple servers and clients from a single dependency graph. Some parts of the dependency graph live on servers, some parts on independent clients, but conceptually it's all one global graph of data flow for your app.
That's a great description, actually.
This is interesting to me because, when SignalR first came out and KO was still young, I once had a long conversation in Redmond with SignalR creators @davidfowl and @DamianEdwards about what kind of tech you'd get if you combined the two. We imagined some kind of server-to-client reactivity mechanism, and envisioned UIs that automatically update and sync without developers writing explicit code to subscribe to anything.
Good to know the desire to do something similar was there even in 2010 or so :)
In the end it wasn't something we pursued because SignalR and KO were still novel on their own, and we didn't have a clear vision about what actual developer pain points
Yes, totally clear. + At that point there was nothing similar to Blazor (Silverlight doesn't count), so the APIs had to be implemented both on JS & .NET, so I guess there would be noticeably more friction while you use it too.
Honestly, I ended up thinking about distributed scenarios mainly because of Blazor.
Showing how Stl.Fusion can be used for recognisable scenarios, each with 50-line-max examples, would help a lot with persuading people it's better than the existing ways they know how to do them.
I'll focus on that :) Thanks a lot, @SteveSandersonMS - super valuable feedback + kind of optimistic too :)
+ Thanks a lot for Blazor - it is absolutely amazing tech!
from stl.fusion.
Yes, and make sure that
ConfigureAwait
is only called on the sync context (viaInvokeAsync
).
Got it.
from stl.fusion.
Hi @SteveSandersonMS , I found two lock
statements in samples, both are in the same type:
The locking here is fully justified because CounterService
actually can be called from multiple threads. You can open the same page in a few windows to see the counter value it displays is always the same in each one of them, which means CounterService
is shared, and lock there serializes the access to _count
field.
In other words, this service is unrelated to Blazor, and moreover, it's a singleton, so it needs a lock.
And yes, I am aware that ConfigureAwait(false)
shouldn't be used in Blazor components. So if you see it in samples, it should be either a service code + maybe ComputeStateAsync
code, which runs outside of Blazor synchronization context too, even though it's a method of Blazor component. See https://github.com/servicetitan/Stl.Fusion/blob/master/src/Stl.Fusion.Blazor/LiveComponentBase.cs#L12 - that's the line that's ultimately responsible for this invocation.
I'm also aware there is InvokeAsync
that marshals the call to Blazor sync context: https://github.com/servicetitan/Stl.Fusion/blob/master/src/Stl.Fusion.Blazor/StatefulComponentBase.cs#L25 + I know that technically calling ConfigureAwait(false)
in ASP.NET Core doesn't change anything. I.e. maybe it's a good idea to simply remove it everywhere in samples.
from stl.fusion.
Just want to highlight one important thing: most of these samples also work in Blazor WASM mode - even though they use the same code there. And when they do work in this mode, they use Fusion proxies instead of real services, which forward calls to actual services via HTTP Client -> ASP.NET Core Controller or Fusion's Replicator-Publisher channel.
https://fusion-samples.servicetitan.com/ hosts the "main" set of samples, you can see that everything stays in sync independently on whether it's a WASM or SSB mode :)
from stl.fusion.
I see, yes, looks like you're right about the lock
.
The ConfigureAwait
calls that first stood out to me are the ones in https://github.com/servicetitan/Stl.Fusion.Samples/blob/master/src/HelloBlazorServer/Pages/Counter.razor, which is screenshotted on the project homepage.
I understand now from your comment above ComputeAsync
"runs outside of Blazor synchronization context", however I find that a bit troubling because it's an instance method on a component, and developers can't be expected to make component instance code thread-safe (everything else in the framework tells them they don't have to do that). It might be worth finding a pattern for ComputeAsync
that only gets called on the sync context to preserve single-threadedness for component instances.
from stl.fusion.
Yes, I guess I should just kill ConfigureAwait
everywhere in samples :)
from stl.fusion.
Yes, and make sure that ComputeAsync
is only called on the sync context (via InvokeAsync
).
from stl.fusion.
As for ComputeStateAsync
, I thought about this, and honestly, it's easy to marshal the call to Blazor context, but this method is supposed to touch just the state, which is thread-safe, and if it uses something from the component, most likely it's a mistake, because the dependency won't be created for this "something" (and thus no auto-update will happen, etc.).
But you're right - this breakes the pattern. I'll think about what's best here. Interestingly, originally this stuff with ComputeStateAsync
wasn't even a part of the component, but I ended up concluding that pushing people to have a separate service for every UI model is actually a worse idea. So that's why LiveComponentBase
sort of serves a dual purpose now - to build the model & to provide auto-updates. And this "duality" is what makes ComputeStateAsync
so different.
from stl.fusion.
@SteveSandersonMS just want to add that hearing your thoughts about Fusion on conceptual level would be super valuable too - i.e. this "like KO, but distributed & spawning whatever is needed on demand" aspect.
I definitely value any actionable feedback like above one - and the fact it's coming from #1 Blazor expert makes it extremely valuable. But it's also interesting to hear something regarding the concept itself. APIs are easier to fix than fundamentals, so I'm curious what's your list of pros/cons for such an approach - or at least, do you see some big cons?
from stl.fusion.
Thought more about ComputeStateAsync
- yes, it definitely makes sense to invoke it via InvokeAsync
, so I'll change this + likely, add an option to provide your own delegate instead & flag indicating whether the Blazor sync context is needed for it.
from stl.fusion.
@SteveSandersonMS I closed the issue: 8d3789c#diff-3cd3f69d47e2d6778c38eae5fb4115baa45fcdc5e8f40fa0d2b3b8c7fff3abda
The code on the left is my first attempt to fix it; it's actually unexpected that even though InvokeAsync
returns Task
, which is Task<object>
under the hood, its Result
is always null
when it succeeds, so I ended up using TaskSource<T>
to pass the result back, and I am still thinking of Fusion-related consequences. E.g. if InvokeAsync
doesn't pass ExecutionContext
somehow, this might be a mistake to switch to this model...
P.S. TaskSource<T>
is TaskCompletionSource<T>
, but struct - I've ended up adding it long time ago to kill 1 extra allocation per TaskCompletionSource<T>
.
from stl.fusion.
Related Issues (20)
- Replace LogLevel / XxxLogLevel with IsLoggingEnabled everywhere
- Possible renames HOT 2
- Add System.Text.Json serializer support HOT 1
- Add MessagePack serializer support HOT 4
- Sign the assemblies that could be signed
- async alternate HOT 3
- [StateHasChangedAsync] System.NullReferenceException: 'Object reference not set to an instance of an object.' HOT 8
- infinite query loop HOT 7
- blazor wasm only (no server side blazor) can't get auth schemes HOT 3
- Exception when using together with Moq 4.18.1 HOT 9
- Don't mask HTTP errors in replica services HOT 1
- Improve test coverage
- A DateTime value was incorrectly passed to the server in Korean. HOT 2
- Commands are executed twice? HOT 3
- Could not load type 'Stl.Fusion.Bridge.IChannelProvider' from assembly 'Stl.Fusion
- Live sample at https://fusion-samples.servicetitan.com/ is broken in wasm mode HOT 2
- Assistance Needed: List Method Not Retrieving Values and Not Subscribing to Updates HOT 5
- Assistance/Improvement for Factories/Proxies using ActivatorUtilities HOT 7
- Stl.Interception gets trimmed away HOT 10
- Add Stl.Async-way of awaiting WaitHandle HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from stl.fusion.