Giter Site home page Giter Site logo

Comments (17)

yelouafi avatar yelouafi commented on May 3, 2024 3

I'm thinking of integrating this into the next release.

The mental model is that a parent + forked children represent a whole unit: a tree with multiple execution paths.

Here is what I propose

  1. Cancellation of parent automatically triggers cancellation of all currently active forked tasks (we cancel the whole execution tree)
  2. A parent terminates when :
    1. its own body terminates and
    2. forked (and attached) tasks terminate (the whole execution tree must terminate)
  3. Provide an additional setting to fork detached children (the default for children is to be attached). The cases for this IMO should be pretty rare so rather than create another effect, W'll just provide this as a config option on the fork itself, something like : yield fork({fn, detached: true}, ...args) or yield fork(fn, ...args).detached

(1) would handle common client side scenarios: when an UI page is unloaded we'd typically like to cancel all the tasks related to that page

(2) would handle server side scenario: when we do render on the server, w'd like to wait for all triggered tasks to terminate before sending the HTML to the client (see #149)

(3) would provide an alternative for other cases

from redux-saga.

yelouafi avatar yelouafi commented on May 3, 2024 1

@slorber In this example you fork tasks then immediately join them

function* handleStamplesPaginationAndFiltering(model) {
  const subtasks = [];
  try {
    subtasks.push(yield fork(stamplePaginateSaga,model))
    subtasks.push(yield fork(stampleFilterUpdatesWatcher,model))
    yield subtasks.map(join)
  }
  catch(e) {
    if ( e instanceof SagaCancellationException ) {
      yield subtasks.map(cancel);
    }
  }
}

why not simply use

function* handleStamplesPaginationAndFiltering(model) {
  yield [
    call(stamplePaginateSaga,model),
    call(stampleFilterUpdatesWatcher,model)
  ]
}

if handleStamplesPaginationAndFiltering is cancelled from a parent Saga, then the cancellation would propagate automatically to the current effect which is the parallel yield [...]. Parallel effect cancellation means cancellation of all sub-effects

from redux-saga.

yelouafi avatar yelouafi commented on May 3, 2024

Actual behavior propagates cancellation only to the current effect; i.e. where the Saga is blocked. For subtasks, it means the cancellation propagates only to called ones but not forked ones (since the saga is not blocked on them).

Do you think cancellation should be automatically propagated to forked tasks also ?

It's true that until now I also only encountered cases when the cancellation should be propagated. But aren't there cases where the propagation is not desirable ?

Or should we perhaps provide the 2 options (like an additional method spawn which automatically propagate the cancellation) ?

from redux-saga.

slorber avatar slorber commented on May 3, 2024

It seems to me a better default in most cases, but an option would be nice too. I'm not a sysadmin but it's worth checking what linux does here

from redux-saga.

bradennapier avatar bradennapier commented on May 3, 2024

Agreed, by default forked tasks should cancel just like linux but with the ability to fork with an argument (nohup &) to break off from it's parent.

from redux-saga.

laurelnaiad avatar laurelnaiad commented on May 3, 2024

node.js uses the term detached to describe forked/spawned processes that do not end with their parent.

FWIW, at first I thought that the default for sagas would be detached (or whatever it ends up being called), but I guess I now realize that the norm for canceled parents would be to cancel children, as opposed to finished parents, which would never have a terminating effect on the child (if a parent yields a fork, then it's up to the recipient to handle that saga). This would make the path of least resistance to be that the cancelation of a parent saga could be used to "turn off" event streams that you have running in its forks, sort of an "unsubscribeAll" for forked child sagas.

from redux-saga.

slorber avatar slorber commented on May 3, 2024

@yelouafi also there's a case where the parent terminates before the forks. Should the forks be cancelled?

from redux-saga.

slorber avatar slorber commented on May 3, 2024

@yelouafi about my last comment, here I don't know how to handle a parent whose role is only to create subprocesses.

function* handleStamplesPaginationAndFiltering(model) {
  const subtasks = [];
  try {
    subtasks.push(yield fork(stamplePaginateSaga,model))
    subtasks.push(yield fork(stampleFilterUpdatesWatcher,model))
    yield subtasks.map(join)
  }
  catch(e) {
    if ( e instanceof SagaCancellationException ) {
      yield subtasks.map(cancel);
    }
  }
}

I think what I have here is pretty common and should require less boilerplate maybe? don't know just wanted you to be aware of this case

from redux-saga.

yelouafi avatar yelouafi commented on May 3, 2024

also there's a case where the parent terminates before the forks. Should the forks be cancelled?

IMO, That depends on the use case. For now the forking model as I see it is

  • forked children remain attached to their parent -> the lifetime of children is scoped by the parent's lifetime; So if the parent terminates (either normally or by error, including cancellation errors), children should also terminate (possibly adding another kind of exception for this case)
  • forked children are detached -> then children become totally independent of their parent; and not affected by the parent's outcome.

Either we should overload fork (or provide a forkDetached function) to support detached forking (I also think the attached option should be the default as in Node).

Or we can adopt the same interface in Node and provide a task.unref() (or task.detach()) method . Personally I prefer the first option.

This would make the path of least resistance to be that the cancelation of a parent saga could be used to "turn off" event streams that you have running in its forks, sort of an "unsubscribeAll" for forked child sagas.

I dont think it's a good idea. A disconnected Saga seems to be useless. And more importantly with the sync looking flow of Generators; the only way to interrupt that flow is by the Exception mechanism. Unless we provide something like unix signals or old DOS interruption mechanism.

from redux-saga.

slorber avatar slorber commented on May 3, 2024

oh ok :) will do that then haha

from redux-saga.

pke avatar pke commented on May 3, 2024

@yelouafi cool. Parallel effects with the ability to cancel is just what I was looking for in my current logni saga. There are a bunch of watchers that should spawn when a user logs in. But they should only run until the the user logs out.

Beside that, a non-attached fork should be called spawn, imho.

from redux-saga.

slorber avatar slorber commented on May 3, 2024

I'll be fine with that :)

Btw don't you think that redux-saga would start to become very close to an actor model?

  • Each actor can receive/emit events from a bus
  • Each actor can span child actors, or create detached actors
  • Killing a parent actor kills the whole branch
  • When a child actor fails, the parent is responsible for recovery strategy

I feel like we are moving in this kind of direction. Btw actor systems like Akka are often used to build backend saga

from redux-saga.

yelouafi avatar yelouafi commented on May 3, 2024

@slorber I haven't looked in detail into the Actor Model. I'll have to check it to find more about.

from redux-saga.

yelouafi avatar yelouafi commented on May 3, 2024

FYI 0.10.0 fixes this

from redux-saga.

slorber avatar slorber commented on May 3, 2024

great thanks :)

from redux-saga.

hugows avatar hugows commented on May 3, 2024

Its not clear to me how this works today. Anyone?

Its clear from docs that errors in children propagate to parents, but I didn't get if forked substaks (I call children here) can outlive their parent tasks?

Of course, a try/catch/finally can solve this...

from redux-saga.

aleksnied avatar aleksnied commented on May 3, 2024

(If anybody else comes here) I think they fixed the above, docs say:

Cancelling a Saga causes the cancellation of:

The main task this means cancelling the current Effect where the Saga is blocked

All attached forks that are still executing

WIP <=== although still says WIP ;)

https://redux-saga.js.org/docs/advanced/ForkModel/#cancellation

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.