Skip to content

Commit

Permalink
Fix issue with overwritten filters (elastic#17713)
Browse files Browse the repository at this point in the history
* Fix issue with overwritten filters

* Add tests

* Only add timerange filter predicate if index exists
  • Loading branch information
timroes committed Apr 17, 2018
1 parent f5765da commit d1fb87f
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 8 deletions.
48 changes: 48 additions & 0 deletions src/ui/public/courier/data_source/__tests__/search_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import { requestQueue } from '../../_request_queue';
import { SearchSourceProvider } from '../search_source';
import StubIndexPatternProv from 'test_utils/stub_index_pattern';

function timeout() {
return new Promise(resolve => {
setTimeout(resolve);
});
}

describe('SearchSource', function () {
require('test_utils/no_digest_promises').activateForSuite();

Expand Down Expand Up @@ -154,6 +160,48 @@ describe('SearchSource', function () {
});
});

describe('#onRequestStart()', () => {
it('should be called when starting a request', async () => {
const source = new SearchSource();
const fn = sinon.spy();
source.onRequestStart(fn);
const request = {};
source.requestIsStarting(request);
await timeout();
expect(fn.calledWith(source, request)).to.be(true);
});

it('should not be called on parent searchSource', async () => {
const parent = new SearchSource();
const source = new SearchSource().inherits(parent);

const fn = sinon.spy();
source.onRequestStart(fn);
const parentFn = sinon.spy();
parent.onRequestStart(parentFn);
const request = {};
source.requestIsStarting(request);
await timeout();
expect(fn.calledWith(source, request)).to.be(true);
expect(parentFn.notCalled).to.be(true);
});

it('should be called on parent searchSource if callParentStartHandlers is true', async () => {
const parent = new SearchSource();
const source = new SearchSource().inherits(parent, { callParentStartHandlers: true });

const fn = sinon.spy();
source.onRequestStart(fn);
const parentFn = sinon.spy();
parent.onRequestStart(parentFn);
const request = {};
source.requestIsStarting(request);
await timeout();
expect(fn.calledWith(source, request)).to.be(true);
expect(parentFn.calledWith(source, request)).to.be(true);
});
});

describe('#_mergeProp', function () {
describe('filter', function () {
let source;
Expand Down
17 changes: 15 additions & 2 deletions src/ui/public/courier/data_source/search_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export function SearchSourceProvider(Promise, PromiseEmitter, Private, config) {

this.history = [];
this._requestStartHandlers = [];
this._inheritOptions = {};

this._filterPredicates = [
(filter) => {
Expand Down Expand Up @@ -197,8 +198,9 @@ export function SearchSourceProvider(Promise, PromiseEmitter, Private, config) {
* @param {SearchSource} searchSource - the parent searchSource
* @return {this} - chainable
*/
inherits(parent) {
inherits(parent, options = {}) {
this._parent = parent;
this._inheritOptions = options;
return this;
}

Expand Down Expand Up @@ -458,8 +460,19 @@ export function SearchSourceProvider(Promise, PromiseEmitter, Private, config) {
this.activeFetchCount = (this.activeFetchCount || 0) + 1;
this.history = [request];

const handlers = [...this._requestStartHandlers];
// If callparentStartHandlers has been set to true, we also call all
// handlers of parent search sources.
if (this._inheritOptions.callParentStartHandlers) {
let searchSource = this.getParent();
while (searchSource) {
handlers.push(...searchSource._requestStartHandlers);
searchSource = searchSource.getParent();
}
}

return Promise
.map(this._requestStartHandlers, fn => fn(this, request))
.map(handlers, fn => fn(this, request))
.then(_.noop);
}

Expand Down
33 changes: 27 additions & 6 deletions src/ui/public/vis/request_handlers/courier.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
}

const index = searchSource.index() || searchSource.getParent().index();
const timeFieldName = index.timeFieldName;
if (!timeFieldName) {
const timeFieldName = index && index.timeFieldName;
if (!index || !timeFieldName) {
return true;
}

Expand All @@ -40,11 +40,32 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
name: 'courier',
handler: function (vis, { appState, queryFilter, searchSource, timeRange }) {

searchSource.filter(() => {
// Create a new search source that inherits the original search source
// but has the propriate timeRange applied via a filter.
// This is a temporary solution until we properly pass down all required
// information for the request to the request handler (https://github.com/elastic/kibana/issues/16641).
// Using callParentStartHandlers: true we make sure, that the parent searchSource
// onSearchRequestStart will be called properly even though we use an inherited
// search source.
const requestSearchSource = new SearchSource().inherits(searchSource, { callParentStartHandlers: true });

// For now we need to mirror the history of the passed search source, since
// the spy panel wouldn't work otherwise.
Object.defineProperty(requestSearchSource, 'history', {
get() {
return requestSearchSource._parent.history;
},
set(history) {
return requestSearchSource._parent.history = history;
}
});

// Add the explicit passed timeRange as a filter to the requestSearchSource.
requestSearchSource.filter(() => {
return timefilter.get(searchSource.index(), timeRange);
});

removeSearchSourceParentTimefilter(searchSource, timeRange);
removeSearchSourceParentTimefilter(requestSearchSource);

if (queryFilter && vis.editorMode) {
searchSource.set('filter', queryFilter.getFilters());
Expand Down Expand Up @@ -75,7 +96,7 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
return new Promise((resolve, reject) => {
if (shouldQuery()) {
delete vis.reload;
searchSource.onResults().then(resp => {
requestSearchSource.onResults().then(resp => {
searchSource.lastQuery = {
filter: _.cloneDeep(searchSource.get('filter')),
query: _.cloneDeep(searchSource.get('query')),
Expand All @@ -88,7 +109,7 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
return _.cloneDeep(resp);
}).then(async resp => {
for (const agg of vis.getAggConfig()) {
const nestedSearchSource = new SearchSource().inherits(searchSource);
const nestedSearchSource = new SearchSource().inherits(requestSearchSource);
resp = await agg.type.postFlightRequest(resp, vis.aggs, agg, nestedSearchSource);
}

Expand Down

0 comments on commit d1fb87f

Please sign in to comment.