From c13450d3412955271130b1a503178c1e1bb79cc7 Mon Sep 17 00:00:00 2001 From: CJ Cenizal Date: Thu, 30 Aug 2018 19:54:11 -0700 Subject: [PATCH] Fix regression in CallClient, which caused request errors like timeouts to result in fatal errors. (#22558) --- .../courier/fetch/__tests__/call_client.js | 29 +++++++++++++++++++ src/ui/public/courier/fetch/call_client.js | 11 +++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/ui/public/courier/fetch/__tests__/call_client.js b/src/ui/public/courier/fetch/__tests__/call_client.js index 565af41f23ebf..efb26e7ea2598 100644 --- a/src/ui/public/courier/fetch/__tests__/call_client.js +++ b/src/ui/public/courier/fetch/__tests__/call_client.js @@ -119,6 +119,35 @@ describe('callClient', () => { expect(results).to.eql([1]); }); }); + + it(`resolves the promise despite the request failing`, () => { + addSearchStrategy({ + id: 'fail', + isViable: indexPattern => { + return indexPattern.type === 'fail'; + }, + search: () => { + return { + searching: Promise.reject(new Error('Search failed')), + failedSearchRequests: [], + abort: () => {}, + }; + }, + }); + + const searchRequestFail = createSearchRequest('fail', { + source: { + getField: () => ({ type: 'fail' }), + }, + }); + + searchRequests = [ searchRequestFail ]; + const callingClient = callClient(searchRequests); + + return callingClient.then(results => { + expect(results).to.eql(undefined); + }); + }); }); describe('implementation', () => { diff --git a/src/ui/public/courier/fetch/call_client.js b/src/ui/public/courier/fetch/call_client.js index fd8266eb6e122..d279b9deb343e 100644 --- a/src/ui/public/courier/fetch/call_client.js +++ b/src/ui/public/courier/fetch/call_client.js @@ -183,17 +183,18 @@ export function CallClientProvider(Private, Promise, es) { } }); - // If there are any errors, notify the searchRequests of them. - defer.promise.catch((err) => { + // Return the promise which acts as our vehicle for providing search responses to the consumer. + // However, if there are any errors, notify the searchRequests of them *instead* of bubbling + // them up to the consumer. + return defer.promise.catch((err) => { + // By returning the return value of this catch() without rethrowing the error, we delegate + // error-handling to the searchRequest instead of the consumer. searchRequests.forEach((searchRequest, index) => { if (searchRequestsAndStatuses[index] !== ABORTED) { searchRequest.handleFailure(err); } }); }); - - // Return the promise which acts as our vehicle for providing search responses to the consumer. - return defer.promise; } return callClient;