Giter Club home page Giter Club logo

Comments (10)

yelouafi avatar yelouafi commented on May 29, 2024 1

@DjebbZ

BTW, have you seen Cycle.js ? It uses Observables from Rx to manage flow and side effects

Yes looked at it. I'm a big fan of reactive Streams. I did some experimentations on building UI using Dataflow approach offered by Observables but ended up each time with a lot of complexity (lots of signals, flow hard to reason about), plus any dynamic behavior (dynamic signal graph) involved much complex monadic manipulations (flatmap and family). Didn't looked in more detail to Cycle but it seems to solve the complex flow issue by organizing signals (Observables) into separate components.

Now I switched to the Dark side :) (i.e. the pull approach)

@slorber

I think @yelouafi will at some point want to provide extension points for the interpreter so that users will be able to plug their own effects.

Yeah, the idea crossed my mind, but I found myself replicating the Redux middleware funcionalities. One can build the effect interpreter as a Redux middleware and then use put(effect) to execute the effect.

But your proposition makes quite sens if the sagas are used outside of Redux

from redux-saga.

slorber avatar slorber commented on May 29, 2024

@DjebbZ I initially suggested to @yelouafi the saga pattern that is already used in backend's eventsourcing architectures. (long discussion here paldepind/functional-frontend-architecture#20)

Also some basic implementations I provided on top of Redux:
http://stackoverflow.com/a/33501899/82609
http://stackoverflow.com/a/33829400/82609

Some doc of the Saga pattern: https://msdn.microsoft.com/en-us/library/jj591569.aspx
Actually Sagas implemented here are more "process managers" but they are often called Saga too (this is a bit confusing yes)

What I mean here is that Saga / process manager is a pattern for which there are many possible implementations. In the backend it's not rare to see the Saga being implemented as an Actor with Scala/Akka or Erlang, or many other solutions.

Here is a Java implementation of the Axon framework just to illustrate. You can see it does not look at all the same as the implementation provided by this repo (also because the domain of a backend app is very different of a frontend app):

public class OrderManagementSaga extends AbstractAnnotatedSaga {

    private boolean paid = false;
    private boolean delivered = false;
    private transient CommandGateway commandGateway;

    @StartSaga
    @SagaEventHandler(associationProperty = "orderId")
    public void handle(OrderCreatedEvent event) {
        // client generated identifiers (1)
        ShippingId shipmentId = createShipmentId();
        InvoiceId invoiceId = createInvoiceId();
        // associate the Saga with these values, before sending the commands (2)
        associateWith("shipmentId", shipmentId);
        associateWith("invoiceId", invoiceId);
        // send the commands
        commandGateway.send(new PrepareShippingCommand(...));
        commandGateway.send(new CreateInvoiceCommand(...));
    }

    @SagaEventHandler(associationProperty = "shipmentId")
    public void handle(ShippingArrivedEvent event) {
        delivered = true;
        if (paid) {
            end(); (3)
        }
    }

    @SagaEventHandler(associationProperty = "invoiceId")
    public void handle(InvoicePaidEvent event) {
        paid = true;
        if (delivered) {
            end(); (4)
        }
    }

    // ...

}

I don't know so much the specificity of CSP and I may be wrong but the thing is @yelouafi wants to keep the effects being declarative because it makes it much easier to test (no mock required). When you use the CSP operations, it seems to me that the operation is executed right now (right?), while with the @yelouafi implementation the operations are executed in some kind of interpreter proc.js a bit like a free-monad script.

We can discuss this in next reactjs paris meetup :)

from redux-saga.

yelouafi avatar yelouafi commented on May 29, 2024

@DjebbZ Right now it looks like there is only 1 channel defined which is the Redux Store'actions (in && out).

When I defined the fork/join tasks. I considered the idea of using other channels in order to allow concurrent tasks inter-communication. But I think this would make it hard to reason about the actual control flow of the program. I prefer the structured programming approach (routine/subroutine) which makes the control flow more explicit and easy to track.

Eventually, we'd have to provide some synchronization mechanism between forked tasks. I'm still thinking about it, But I'm more willing to a more restrictive approach like some pipe operation to connect one Task's output to another Task's Input.

from redux-saga.

DjebbZ avatar DjebbZ commented on May 29, 2024

Thanks @slorber for link to the (long) discussion. My understanding is that Sagas are a way to represent side-effect as pure data (declaratively) and let a special runtime/manager execute them. In this case CSP can be viewed as an implementation detail of the manager. Could use callbacks, Promises, whatever. Am I right ?

With regards to synchronization between forked tasks @yelouafi, indeed channels may make flow harder to reason about when there's a lot of them but they provide all the power to handle async cases. I hope you'll find a way to synchronise them, because handling any complex async flows declaratively would be just awesome.

BTW, have you seen Cycle.js ? It uses Observables from Rx to manage flow and side effects. In Cycle, the program is a pure function from input Observables to output Observables. You get the testability benefit from Saga, and while not completely declarative (flows are not data, they're operators on Observables), you get some "declarativeness" since each Observable must declare all the other Observables it uses and no one can change this from the outside. I know that Cycle.js auhor is working on generating flow diagrams from code just by reading the Observables declaration.

Makes me think : all declarative is nice to read/write but always seems limiting, whereas full imperative/functional is limitless but can lead to spaghettis. Sagas seem to be somewhat in the middle ground. Is it because it's impossible to have both ? Are we using the wrong paradigms ? Is it a limitation of the language ? Should we all move to LISP (half a joke, really) ? Or Dedalus (watch this GREAT talk, you'll understand my point on languages) ?

from redux-saga.

slorber avatar slorber commented on May 29, 2024

@DjebbZ yes i think the proc to use promises is an implementation detail.

Makes me think : all declarative is nice to read/write but always seems limiting, whereas full imperative/functional is limitless but can lead to spaghettis. Sagas seem to be somewhat in the middle ground. Is it because it's impossible to have both ? Are we using the wrong paradigms ? Is it a limitation of the language ? Should we all move to LISP (half a joke, really) ? Or Dedalus (watch this GREAT talk, you'll understand my point on languages) ?

I think @yelouafi will at some point want to provide extension points for the interpreter so that users will be able to plug their own effects.

If you can build your own AST and its interpreter than you are free to do whatever you want, and Redux-saga can provide some nice and useful defaults that make sense in most cases.

from redux-saga.

mocheng avatar mocheng commented on May 29, 2024

@yelouafi In my understanding, CSP works in blocking approach. Every put holds until the message is take-ed by another process. Every take holds until there is message put into the channel.

In Redux-saga, the Store is the global channel, but take and put don't work in blocking approach. This makes Redux-saga not actually CSP. Am I correct?

from redux-saga.

mheiber avatar mheiber commented on May 29, 2024

@mocheng as far as I can tell, redux-saga is most like CSP with a single channel. put and take block the current saga ("coroutine" in CSP terms):

  • Calling take(actionType) blocks the current saga until an action with actionType is dispatched
  • Calling put(action) immediately dispatches the action, causing the store state to be synchronously updated. Any lines of code in a saga after a put are executed after action is processed by the reducer and the store is in its next state.

from redux-saga.

Andarist avatar Andarist commented on May 29, 2024

put effect is not exactly synchronous, you can look on how its handled here - https://github.com/yelouafi/redux-saga/blob/e18dfa2592b493d91b82ef68d026e311827a34ba/src/internal/proc.js#L382

from redux-saga.

mheiber avatar mheiber commented on May 29, 2024

@Andarist thanks for the correction. I think the main point stands, however, which is that put blocks (The next line of code in the saga doesn't run until after the reducer has done its work). Not 100% sure, but I tested with some small examples.

from redux-saga.

xu33 avatar xu33 commented on May 29, 2024

In CSP,the write to the channel is blocking until there's someone read it.
but in REDUX-SAGA, put/dispatch is not blocking, if there's no one take it, the message(action) will be dropped by default.
If you use action channel,it acts more like CSP.
that's my understanding.

from redux-saga.

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.