-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Don't kill an entire dashboard because of one bad request #11337
Don't kill an entire dashboard because of one bad request #11337
Conversation
b10ec0b
to
336bf73
Compare
I've seen this flaky failure before:
jenkins, test this |
336bf73
to
5e10b8b
Compare
e942bde
to
3105fbe
Compare
Tests are now passing. When you get a chance, lmk what you think about this fix, @spalger. |
return Promise.try(req.getFetchParams, void 0, req) | ||
.then(function (fetchParams) { | ||
return (req.fetchParams = fetchParams); | ||
promiseMapSettled( |
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 think that promiseMapSettled()
would be more clearly implemented as two lines at the bottom of Promise.map()
's mapper:
Promise.map(arr, item => {
return Promise.try(...)
.then(value => ({ resolved: value })
.catch(err => ({ rejected: 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.
👏 Much simpler, thanks!
}, | ||
Promise) | ||
.then(function (results) { | ||
const requestsWithFetchParams = results.map((result, index) => { |
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'm not in love with this solution, but I've spent a couple hours trying to come up with a better one and none of my ideas will take less than a couple days... This works, and the scope of the change is impressively small, so I'm happy with it 😎
} else { | ||
const request = executable[index]; | ||
request.handleFailure(result.rejected); | ||
executable[index] = undefined; |
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 think that if we return undefined
here it will be more clear why_.remove(requestsWithFetchParams, request => request === undefined);
is necessary
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.
Otherwise I think it might make more sense to just build up requestsWithFetchParams
in a forEach
loop rather than using .map()
followed by deletes
}) | ||
.then(function (reqsFetchParams) { | ||
return strategy.reqsFetchParamsToBody(reqsFetchParams); | ||
_.remove(executable, request => request === undefined); |
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.
Can we use x = x.filter(...)
so that both executable
and requestsWithFetchParams
have to be defined with let
and signify that they are modified below.
@@ -3,7 +3,7 @@ import expect from 'expect.js'; | |||
import ngMock from 'ng_mock'; | |||
import { WorkQueue } from 'ui/routes/work_queue'; | |||
import sinon from 'auto-release-sinon'; | |||
import 'ui/promises'; | |||
import 'ui/promises/index'; |
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.
This should not be necessary since: 9bdbc26
If for some reason it is please file an issue at https://github.com/elastic/webpack-directory-name-as-main, but if we remove promiseMapSettled()
then this doesn't really mean much.
Some tests get rid of the angular promise library so it works better if it’s a separate function then on the actual angular Promise class.
Use a much simpler implementation
3105fbe
to
19f2b8a
Compare
Jenkins, test this |
All changes should be addressed @spalger. |
@stacey-gammon LGTM, thanks! |
) * Don't kill an entire dashboard because of one bad request Some tests get rid of the angular promise library so it works better if it’s a separate function then on the actual angular Promise class. * Fix promise path references after creation of index file. * Remove index suffix from import paths * Remove promiseMapSettled Use a much simpler implementation * Clean up
…11652) * Don't kill an entire dashboard because of one bad request Some tests get rid of the angular promise library so it works better if it’s a separate function then on the actual angular Promise class. * Fix promise path references after creation of index file. * Remove index suffix from import paths * Remove promiseMapSettled Use a much simpler implementation * Clean up
) * Don't kill an entire dashboard because of one bad request Some tests get rid of the angular promise library so it works better if it’s a separate function then on the actual angular Promise class. * Fix promise path references after creation of index file. * Remove index suffix from import paths * Remove promiseMapSettled Use a much simpler implementation * Clean up
Fixes #9747
Summary: Previously if a visualization caused a request error to be thrown, the entire dashboard would fail to load. We changed that so now the rest of the visualizations will continue to load successfully, helping you narrow down which visualizations the errors are coming from.
Note: I will clean the code up if this way forward is approved (and add a hefty amount of comments) but waiting for feedback before spending the time.
It filters out failing requests, and considered them "aborted". I briefly investigated marking them as failures, which might work too, but it doesn't seem to make a difference.
The logic is extremely convoluted and I'm not confident this doesn't raise issues in other situations. I started working on some clean up but it went farther and farther and decided to extricate myself. I could continue back down that path, but it's time consuming.
So @spalger I'd like to get your opinion on this and what you think the best way forward is. It looks like our courier was never meant to handle partial failures. Making this more explicit would require some refactoring and I'm not sure the time investment is worth it.
But this implementation does solve the issue, and dashboards will now show all visualizations except the failing ones which are blank. They should probably show the error inside the visualization, but because it's a top level notify error, this isn't clear.
Before:
After:
The fix, while a bit hacky, could prove really helpful in debugging user issues because it helps a user narrow down the faulty visualizations. The field error is pretty common and takes some time to figure out which field is killing the visualization which is killing the entire dashboard.