-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature - add priority race #1472
Feature - add priority race #1472
Conversation
From what I can tell, the Travis failure (for Node 7 only) is unrelated to my changes, maybe a spurious build error? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some reservations about how this is implemented. First I'm not sure if .isPrioritized = bool
is generic enough. I would prefer .priority = int
. Also don't really like the assigning of the priorities to the functions.
As for the new method itself I haven't really ever seen a use case for it. Mind providing a couple of examples?
mocha_test/priorityRace.js
Outdated
} | ||
for (var i = 0; i <= 5; i++) { | ||
tasks[i] = eachTest(i); | ||
tasks[0].priority = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this getting set for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To show that when more than one task has priority, the async operation will finish if/when all of them finish, not just one of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I meant that this should be isPrioritized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right, this was left over from an earlier implementation. Fixed.
@megawac Thanks for reviewing. Great questions. Here's the use case that motivates this. We have two db tables, A and B. Data from A is preferred -- we always use it if available. But not every query has data in A. Some queries have data in B, and if A is not available, we'll use the data from B. The simplest thing to do would be:
That's fine, but we're trying to optimize for speed. Priority race would allow us to kick off queries to A and B concurrently, return as soon as a result is found in A if one is found, else return when either B has a result or neither has a result. This speeds up two of three cases:
So that's the motivation. Regarding
For these orderings of when each task finishes:
Thanks! |
Also, I agree that assigning a property to functions is a bit odd, certainly uncommon. An alternative is to have some way inside of tasks to signal that the entire async operation should finish before all tasks are done. I read over #1064 and it seemed to have a lot of debate about how to accomplish this, so then assigning priority to tasks started to look acceptable -- it sidesteps the question of how tasks can stop the async operation. |
@sandinmyjoints could this use case be solved by async.parallel({
tableA: (callback) => {
getDataFromTableA((err, data) => {
if (err || !data) {
return callback(err);
}
// finish early, don't wait for tableB to finish
return callback(false, data);
});
},
tableB: (callback) => {
getDataFromTableB((err, data) => {
if (err) {
return callback(err);
}
return callback(null, data);
});
}
}, (err, results) => {
if (err) {
// error handling code
}
let data = results.tableA || results.tableB;
// handle the data
}); This has the same performance benefits as
For an int priority, I would expect |
@hargasinski I agree that that approach accomplishes the same outcome. My thinking was that calling back with |
I feel this method is a bit too niche to add to Async. It also feels like the control flow can be accomplished with I also think the discussion about #1064 is a bit of a red herring. There's nothing preventing you from calling an outer callback early, but currently, doing so causes a subtle memory leak since the subsequent callbacks wait forever to be called. The proposed |
OK, thanks for the thoughts and feedback @aearly @hargasinski @megawac. I'll use an alternative approach for my use case. |
This solves a similar problem to #1064. For this solution, you can't arbitrarily stop the loop (to have annotate tasks ahead of time), but otoh, it's not a breaking change.