In Shake there is a way to run an Action from Rules:
action :: Action a -> Rules ()
But I couldn't find a function which returns the result of the Action, namely:
actionWithResult :: Action a -> Rules a
How come?
The reason is that Rules is run first, to completion, and then Actions are run - so it's somewhat staged programming. All action does is records an Action, to execute later. The reason you have to run all the Rules first is so that it can collect all the possible types of rule that are available, since they're all available for all Actions.
Once you understand the staging, it's impossible to have Action a -> Rules a, because that implies running an Action and returning the result to Rules, so Action must run before Rules completes. However, Actions a -> Rules () is fine, because it doesn't actually run then, but later.
Related
I am implementing a use case in Flink stateful functions. My specification highlights that starting from a stateful function f a business workflow (in other words a group of stateful functions f1, f2, … fn are called either sequentially or in parallel or both ). Stateful function f waits for a result to be returned to update a local state, it as well starts a timeout callback i.e. a message to itself. At timeout, f checks if the local state is updated (it has received a result), if this is the case life is good.
However, if at timeout f discovers that it has not received a result yet, it has to launch a compensating workflow to undo any changes that stateful functions f1, f2, … fn might have received.
Does Flink stateful functions framework support such as a design pattern/use case, or it should be implemented at the application level? What is the simplest design to achieve such a solution? For instance, how to know what functions of the workflow stateful functions f1, f2, … fn were affected by the timedout invocation (where the control flow has been timed out)? How does Flink sateful functions and the concept of integrated messaging and state facilitate such a pattern?
Thank you.
I posted the question on Apache Flink mailing list and got the following response by Igal Shilman, Thanks to Igal.
The first thing that I would like to mention is that, if your original
motivation for that scenario is a concern of a transient failures such as:
did function Y ever received a message sent by function X ?
did sending a message failed?
did the target function is there to accept a message sent to it?
did the order of message got mixed up?
etc'
Then, StateFun eliminates all of these problems and a whole class of
transient errors that otherwise you would have to deal with by yourself in
your business logic (like retries, backoffs, service discovery etc').
Now if your motivating scenario is not about transient errors but more
about transactional workflows, then as Dawid mentioned you would have to
implement
this in your application logic. I think that the way you have described the
flow should map directly to a coordinating function (per flow instance)
that keeps track of results/timeouts in its internal state.
Here is a sketch:
A Flow Coordinator Function - it would be invoked with the input
necessary to kick off a flow. It would start invoking the relevant
functions (as defined by the flow's DAG) and would keep an internal state
indicating
what functions (addresses) were invoked and their completion statues.
When the flow completes successfully the coordinator can safely discard its
state.
In any case that the coordinator decides to abort the flow (an internal
timeout / an external message / etc') it would have to check its internal
state and kick off a compensating workflow (sending a special message to
the already succeed/in progress functions)
Each function in the flow has to accept a message from the coordinator,
in turn, and reply with either a success or a failure.
I am not clear in when to use takeEvery and when to use takeLatest ? in redux-saga.
I got a basic difference by reading the official documentation. But what is the use of creating concurrent actions in takeEvery (for example, the user clicks on a Load User button 2 consecutive times at a rapid rate, the 2nd click will dispatch a USER_REQUESTED while the fetchUser fired on the first one hasn't yet terminated)
import { takeEvery } from `redux-saga/effects`
function* fetchUser(action) {
...
}
function* watchFetchUser() {
yield takeEvery('USER_REQUESTED', fetchUser)
}
Can anyone please explain. As I am completely new to redux-saga.
Thanks in advance.
Though #Martin Kadlec's solid answers covers the question, I want to elaborate a bit more on the details and differences on takeEvery and takeLatest and when they might be used so you can derive the possible use-cases of them.
TLDR:
You can use takeEvery when the returns of all previous tasks are needed. For example fetching temperature and humidity data from a weatherstation over a certain period to be stored in a database and displayed as a graph - in this case all previous sagas and their return-values are of interset and not only the latest.
You can use takeLatest if i.E. a internal/external instance or a user of an interface could trigger multiple consecutive actions and only the conclusion of the last value is desireable. A good example would be rapid calls to a broker-API for a live-ticker for stock-values where only the latest/most recent value is of interest.
DETAILED:
Think of takeEvery and takeLatest as helper funtions on top of the lower level API of redux-saga which are wrapping internal operations such as spawning tasks when specific actions are dispatched to the Store. Calling them spawns a saga on each action dispatched to the Store that matches pattern.
takeEvery:
The most common takeEvery function is very similar to redux-thunk in its behaviour and methodology. It's basically a wrapper for yield take of a pattern or channel and yield fork.
The clue about takeEvery is that it allows multiple instances of a defined action/task (such as fetchSomeThing in the example below) to be started concurrently/simultaniously.
Unlike takeLatest you can start a new fetchSomeThing task while one or more previous instances of fetchSomeThing have not yet been completed/terminated, therefore are still pending. Keep in mind that there is no guarantee that the tasks will terminate/complete in the same order they were started. To handle out of order responses, you could use takeLatest.
From the official docs:
takeEvery(pattern, saga, ...args)
Spawns a saga on each action dispatched to the Store that matches pattern.
pattern: String | Array | Function
saga: Function - a Generator function
args: Array - arguments to be passed to the started task. takeEvery will add the incoming action to the argument list (i.e. the action will be the last argument provided to saga)
You can also pass in a channel as argument instead of a pattern resulting in the same behaviour as takeEvery(pattern, saga, ...args).
takeLatest:
The takeLatest helper function in contrast only gets the response of the latest request that was fired and can be seen as a wrapper for yield take of a pattern or channel and an additional if-statement checking if a lastTask is present (a previous task that is still pending), which will then be terminated via a yield cancel and a subsequent yield fork that will spawn the current task/action.
From the official docs:
takeLatest(pattern, saga, ...args)
Will only get the response of the latest request fired.
pattern: String | Array | Function
saga: Function - a Generator function
args: Array - arguments to be passed to the started task. takeLatest will add the incoming action to the argument list (i.e. the action will be the last argument provided to saga)
Similar to takeEvery you can also pass in a channel as argument instead of a pattern.
This is something you really need to think about per use case.
These are some cases when you might use takeEvery.
For sagas that are not asynchronous and so there is no reason to
cancel them. takeLatest would work here as well but it might give
false indication when reading code that there is something to
cancel.
Sometimes when the action differs in some way each time. E.g.
imagine you have a movie and you are adding tags with genre of the
movie. Each time the action is triggered you get a different genre,
even though it is the same action type. The user can add genres
quicker than you get response from the server. But just because you
added multiple genres quickly doesn't mean you want to stop the saga
adding the previous one.
Cheap implementation of when you have the same load action for
multiple different items. E.g. You have list of movies and each has
"load detail" button. (Let's ignore the fact that you should
probably hide or disable the button once the loading starts). The
data are always the same for one movie but differs in between them.
When you click on load detail for movie 1 you don't want to cancel
loading of data for movie 2. Since it is a dynamic list of movies
the action type is the same every time, the difference will be
probably something like id of the movie in the action.
In ideal implementation you should probably cancel the previous load saga for
the same movie/id, but that will require more complicated code and
so if you are doing only some simple app you might decide to ignore
that and just allow to run the sagas for same movie multiple times.
That is why I call it "cheap implementation".
To summarize in a few words,
takeEvery allows concurrent actions to be handled. For example, the user clicks on a Load User button 2 consecutive times at a rapid rate, the 2nd click will dispatch a USER_REQUESTED action while the fetchUser fired on the first one hasn't yet terminated.
takeEvery doesn't handle out of order responses from tasks. There is no guarantee that the tasks will terminate in the same order they were started. To handle out of order responses, you may consider takeLatest.
takeLatest instead start a new fetchUser task on each dispatched USER_REQUESTED action. Since takeLatest cancels any pending task started previously, we ensure that if a user triggers multiple consecutive USER_REQUESTED actions rapidly, we'll only conclude with the latest action
Docu: https://redux-saga.js.org/docs/api/
takeEvery - enables the use of several fetchData objects at the same time.
At a given moment, we can start a new fetchData task while there
are still one or more previous fetchData tasks which have not
yet terminated.
takeLatest - Only one fetchData task can be active at any given moment. It
will also be the work that was started most recently. If a new
fetchData job is started while a previous task is still running,
the previous work will be terminated immediately.
What is the difference between seeding a action and call a 'setter' method of a store in reflux data flow?
TodoActions['add'](todo)
vs
TodoStore.add(todo)
Action will trigger your store via RefluxJS lib, but Store.Add() is calling add method directly
First off, it's useful to note that Whatever.func() and Whatever['func']() are just two different syntaxes for the same thing. So the only difference here in your example is what you're calling it on.
As far as calling a method in a store directly, vs. an action which then ends up calling that method in a store, the difference is architectural, and has to do with following a pattern that is more easily scaled, works more broadly, etc. etc.
If any given event within the program (such as, in this case, adding something) emits 1 clear action that anything can listen for, then it becomes MUCH easier to build large programs, edit previously made programs, etc. The component saying that this event has happened doesn't need to keep track of everywhere that might need to know about it...it just needs to say TodoActions.add(todo), and every other part of the program that needs to know about an addition happening can manage itself to make sure it's listening for that action.
So that's why we follow the 1 way looping pattern:
component -> action -> store -> back to component
Because then the flow of events happening is much more easily managed, because each part of the program can manage its own knowledge about the program state and when it needs to be changed. The component emitting the action doesn't need to know every possible part of the program that might need that action...it just needs to emit it.
After having built a few apps using (what I believe) to be a Flux architecture based off a framework I built, I wonder what it means when:
Mozilla says:
"The dispatcher dispatches actions to interested stores. Only one
action can be processed at any one time."
Or Facebook says:
"We need the dispatcher to be able to invoke the callback for Store B,
and finish that callback, before moving forward with Store A."
Why I'm confused is because Javascript's concurrency model only allows one thing to happen at once, and ensures the call stack of the current action is depleted before it moves on with the task Queue.
So we get for free what Facebook and Mozilla says their dispatchers give us. We can't avoid it. Why are we talking about it like it's anything special?
Well... another consideration is if your "action" does something asynchronous with a callback like:
update state,
fire off an XHR,
update state with result.
Here your action can be broken in 2 parts and something can happen in between 2 and 3, thus violating the "one action at a time" principle.
That problem is solved by nothing more than terminology:
Define Action A as the thing that updates state and sends XHR.
result of XHR triggers Action B which updates state.
After all, Facebook has said "Actions may also come from other places, such as the server."
So with a little change in terminology we have no need for a dispatcher that does anything beyond dispatch an event to interested stores.
So what am I missing? Why must a dispatcher in Flux do anything more than dispatch?
My answer is: the people who wrote those bits of documentation weren't clear in what they were talking about.
Even the top stackoverflow React answerer and React contributor says:
In my understanding, asynchronous actions that rely on Ajax, etc.
shouldn't block the action from being dispatched to all subscribers.
You'll have a separate action for the user action, like
TODO_UPDATE_TEXT in the TodoMVC example and one that gets called when
the server returns, something like TODO_UPDATE_TEXT_COMPLETED (or
maybe just something more generic like TODO_UPDATE_COMPLETED that
contains a new copy of the latest attributes).
See: https://stackoverflow.com/a/23637463/131227
I've found lots of examples of calling custom actions in WiX using Binary element, but none examples where a File element was used. Can anyone give me an example?
Not strictly true about needing to run the action deferred! You can use the InstallExecute action to run all the spooled actions up to that point, including, for example file installation. After that you could schedule an immediate action which depends on the newly-installed file, which at this point will be present.
That said, if the file is going to make any changes to the machine state, then the CA really needs to be deferred in system context, so InstallExecute doesn't really buy you anything.