Coder Social home page Coder Social logo

Comments (12)

SteveSandersonMS avatar SteveSandersonMS commented on May 2, 2024 6

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.

alexyakunin avatar alexyakunin commented on May 2, 2024 6

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.

alexyakunin avatar alexyakunin commented on May 2, 2024 1

Yes, and make sure that ConfigureAwait is only called on the sync context (via InvokeAsync).

Got it.

from stl.fusion.

alexyakunin avatar alexyakunin commented on May 2, 2024

Hi @SteveSandersonMS , I found two lock statements in samples, both are in the same type:

image

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.

alexyakunin avatar alexyakunin commented on May 2, 2024

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.

SteveSandersonMS avatar SteveSandersonMS commented on May 2, 2024

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.

alexyakunin avatar alexyakunin commented on May 2, 2024

Yes, I guess I should just kill ConfigureAwait everywhere in samples :)

from stl.fusion.

SteveSandersonMS avatar SteveSandersonMS commented on May 2, 2024

Yes, and make sure that ComputeAsync is only called on the sync context (via InvokeAsync).

from stl.fusion.

alexyakunin avatar alexyakunin commented on May 2, 2024

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.

alexyakunin avatar alexyakunin commented on May 2, 2024

@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.

alexyakunin avatar alexyakunin commented on May 2, 2024

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.

alexyakunin avatar alexyakunin commented on May 2, 2024

@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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.