Comments (17)
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
- Cancellation of parent automatically triggers cancellation of all currently active forked tasks (we cancel the whole execution tree)
- A parent terminates when :
- its own body terminates and
- forked (and attached) tasks terminate (the whole execution tree must terminate)
- 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)
oryield 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.
@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.
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.
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.
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.
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.
@yelouafi also there's a case where the parent terminates before the forks. Should the forks be cancelled?
from redux-saga.
@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.
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.
oh ok :) will do that then haha
from redux-saga.
@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.
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.
@slorber I haven't looked in detail into the Actor Model. I'll have to check it to find more about.
from redux-saga.
FYI 0.10.0 fixes this
from redux-saga.
great thanks :)
from redux-saga.
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.
(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)
- Waiting for an action with takeMaybe / take after END is dispatched for SSR HOT 7
- Is it possible to selectively cancel tasks in an actionChannel? Ie cancel the 3rd task out of 5 running ones. HOT 5
- Is it possible for a saga to "trace" the effect "chain"? HOT 4
- Delay inside of while loop may never fire with React Native 0.71.6 HOT 2
- UI freezes when chrome devtools is open HOT 4
- Redux 4.0 - Unable to access updated data using useSelector HOT 2
- could we add leading/trailing edge options for debounce? HOT 3
- Workflow has flaw
- Why not use the await and async instead of the generator and yield? HOT 1
- TS2345 error while putting thunk actions
- React native Redux Saga with Redux Tollkit
- Module '"redux-saga/effects"' has no exported member 'call'. HOT 4
- Is there a standard way to break while true loops with call effect when END is dispatched? HOT 1
- Can put type improvements be released downstream? HOT 2
- Sending very large files, tasks in parallel are using a lot of memory
- How to use package that use redux-saga as dependency when its in webpack externals? HOT 7
- Help me connect redux-saga with Nextjs 13.5 using app router HOT 2
- Update peer dependencies to include `redux@5` (currently beta) HOT 14
- feature request: interface for integration with other frameworks (like Vue) HOT 2
- Redux saga is not working in apps script react js project HOT 2
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 redux-saga.