Simplify Courier interface and organize internals (#20060)
**Interface changes** There are two goals behind the interface changes: * Make it clearer which courier modules are meant for public consumption by exporting them from the top level. * Simplify the courier object by removing responsibilities and focusing its responsibility solely on scheduling search requests via the fetch method and timefilter.refreshInterval Angular event. I did this by taking the following steps: * Removing redirectWhenMissing, indexPatterns, SearchSource, and SavedObject from the courier object. I also removed some unused methods from its interface. * redirectWhenMissing is now a service registered on the kibana/url Angular module. * indexPatterns is now a service registered on the kibana/index_patterns Angular module. * SearchSourceProvider and SavedObjectProvider are now top-level exports of ui/courier. * migrateFilter, decorateQuery, buildQueryFromFilters, and luceneStringToDsl are now top-level exports of ui/courier. **Internal changes** I also made some internal changes in an effort to organize the code clearly and reduce unnecessary complexity. * I refactored the async code in CallClient to appear sync with async/await and encapsulated chunks of logic in helper functions. I also used an isAborted flag instead of overwriting the esPromise var with an enum. * I combined Looper and SearchLooper into a single class and deleted unused functions. * I reorganized the courier/fetch/request code into SearchRequest, SegmentedSearchRequest, and serializeFetchParams modules. * Renamed various other methods and variables to improve clarity.
This commit is contained in:
parent
c8185cfef5
commit
3ea4c3e0bc
|
@ -19,15 +19,13 @@
|
|||
|
||||
import sinon from 'sinon';
|
||||
|
||||
export function createCourierStub() {
|
||||
export function createIndexPatternsStub() {
|
||||
return {
|
||||
indexPatterns: {
|
||||
get: sinon.spy(indexPatternId =>
|
||||
Promise.resolve({
|
||||
id: indexPatternId,
|
||||
})
|
||||
),
|
||||
},
|
||||
get: sinon.spy(indexPatternId =>
|
||||
Promise.resolve({
|
||||
id: indexPatternId,
|
||||
})
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ import expect from 'expect.js';
|
|||
import ngMock from 'ng_mock';
|
||||
import sinon from 'sinon';
|
||||
|
||||
import { createCourierStub } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier/data_source/search_source';
|
||||
import { createIndexPatternsStub } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier';
|
||||
|
||||
import { fetchAnchorProvider } from '../anchor';
|
||||
|
||||
|
@ -35,7 +35,7 @@ describe('context app', function () {
|
|||
let SearchSourceStub;
|
||||
|
||||
beforeEach(ngMock.module(function createServiceStubs($provide) {
|
||||
$provide.value('courier', createCourierStub());
|
||||
$provide.value('indexPatterns', createIndexPatternsStub());
|
||||
}));
|
||||
|
||||
beforeEach(ngMock.inject(function createPrivateStubs(Private) {
|
||||
|
|
|
@ -21,8 +21,8 @@ import expect from 'expect.js';
|
|||
import ngMock from 'ng_mock';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { createCourierStub, createSearchSourceStubProvider } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier/data_source/search_source';
|
||||
import { createIndexPatternsStub, createSearchSourceStubProvider } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier';
|
||||
|
||||
import { fetchContextProvider } from '../context';
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe('context app', function () {
|
|||
let getSearchSourceStub;
|
||||
|
||||
beforeEach(ngMock.module(function createServiceStubs($provide) {
|
||||
$provide.value('courier', createCourierStub());
|
||||
$provide.value('indexPatterns', createIndexPatternsStub());
|
||||
}));
|
||||
|
||||
beforeEach(ngMock.inject(function createPrivateStubs(Private) {
|
||||
|
|
|
@ -21,8 +21,8 @@ import expect from 'expect.js';
|
|||
import ngMock from 'ng_mock';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { createCourierStub, createSearchSourceStubProvider } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier/data_source/search_source';
|
||||
import { createIndexPatternsStub, createSearchSourceStubProvider } from './_stubs';
|
||||
import { SearchSourceProvider } from 'ui/courier';
|
||||
|
||||
import { fetchContextProvider } from '../context';
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe('context app', function () {
|
|||
let getSearchSourceStub;
|
||||
|
||||
beforeEach(ngMock.module(function createServiceStubs($provide) {
|
||||
$provide.value('courier', createCourierStub());
|
||||
$provide.value('indexPatterns', createIndexPatternsStub());
|
||||
}));
|
||||
|
||||
beforeEach(ngMock.inject(function createPrivateStubs(Private) {
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { SearchSourceProvider } from 'ui/courier/data_source/search_source';
|
||||
import { SearchSourceProvider } from 'ui/courier';
|
||||
|
||||
export function fetchAnchorProvider(courier, Private) {
|
||||
export function fetchAnchorProvider(indexPatterns, Private) {
|
||||
const SearchSource = Private(SearchSourceProvider);
|
||||
|
||||
return async function fetchAnchor(
|
||||
|
@ -30,8 +30,7 @@ export function fetchAnchorProvider(courier, Private) {
|
|||
anchorId,
|
||||
sort
|
||||
) {
|
||||
const indexPattern = await courier.indexPatterns.get(indexPatternId);
|
||||
|
||||
const indexPattern = await indexPatterns.get(indexPatternId);
|
||||
const searchSource = new SearchSource()
|
||||
.inherits(false)
|
||||
.set('index', indexPattern)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
|
||||
// @ts-ignore
|
||||
import { SearchSourceProvider } from 'ui/courier/data_source/search_source';
|
||||
import { SearchSourceProvider } from 'ui/courier';
|
||||
|
||||
import { reverseSortDirection } from './utils/sorting';
|
||||
|
||||
|
@ -46,7 +46,7 @@ const DAY_MILLIS = 24 * 60 * 60 * 1000;
|
|||
// look from 1 day up to 10000 days into the past and future
|
||||
const LOOKUP_OFFSETS = [0, 1, 7, 30, 365, 10000].map((days) => days * DAY_MILLIS);
|
||||
|
||||
function fetchContextProvider(courier, Private) {
|
||||
function fetchContextProvider(indexPatterns, Private) {
|
||||
/**
|
||||
* @type {{new(): SearchSourceT}}
|
||||
*/
|
||||
|
@ -159,7 +159,7 @@ function fetchContextProvider(courier, Private) {
|
|||
* @returns {Promise<Object>}
|
||||
*/
|
||||
async function createSearchSource(indexPatternId, filters) {
|
||||
const indexPattern = await courier.indexPatterns.get(indexPatternId);
|
||||
const indexPattern = await indexPatterns.get(indexPatternId);
|
||||
|
||||
return new SearchSource()
|
||||
.inherits(false)
|
||||
|
|
|
@ -31,8 +31,8 @@ uiRoutes
|
|||
controller: ContextAppRouteController,
|
||||
controllerAs: 'contextAppRoute',
|
||||
resolve: {
|
||||
indexPattern: function ($route, courier) {
|
||||
return courier.indexPatterns.get($route.current.params.indexPatternId);
|
||||
indexPattern: function ($route, indexPatterns) {
|
||||
return indexPatterns.get($route.current.params.indexPatternId);
|
||||
},
|
||||
},
|
||||
template: contextAppRouteTemplate,
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
} from './constants';
|
||||
|
||||
|
||||
export function QueryParameterActionsProvider(courier, Private) {
|
||||
export function QueryParameterActionsProvider(indexPatterns, Private) {
|
||||
const filterManager = Private(FilterManagerProvider);
|
||||
|
||||
const setPredecessorCount = (state) => (predecessorCount) => (
|
||||
|
@ -68,7 +68,7 @@ export function QueryParameterActionsProvider(courier, Private) {
|
|||
const addFilter = (state) => async (field, values, operation) => {
|
||||
const indexPatternId = state.queryParameters.indexPatternId;
|
||||
filterManager.add(field, values, operation, indexPatternId);
|
||||
const indexPattern = await courier.indexPatterns.get(indexPatternId);
|
||||
const indexPattern = await indexPatterns.get(indexPatternId);
|
||||
indexPattern.popularizeField(field.name, 1);
|
||||
};
|
||||
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
import _ from 'lodash';
|
||||
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
|
||||
import 'ui/state_management/app_state';
|
||||
import { luceneStringToDsl } from '../../../../ui/public/courier/data_source/build_query/lucene_string_to_dsl';
|
||||
import { migrateFilter } from 'ui/courier/data_source/_migrate_filter';
|
||||
import { luceneStringToDsl, migrateFilter } from 'ui/courier';
|
||||
|
||||
export function dashboardContextProvider(Private, getAppState) {
|
||||
return () => {
|
||||
|
|
|
@ -66,7 +66,7 @@ uiRoutes
|
|||
$scope.initialFilter = ($location.search()).filter || EMPTY_FILTER;
|
||||
},
|
||||
resolve: {
|
||||
dash: function ($route, Private, courier, kbnUrl) {
|
||||
dash: function ($route, Private, redirectWhenMissing, kbnUrl) {
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
const title = $route.current.params.title;
|
||||
if (title) {
|
||||
|
@ -84,7 +84,7 @@ uiRoutes
|
|||
kbnUrl.redirect(`${DashboardConstants.LANDING_PAGE_PATH}?filter="${title}"`);
|
||||
}
|
||||
throw uiRoutes.WAIT_FOR_URL_CHANGE_TOKEN;
|
||||
}).catch(courier.redirectWhenMissing({
|
||||
}).catch(redirectWhenMissing({
|
||||
'dashboard': DashboardConstants.LANDING_PAGE_PATH
|
||||
}));
|
||||
}
|
||||
|
@ -94,9 +94,9 @@ uiRoutes
|
|||
.when(DashboardConstants.CREATE_NEW_DASHBOARD_URL, {
|
||||
template: dashboardTemplate,
|
||||
resolve: {
|
||||
dash: function (savedDashboards, courier) {
|
||||
dash: function (savedDashboards, redirectWhenMissing) {
|
||||
return savedDashboards.get()
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'dashboard': DashboardConstants.LANDING_PAGE_PATH
|
||||
}));
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ uiRoutes
|
|||
.when(createDashboardEditUrl(':id'), {
|
||||
template: dashboardTemplate,
|
||||
resolve: {
|
||||
dash: function (savedDashboards, Notifier, $route, $location, courier, kbnUrl, AppState) {
|
||||
dash: function (savedDashboards, Notifier, $route, $location, redirectWhenMissing, kbnUrl, AppState) {
|
||||
const id = $route.current.params.id;
|
||||
|
||||
return savedDashboards.get(id)
|
||||
|
@ -124,7 +124,7 @@ uiRoutes
|
|||
throw error;
|
||||
}
|
||||
})
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'dashboard': DashboardConstants.LANDING_PAGE_PATH
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -21,14 +21,16 @@ import angular from 'angular';
|
|||
import { uiModules } from 'ui/modules';
|
||||
import { createDashboardEditUrl } from '../dashboard_constants';
|
||||
import { createLegacyClass } from 'ui/utils/legacy_class';
|
||||
import { SavedObjectProvider } from 'ui/courier';
|
||||
|
||||
const module = uiModules.get('app/dashboard');
|
||||
|
||||
// Used only by the savedDashboards service, usually no reason to change this
|
||||
module.factory('SavedDashboard', function (courier, config) {
|
||||
module.factory('SavedDashboard', function (Private, config) {
|
||||
// SavedDashboard constructor. Usually you'd interact with an instance of this.
|
||||
// ID is option, without it one will be generated on save.
|
||||
createLegacyClass(SavedDashboard).inherits(courier.SavedObject);
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
createLegacyClass(SavedDashboard).inherits(SavedObject);
|
||||
function SavedDashboard(id) {
|
||||
// Gives our SavedDashboard the properties of a SavedObject
|
||||
SavedDashboard.Super.call(this, {
|
||||
|
|
|
@ -57,6 +57,7 @@ import '../components/fetch_error';
|
|||
const app = uiModules.get('apps/discover', [
|
||||
'kibana/notify',
|
||||
'kibana/courier',
|
||||
'kibana/url',
|
||||
'kibana/index_patterns'
|
||||
]);
|
||||
|
||||
|
@ -68,7 +69,7 @@ uiRoutes
|
|||
template: indexTemplate,
|
||||
reloadOnSearch: false,
|
||||
resolve: {
|
||||
ip: function (Promise, courier, config, $location, Private) {
|
||||
ip: function (Promise, indexPatterns, config, $location, Private) {
|
||||
const State = Private(StateProvider);
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
|
||||
|
@ -96,13 +97,13 @@ uiRoutes
|
|||
|
||||
return Promise.props({
|
||||
list: savedObjects,
|
||||
loaded: courier.indexPatterns.get(id),
|
||||
loaded: indexPatterns.get(id),
|
||||
stateVal: state.index,
|
||||
stateValFound: specified && exists
|
||||
});
|
||||
});
|
||||
},
|
||||
savedSearch: function (courier, savedSearches, $route) {
|
||||
savedSearch: function (redirectWhenMissing, savedSearches, $route) {
|
||||
const savedSearchId = $route.current.params.id;
|
||||
return savedSearches.get(savedSearchId)
|
||||
.then((savedSearch) => {
|
||||
|
@ -114,7 +115,7 @@ uiRoutes
|
|||
}
|
||||
return savedSearch;
|
||||
})
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'search': '/discover',
|
||||
'index-pattern': '/management/kibana/objects/savedSearches/' + $route.current.params.id
|
||||
}));
|
||||
|
|
|
@ -20,16 +20,18 @@
|
|||
import 'ui/notify';
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { createLegacyClass } from 'ui/utils/legacy_class';
|
||||
import { SavedObjectProvider } from 'ui/courier';
|
||||
|
||||
const module = uiModules.get('discover/saved_searches', [
|
||||
'kibana/notify',
|
||||
'kibana/courier'
|
||||
]);
|
||||
|
||||
module.factory('SavedSearch', function (courier) {
|
||||
createLegacyClass(SavedSearch).inherits(courier.SavedObject);
|
||||
module.factory('SavedSearch', function (Private) {
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
createLegacyClass(SavedSearch).inherits(SavedObject);
|
||||
function SavedSearch(id) {
|
||||
courier.SavedObject.call(this, {
|
||||
SavedObject.call(this, {
|
||||
type: SavedSearch.type,
|
||||
mapping: SavedSearch.mapping,
|
||||
searchSource: SavedSearch.searchSource,
|
||||
|
|
|
@ -35,8 +35,8 @@ const app = uiModules.get('apps/doc', [
|
|||
|
||||
|
||||
const resolveIndexPattern = {
|
||||
indexPattern: function (courier, savedSearches, $route) {
|
||||
return courier.indexPatterns.get($route.current.params.indexPattern);
|
||||
indexPattern: function (indexPatterns, savedSearches, $route) {
|
||||
return indexPatterns.get($route.current.params.indexPattern);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -147,10 +147,10 @@ uiRoutes
|
|||
.when('/management/kibana/indices/:indexPatternId', {
|
||||
template,
|
||||
resolve: {
|
||||
indexPattern: function ($route, courier) {
|
||||
return courier.indexPatterns
|
||||
indexPattern: function ($route, redirectWhenMissing, indexPatterns) {
|
||||
return indexPatterns
|
||||
.get($route.current.params.indexPatternId)
|
||||
.catch(courier.redirectWhenMissing('/management/kibana/index'));
|
||||
.catch(redirectWhenMissing('/management/kibana/index'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -173,7 +173,7 @@ uiRoutes
|
|||
|
||||
uiModules.get('apps/management')
|
||||
.controller('managementIndicesEdit', function (
|
||||
$scope, $location, $route, config, courier, Notifier, Private, AppState, docTitle, confirmModal) {
|
||||
$scope, $location, $route, config, indexPatterns, Notifier, Private, AppState, docTitle, confirmModal) {
|
||||
const notify = new Notifier();
|
||||
const $state = $scope.state = new AppState();
|
||||
const { fieldWildcardMatcher } = Private(FieldWildcardProvider);
|
||||
|
@ -257,7 +257,7 @@ uiModules.get('apps/management')
|
|||
}
|
||||
}
|
||||
|
||||
courier.indexPatterns.delete($scope.indexPattern)
|
||||
indexPatterns.delete($scope.indexPattern)
|
||||
.then(function () {
|
||||
$location.url('/management/kibana/index');
|
||||
})
|
||||
|
|
|
@ -43,9 +43,9 @@ uiRoutes
|
|||
});
|
||||
},
|
||||
resolve: {
|
||||
indexPattern: function ($route, courier) {
|
||||
return courier.indexPatterns.get($route.current.params.indexPatternId)
|
||||
.catch(courier.redirectWhenMissing('/management/kibana/indices'));
|
||||
indexPattern: function ($route, redirectWhenMissing, indexPatterns) {
|
||||
return indexPatterns.get($route.current.params.indexPatternId)
|
||||
.catch(redirectWhenMissing('/management/kibana/indices'));
|
||||
}
|
||||
},
|
||||
controllerAs: 'fieldSettings',
|
||||
|
|
|
@ -46,7 +46,7 @@ uiRoutes
|
|||
.when(VisualizeConstants.CREATE_PATH, {
|
||||
template: editorTemplate,
|
||||
resolve: {
|
||||
savedVis: function (savedVisualizations, courier, $route, Private) {
|
||||
savedVis: function (savedVisualizations, redirectWhenMissing, $route, Private) {
|
||||
const visTypes = Private(VisTypesRegistryProvider);
|
||||
const visType = _.find(visTypes, { name: $route.current.params.type });
|
||||
const shouldHaveIndex = visType.requiresSearch && visType.options.showIndexSelection;
|
||||
|
@ -56,7 +56,7 @@ uiRoutes
|
|||
}
|
||||
|
||||
return savedVisualizations.get($route.current.params)
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'*': '/visualize'
|
||||
}));
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ uiRoutes
|
|||
.when(`${VisualizeConstants.EDIT_PATH}/:id`, {
|
||||
template: editorTemplate,
|
||||
resolve: {
|
||||
savedVis: function (savedVisualizations, courier, $route) {
|
||||
savedVis: function (savedVisualizations, redirectWhenMissing, $route) {
|
||||
return savedVisualizations.get($route.current.params.id)
|
||||
.then((savedVis) => {
|
||||
recentlyAccessed.add(
|
||||
|
@ -74,7 +74,7 @@ uiRoutes
|
|||
savedVis.id);
|
||||
return savedVis;
|
||||
})
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'visualization': '/visualize',
|
||||
'search': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
|
||||
'index-pattern': '/management/kibana/objects/savedVisualizations/' + $route.current.params.id,
|
||||
|
@ -87,7 +87,7 @@ uiRoutes
|
|||
uiModules
|
||||
.get('app/visualize', [
|
||||
'kibana/notify',
|
||||
'kibana/courier'
|
||||
'kibana/url'
|
||||
])
|
||||
.directive('visualizeApp', function () {
|
||||
return {
|
||||
|
@ -97,7 +97,19 @@ uiModules
|
|||
};
|
||||
});
|
||||
|
||||
function VisEditor($scope, $route, AppState, $window, kbnUrl, courier, Private, Promise, config, kbnBaseUrl, localStorage) {
|
||||
function VisEditor(
|
||||
$scope,
|
||||
$route,
|
||||
AppState,
|
||||
$window,
|
||||
kbnUrl,
|
||||
redirectWhenMissing,
|
||||
Private,
|
||||
Promise,
|
||||
config,
|
||||
kbnBaseUrl,
|
||||
localStorage
|
||||
) {
|
||||
const docTitle = Private(DocTitleProvider);
|
||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||
|
||||
|
@ -198,7 +210,7 @@ function VisEditor($scope, $route, AppState, $window, kbnUrl, courier, Private,
|
|||
Promise.try(function () {
|
||||
vis.setState(appState.vis);
|
||||
})
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'index-pattern-field': '/visualize'
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -30,13 +30,14 @@ import { uiModules } from 'ui/modules';
|
|||
import { updateOldState } from 'ui/vis/vis_update_state';
|
||||
import { VisualizeConstants } from '../visualize_constants';
|
||||
import { createLegacyClass } from 'ui/utils/legacy_class';
|
||||
import { SavedObjectProvider } from 'ui/courier';
|
||||
|
||||
uiModules
|
||||
.get('app/visualize')
|
||||
.factory('SavedVis', function (config, $injector, courier, Promise, savedSearches, Private) {
|
||||
.factory('SavedVis', function (config, $injector, Promise, savedSearches, Private) {
|
||||
const Vis = Private(VisProvider);
|
||||
|
||||
createLegacyClass(SavedVis).inherits(courier.SavedObject);
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
createLegacyClass(SavedVis).inherits(SavedObject);
|
||||
function SavedVis(opts) {
|
||||
const self = this;
|
||||
opts = opts || {};
|
||||
|
|
|
@ -61,7 +61,7 @@ require('ui/routes')
|
|||
template: require('plugins/timelion/index.html'),
|
||||
reloadOnSearch: false,
|
||||
resolve: {
|
||||
savedSheet: function (courier, savedSheets, $route) {
|
||||
savedSheet: function (redirectWhenMissing, savedSheets, $route) {
|
||||
return savedSheets.get($route.current.params.id)
|
||||
.then((savedSheet) => {
|
||||
if ($route.current.params.id) {
|
||||
|
@ -72,7 +72,7 @@ require('ui/routes')
|
|||
}
|
||||
return savedSheet;
|
||||
})
|
||||
.catch(courier.redirectWhenMissing({
|
||||
.catch(redirectWhenMissing({
|
||||
'search': '/'
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -19,17 +19,19 @@
|
|||
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { createLegacyClass } from 'ui/utils/legacy_class';
|
||||
import { SavedObjectProvider } from 'ui/courier';
|
||||
const module = uiModules.get('app/timelion');
|
||||
|
||||
// Used only by the savedSheets service, usually no reason to change this
|
||||
module.factory('SavedSheet', function (courier, config) {
|
||||
module.factory('SavedSheet', function (Private, config) {
|
||||
|
||||
// SavedSheet constructor. Usually you'd interact with an instance of this.
|
||||
// ID is option, without it one will be generated on save.
|
||||
createLegacyClass(SavedSheet).inherits(courier.SavedObject);
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
createLegacyClass(SavedSheet).inherits(SavedObject);
|
||||
function SavedSheet(id) {
|
||||
// Gives our SavedSheet the properties of a SavedObject
|
||||
courier.SavedObject.call(this, {
|
||||
SavedObject.call(this, {
|
||||
type: SavedSheet.type,
|
||||
mapping: SavedSheet.mapping,
|
||||
|
||||
|
|
|
@ -25,10 +25,7 @@ export default function (Private, Promise) {
|
|||
const getIndexPatternStub = sinon.stub()
|
||||
.returns(Promise.resolve(indexPatterns));
|
||||
|
||||
const courier = {
|
||||
indexPatterns: { get: getIndexPatternStub },
|
||||
getStub: getIndexPatternStub
|
||||
return {
|
||||
get: getIndexPatternStub,
|
||||
};
|
||||
|
||||
return courier;
|
||||
}
|
|
@ -21,7 +21,7 @@ import _ from 'lodash';
|
|||
import { AggConfig } from '../../vis/agg_config';
|
||||
import { buildExistsFilter } from '../../filter_manager/lib/exists';
|
||||
import { buildPhrasesFilter } from '../../filter_manager/lib/phrases';
|
||||
import { buildQueryFromFilters } from '../../courier/data_source/build_query/from_filters';
|
||||
import { buildQueryFromFilters } from '../../courier';
|
||||
|
||||
/**
|
||||
* walks the aggregation DSL and returns DSL starting at aggregation with id of startFromAggId
|
||||
|
|
|
@ -19,11 +19,10 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import angular from 'angular';
|
||||
import { luceneStringToDsl } from '../../courier/data_source/build_query/lucene_string_to_dsl.js';
|
||||
|
||||
import { BucketAggType } from './_bucket_agg_type';
|
||||
import { createFilterFilters } from './create_filter/filters';
|
||||
import { decorateQuery } from '../../courier/data_source/_decorate_query';
|
||||
import { decorateQuery, luceneStringToDsl } from '../../courier';
|
||||
import filtersTemplate from '../controls/filters.html';
|
||||
|
||||
export const filtersBucketAgg = new BucketAggType({
|
||||
|
|
|
@ -19,93 +19,41 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
|
||||
import '../es';
|
||||
import '../promises';
|
||||
import '../index_patterns';
|
||||
import { uiModules } from '../modules';
|
||||
import { addFatalErrorCallback } from '../notify';
|
||||
import '../promises';
|
||||
|
||||
import { SearchSourceProvider } from './data_source/search_source';
|
||||
import { requestQueue } from './_request_queue';
|
||||
import { FetchSoonProvider } from './fetch';
|
||||
import { SearchLooperProvider } from './looper/search';
|
||||
import { SavedObjectProvider } from './saved_object';
|
||||
import { RedirectWhenMissingProvider } from './_redirect_when_missing';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
import { SearchLooperProvider } from './search_looper';
|
||||
|
||||
uiModules.get('kibana/courier').service('courier', ($rootScope, Private) => {
|
||||
const fetchSoon = Private(FetchSoonProvider);
|
||||
|
||||
uiModules.get('kibana/courier')
|
||||
.service('courier', function ($rootScope, Private, indexPatterns) {
|
||||
function Courier() {
|
||||
const self = this;
|
||||
const SearchSource = Private(SearchSourceProvider);
|
||||
const fetchSoon = Private(FetchSoonProvider);
|
||||
const searchLooper = self.searchLooper = Private(SearchLooperProvider);
|
||||
// This manages the doc fetch interval.
|
||||
const searchLooper = Private(SearchLooperProvider);
|
||||
|
||||
self.SavedObject = Private(SavedObjectProvider);
|
||||
self.indexPatterns = indexPatterns;
|
||||
self.redirectWhenMissing = Private(RedirectWhenMissingProvider);
|
||||
class Courier {
|
||||
constructor() {
|
||||
// Listen for refreshInterval changes
|
||||
$rootScope.$listen(timefilter, 'refreshIntervalUpdate', function () {
|
||||
const refreshValue = _.get(timefilter.getRefreshInterval(), 'value');
|
||||
const refreshPause = _.get(timefilter.getRefreshInterval(), 'pause');
|
||||
|
||||
self.SearchSource = SearchSource;
|
||||
// Update the time between automatic search requests.
|
||||
if (_.isNumber(refreshValue) && !refreshPause) {
|
||||
searchLooper.setIntervalInMs(refreshValue);
|
||||
} else {
|
||||
searchLooper.setIntervalInMs(0);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* update the time between automatic search requests
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
self.fetchInterval = function (ms) {
|
||||
searchLooper.ms(ms);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Start fetching search requests on an interval
|
||||
* @chainable
|
||||
*/
|
||||
self.start = function () {
|
||||
searchLooper.start();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Process the pending request queue right now, returns
|
||||
* a promise that resembles the success of the fetch completing,
|
||||
* individual errors are routed to their respective requests.
|
||||
*/
|
||||
self.fetch = function () {
|
||||
fetchSoon.fetchQueued().then(function () {
|
||||
searchLooper.restart();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* is the courier currently fetching search
|
||||
* results automatically?
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.started = function () {
|
||||
return searchLooper.started();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* stop the courier from fetching more search
|
||||
* results, does not stop validating docs.
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
self.stop = function () {
|
||||
searchLooper.stop();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abort all pending requests
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
self.close = function () {
|
||||
// Abort all pending requests if there's a fatal error.
|
||||
const closeOnFatal = _.once(() => {
|
||||
searchLooper.stop();
|
||||
|
||||
_.invoke(requestQueue, 'abort');
|
||||
|
@ -113,21 +61,22 @@ uiModules.get('kibana/courier')
|
|||
if (requestQueue.length) {
|
||||
throw new Error('Aborting all pending requests failed.');
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$listen(timefilter, 'refreshIntervalUpdate', function () {
|
||||
const refreshValue = _.get(timefilter.getRefreshInterval(), 'value');
|
||||
const refreshPause = _.get(timefilter.getRefreshInterval(), 'pause');
|
||||
if (_.isNumber(refreshValue) && !refreshPause) {
|
||||
self.fetchInterval(refreshValue);
|
||||
} else {
|
||||
self.fetchInterval(0);
|
||||
}
|
||||
});
|
||||
|
||||
const closeOnFatal = _.once(self.close);
|
||||
addFatalErrorCallback(closeOnFatal);
|
||||
}
|
||||
|
||||
return new Courier();
|
||||
});
|
||||
/**
|
||||
* Process the pending request queue right now, returns
|
||||
* a promise that resembles the success of the fetch completing,
|
||||
* individual errors are routed to their respective requests.
|
||||
*/
|
||||
fetch = () => {
|
||||
fetchSoon.fetchQueued().then(() => {
|
||||
searchLooper.restart();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return new Courier();
|
||||
});
|
||||
|
|
|
@ -23,13 +23,13 @@ import { ErrorAllowExplicitIndexProvider } from '../../error_allow_explicit_inde
|
|||
import { IsRequestProvider } from './is_request';
|
||||
import { MergeDuplicatesRequestProvider } from './merge_duplicate_requests';
|
||||
import { RequestStatus } from './req_status';
|
||||
import { RequestFetchParamsToBodyProvider } from './request/request_fetch_params_to_body_provider';
|
||||
import { SerializeFetchParamsProvider } from './request/serialize_fetch_params';
|
||||
|
||||
export function CallClientProvider(Private, Promise, es) {
|
||||
const errorAllowExplicitIndex = Private(ErrorAllowExplicitIndexProvider);
|
||||
const isRequest = Private(IsRequestProvider);
|
||||
const mergeDuplicateRequests = Private(MergeDuplicatesRequestProvider);
|
||||
const requestFetchParamsToBody = Private(RequestFetchParamsToBodyProvider);
|
||||
const serializeFetchParams = Private(SerializeFetchParamsProvider);
|
||||
|
||||
const ABORTED = RequestStatus.ABORTED;
|
||||
const DUPLICATE = RequestStatus.DUPLICATE;
|
||||
|
@ -45,7 +45,8 @@ export function CallClientProvider(Private, Promise, es) {
|
|||
if (!execCount) return Promise.resolve([]);
|
||||
|
||||
// resolved by respond()
|
||||
let esPromise;
|
||||
let esPromise = undefined;
|
||||
let isRequestAborted = false;
|
||||
const defer = Promise.defer();
|
||||
|
||||
// for each respond with either the response or ABORTED
|
||||
|
@ -72,7 +73,6 @@ export function CallClientProvider(Private, Promise, es) {
|
|||
);
|
||||
};
|
||||
|
||||
|
||||
// handle a request being aborted while being fetched
|
||||
const requestWasAborted = Promise.method(function (req, i) {
|
||||
if (statuses[i] === ABORTED) {
|
||||
|
@ -89,12 +89,12 @@ export function CallClientProvider(Private, Promise, es) {
|
|||
esPromise.abort();
|
||||
}
|
||||
|
||||
esPromise = ABORTED;
|
||||
esPromise = undefined;
|
||||
isRequestAborted = true;
|
||||
|
||||
return respond();
|
||||
});
|
||||
|
||||
|
||||
// attach abort handlers, close over request index
|
||||
statuses.forEach(function (req, i) {
|
||||
if (!isRequest(req)) return;
|
||||
|
@ -103,63 +103,81 @@ export function CallClientProvider(Private, Promise, es) {
|
|||
});
|
||||
});
|
||||
|
||||
// Now that all of THAT^^^ is out of the way, lets actually
|
||||
// call out to elasticsearch
|
||||
Promise.map(requestsToFetch, function (request) {
|
||||
return Promise.try(request.getFetchParams, void 0, request)
|
||||
.then(function (fetchParams) {
|
||||
return (request.fetchParams = fetchParams);
|
||||
})
|
||||
.then(value => ({ resolved: value }))
|
||||
.catch(error => ({ rejected: error }));
|
||||
})
|
||||
.then(function (results) {
|
||||
const requestsWithFetchParams = [];
|
||||
// Gather the fetch param responses from all the successful requests.
|
||||
results.forEach((result, index) => {
|
||||
if (result.resolved) {
|
||||
requestsWithFetchParams.push(result.resolved);
|
||||
} else {
|
||||
const request = requestsToFetch[index];
|
||||
request.handleFailure(result.rejected);
|
||||
requestsToFetch[index] = undefined;
|
||||
}
|
||||
});
|
||||
// The index of the request inside requestsToFetch determines which response is mapped to it. If a request
|
||||
// won't generate a response, since it already failed, we need to remove the request
|
||||
// from the requestsToFetch array so the indexes will continue to match up to the responses correctly.
|
||||
requestsToFetch = requestsToFetch.filter(request => request !== undefined);
|
||||
return requestFetchParamsToBody(requestsWithFetchParams);
|
||||
})
|
||||
.then(function (body) {
|
||||
// while the strategy was converting, our request was aborted
|
||||
if (esPromise === ABORTED) {
|
||||
// We're going to create a new async context here, so that the logic within it can execute
|
||||
// asynchronously after we've returned a reference to defer.promise.
|
||||
Promise.resolve().then(async () => {
|
||||
// Flatten the searchSource within each searchRequest to get the fetch params,
|
||||
// e.g. body, filters, index pattern, query.
|
||||
const allFetchParams = await getAllFetchParams(requestsToFetch);
|
||||
|
||||
// Serialize the fetch params into a format suitable for the body of an ES query.
|
||||
const serializedFetchParams = await serializeAllFetchParams(allFetchParams, requestsToFetch);
|
||||
|
||||
// The index of the request inside requestsToFetch determines which response is mapped to it.
|
||||
// If a request won't generate a response, since it already failed, we need to remove the
|
||||
// request from the requestsToFetch array so the indexes will continue to match up to the
|
||||
// responses correctly.
|
||||
requestsToFetch = requestsToFetch.filter(request => request !== undefined);
|
||||
|
||||
try {
|
||||
// The request was aborted while we were doing the above logic.
|
||||
if (isRequestAborted) {
|
||||
throw ABORTED;
|
||||
}
|
||||
|
||||
return (esPromise = es.msearch({ body }));
|
||||
})
|
||||
.then((clientResponse => respond(clientResponse.responses)))
|
||||
.catch(function (error) {
|
||||
esPromise = es.msearch({ body: serializedFetchParams });
|
||||
const clientResponse = await esPromise;
|
||||
await respond(clientResponse.responses);
|
||||
} catch(error) {
|
||||
if (error === ABORTED) {
|
||||
return await respond();
|
||||
}
|
||||
|
||||
if (errorAllowExplicitIndex.test(error)) {
|
||||
return errorAllowExplicitIndex.takeover();
|
||||
}
|
||||
|
||||
if (error === ABORTED) respond();
|
||||
else defer.reject(error);
|
||||
});
|
||||
defer.reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
// return our promise, but catch any errors we create and
|
||||
// send them to the requests
|
||||
return defer.promise
|
||||
.catch(function (err) {
|
||||
requests.forEach(function (req, i) {
|
||||
if (statuses[i] !== ABORTED) {
|
||||
.catch((err) => {
|
||||
requests.forEach((req, index) => {
|
||||
if (statuses[index] !== ABORTED) {
|
||||
req.handleFailure(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getAllFetchParams(requests) {
|
||||
return Promise.map(requests, (request) => {
|
||||
return Promise.try(request.getFetchParams, void 0, request)
|
||||
.then((fetchParams) => {
|
||||
return (request.fetchParams = fetchParams);
|
||||
})
|
||||
.then(value => ({ resolved: value }))
|
||||
.catch(error => ({ rejected: error }));
|
||||
});
|
||||
}
|
||||
|
||||
function serializeAllFetchParams(fetchParams, requestsToFetch) {
|
||||
const requestsWithFetchParams = [];
|
||||
|
||||
// Gather the fetch param responses from all the successful requests.
|
||||
fetchParams.forEach((result, index) => {
|
||||
if (result.resolved) {
|
||||
requestsWithFetchParams.push(result.resolved);
|
||||
} else {
|
||||
const request = requestsToFetch[index];
|
||||
request.handleFailure(result.rejected);
|
||||
requestsToFetch[index] = undefined;
|
||||
}
|
||||
});
|
||||
return serializeFetchParams(requestsWithFetchParams);
|
||||
}
|
||||
|
||||
return callClient;
|
||||
|
|
|
@ -47,13 +47,13 @@ export function FetchSoonProvider(Private, Promise) {
|
|||
* @param {array} requests - the requests to fetch
|
||||
* @async
|
||||
*/
|
||||
this.these = (requests) => {
|
||||
this.fetchSearchRequests = (requests) => {
|
||||
requests.forEach(req => req._setFetchRequested());
|
||||
debouncedFetchNow();
|
||||
return Promise.all(requests.map(req => req.getCompletePromise()));
|
||||
};
|
||||
|
||||
this.fetchQueued = () => {
|
||||
return this.these(requestQueue.getStartable());
|
||||
return this.fetchSearchRequests(requestQueue.getStartable());
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import sinon from 'sinon';
|
|||
import expect from 'expect.js';
|
||||
|
||||
import { SearchRequestProvider } from '../search_request';
|
||||
import { requestQueue } from '../../../_request_queue';
|
||||
import { requestQueue } from '../../../../_request_queue';
|
||||
|
||||
describe('ui/courier/fetch search request', () => {
|
||||
beforeEach(ngMock.module('kibana'));
|
20
src/ui/public/courier/fetch/request/search_request/index.js
Normal file
20
src/ui/public/courier/fetch/request/search_request/index.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { SearchRequestProvider } from './search_request';
|
|
@ -20,7 +20,7 @@
|
|||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
import { requestQueue } from '../../_request_queue';
|
||||
import { requestQueue } from '../../../_request_queue';
|
||||
|
||||
export function SearchRequestProvider(Promise) {
|
||||
class SearchRequest {
|
|
@ -23,11 +23,11 @@ import ngMock from 'ng_mock';
|
|||
|
||||
import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
|
||||
|
||||
import { SegmentedRequestProvider } from '../segmented';
|
||||
import { SegmentedSearchRequestProvider } from '../segmented_search_request';
|
||||
|
||||
describe('ui/courier/fetch/request/segmented/_createQueue', () => {
|
||||
describe('SegmentedSearchRequest _createQueue', () => {
|
||||
let Promise;
|
||||
let SegmentedReq;
|
||||
let SegmentedSearchRequest;
|
||||
let MockSource;
|
||||
|
||||
require('test_utils/no_digest_promises').activateForSuite();
|
||||
|
@ -35,7 +35,7 @@ describe('ui/courier/fetch/request/segmented/_createQueue', () => {
|
|||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject((Private, $injector) => {
|
||||
Promise = $injector.get('Promise');
|
||||
SegmentedReq = Private(SegmentedRequestProvider);
|
||||
SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
|
||||
|
||||
MockSource = class {
|
||||
constructor() {
|
||||
|
@ -45,7 +45,7 @@ describe('ui/courier/fetch/request/segmented/_createQueue', () => {
|
|||
}));
|
||||
|
||||
it('manages the req._queueCreated flag', async function () {
|
||||
const req = new SegmentedReq({ source: new MockSource(), errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
|
||||
req._queueCreated = null;
|
||||
|
||||
const promise = req._createQueue();
|
||||
|
@ -60,7 +60,7 @@ describe('ui/courier/fetch/request/segmented/_createQueue', () => {
|
|||
const indices = [1, 2, 3];
|
||||
sinon.stub(ip, 'toDetailedIndexList').returns(Promise.resolve(indices));
|
||||
|
||||
const req = new SegmentedReq({ source, errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source, errorHandler: () => {} });
|
||||
const output = await req._createQueue();
|
||||
expect(output).to.equal(indices);
|
||||
});
|
||||
|
@ -68,7 +68,7 @@ describe('ui/courier/fetch/request/segmented/_createQueue', () => {
|
|||
it('tells the index pattern its direction', async function () {
|
||||
const source = new MockSource();
|
||||
const ip = source.get('index');
|
||||
const req = new SegmentedReq({ source, errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source, errorHandler: () => {} });
|
||||
sinon.stub(ip, 'toDetailedIndexList').returns(Promise.resolve([1, 2, 3]));
|
||||
|
||||
req.setDirection('asc');
|
|
@ -26,11 +26,11 @@ import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn';
|
|||
import NoDigestPromises from 'test_utils/no_digest_promises';
|
||||
import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
|
||||
|
||||
import { SegmentedRequestProvider } from '../segmented';
|
||||
import { SegmentedSearchRequestProvider } from '../segmented_search_request';
|
||||
|
||||
describe('Segmented Request Index Selection', function () {
|
||||
describe('SegmentedSearchRequest index selection', function () {
|
||||
let Promise;
|
||||
let SegmentedReq;
|
||||
let SegmentedSearchRequest;
|
||||
let MockSource;
|
||||
let HitSortFn;
|
||||
|
||||
|
@ -40,7 +40,7 @@ describe('Segmented Request Index Selection', function () {
|
|||
beforeEach(ngMock.inject((Private, $injector) => {
|
||||
Promise = $injector.get('Promise');
|
||||
HitSortFn = Private(HitSortFnProv);
|
||||
SegmentedReq = Private(SegmentedRequestProvider);
|
||||
SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
|
||||
|
||||
MockSource = class {
|
||||
constructor() {
|
||||
|
@ -60,7 +60,7 @@ describe('Segmented Request Index Selection', function () {
|
|||
{ index: 'five', min: 0, max: 1 },
|
||||
]));
|
||||
|
||||
const req = new SegmentedReq({ source: search, errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source: search, errorHandler: () => {} });
|
||||
req._handle.setDirection('desc');
|
||||
req._handle.setSortFn(new HitSortFn('desc'));
|
||||
req._handle.setSize(500);
|
||||
|
@ -111,7 +111,7 @@ describe('Segmented Request Index Selection', function () {
|
|||
{ index: 'five', min: 5, max: 50 },
|
||||
]));
|
||||
|
||||
const req = new SegmentedReq({ source: search, errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source: search, errorHandler: () => {} });
|
||||
req._handle.setDirection('desc');
|
||||
req._handle.setSortFn(new HitSortFn('desc'));
|
||||
req._handle.setSize(10);
|
|
@ -21,12 +21,12 @@ import sinon from 'sinon';
|
|||
import expect from 'expect.js';
|
||||
import ngMock from 'ng_mock';
|
||||
|
||||
import { SegmentedRequestProvider } from '../segmented';
|
||||
import { SearchRequestProvider } from '../search_request';
|
||||
import { SegmentedSearchRequestProvider } from '../segmented_search_request';
|
||||
import { SearchRequestProvider } from '../../search_request';
|
||||
|
||||
describe('SegmentedRequestProvider', () => {
|
||||
describe('SegmentedSearchRequest', () => {
|
||||
let Promise;
|
||||
let SegmentedReq;
|
||||
let SegmentedSearchRequest;
|
||||
let segmentedReq;
|
||||
let abstractReqStart;
|
||||
|
||||
|
@ -34,7 +34,7 @@ describe('SegmentedRequestProvider', () => {
|
|||
|
||||
beforeEach(ngMock.inject((Private, $injector) => {
|
||||
Promise = $injector.get('Promise');
|
||||
SegmentedReq = Private(SegmentedRequestProvider);
|
||||
SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
|
||||
|
||||
const SearchRequest = Private(SearchRequestProvider);
|
||||
abstractReqStart = sinon.stub(SearchRequest.prototype, 'start').callsFake(() => {
|
||||
|
@ -67,7 +67,7 @@ describe('SegmentedRequestProvider', () => {
|
|||
});
|
||||
|
||||
function init() {
|
||||
segmentedReq = new SegmentedReq({ source: mockSource(), errorHandler: () => {} });
|
||||
segmentedReq = new SegmentedSearchRequest({ source: mockSource(), errorHandler: () => {} });
|
||||
}
|
||||
|
||||
function mockSource() {
|
|
@ -24,10 +24,10 @@ import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn';
|
|||
import NoDigestPromises from 'test_utils/no_digest_promises';
|
||||
import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source';
|
||||
|
||||
import { SegmentedRequestProvider } from '../segmented';
|
||||
import { SegmentedSearchRequestProvider } from '../segmented_search_request';
|
||||
|
||||
describe('Segmented Request Size Picking', function () {
|
||||
let SegmentedReq;
|
||||
describe('SegmentedSearchRequest size picking', function () {
|
||||
let SegmentedSearchRequest;
|
||||
let MockSource;
|
||||
let HitSortFn;
|
||||
|
||||
|
@ -36,7 +36,7 @@ describe('Segmented Request Size Picking', function () {
|
|||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject((Private, $injector) => {
|
||||
HitSortFn = Private(HitSortFnProv);
|
||||
SegmentedReq = Private(SegmentedRequestProvider);
|
||||
SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
|
||||
|
||||
MockSource = class {
|
||||
constructor() {
|
||||
|
@ -47,7 +47,7 @@ describe('Segmented Request Size Picking', function () {
|
|||
|
||||
describe('without a size', function () {
|
||||
it('does not set the request size', async function () {
|
||||
const req = new SegmentedReq({ source: new MockSource(), errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
|
||||
req._handle.setDirection('desc');
|
||||
req._handle.setSortFn(new HitSortFn('desc'));
|
||||
await req.start();
|
||||
|
@ -58,7 +58,7 @@ describe('Segmented Request Size Picking', function () {
|
|||
|
||||
describe('with a size', function () {
|
||||
it('sets the request size to the entire desired size', async function () {
|
||||
const req = new SegmentedReq({ source: new MockSource(), errorHandler: () => {} });
|
||||
const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} });
|
||||
req._handle.setDirection('desc');
|
||||
req._handle.setSize(555);
|
||||
req._handle.setSortFn(new HitSortFn('desc'));
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { SegmentedSearchRequestProvider } from './segmented_search_request';
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { EventsProvider } from '../../../events';
|
||||
import { EventsProvider } from '../../../../events';
|
||||
|
||||
export function SegmentedHandleProvider(Private) {
|
||||
const Events = Private(EventsProvider);
|
||||
|
@ -26,13 +26,13 @@ export function SegmentedHandleProvider(Private) {
|
|||
|
||||
/**
|
||||
* Simple class for creating an object to send to the
|
||||
* requester of a SegmentedRequest. Since the SegmentedRequest
|
||||
* requester of a SegmentedSearchRequest. Since the SegmentedSearchRequest
|
||||
* extends AbstractRequest, it wasn't able to be the event
|
||||
* emitter it was born to be. This provides a channel for
|
||||
* setting values on the segmented request, and an event
|
||||
* emitter for the request to speak outwardly
|
||||
*
|
||||
* @param {SegmentedRequest} - req - the request this handle relates to
|
||||
* @param {SegmentedSearchRequest} - req - the request this handle relates to
|
||||
*/
|
||||
return class SegmentedHandle extends Events {
|
||||
constructor(req) {
|
|
@ -18,13 +18,13 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { Notifier } from '../../../notify';
|
||||
import { SearchRequestProvider } from './search_request';
|
||||
import { SegmentedHandleProvider } from './segmented_handle';
|
||||
import { pushAll } from '../../../utils/collection';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
import { SearchRequestProvider } from '../search_request';
|
||||
import { SegmentedHandleProvider } from './segmented_handle';
|
||||
import { Notifier } from '../../../../notify';
|
||||
import { pushAll } from '../../../../utils/collection';
|
||||
|
||||
export function SegmentedRequestProvider(Private, config) {
|
||||
export function SegmentedSearchRequestProvider(Private, config) {
|
||||
const SearchRequest = Private(SearchRequestProvider);
|
||||
const SegmentedHandle = Private(SegmentedHandleProvider);
|
||||
|
||||
|
@ -32,7 +32,7 @@ export function SegmentedRequestProvider(Private, config) {
|
|||
location: 'Segmented Fetch'
|
||||
});
|
||||
|
||||
class SegmentedReq extends SearchRequest {
|
||||
class SegmentedSearchRequest extends SearchRequest {
|
||||
constructor({ source, defer, errorHandler, initFn }) {
|
||||
super({ source, defer, errorHandler });
|
||||
|
||||
|
@ -136,7 +136,7 @@ export function SegmentedRequestProvider(Private, config) {
|
|||
}
|
||||
|
||||
clone() {
|
||||
return new SegmentedReq(this.source, this.defer, this._initFn);
|
||||
return new SegmentedSearchRequest(this.source, this.defer, this._initFn);
|
||||
}
|
||||
|
||||
complete() {
|
||||
|
@ -146,7 +146,7 @@ export function SegmentedRequestProvider(Private, config) {
|
|||
}
|
||||
|
||||
/*********
|
||||
** SegmentedReq specific methods
|
||||
** SegmentedSearchRequest specific methods
|
||||
*********/
|
||||
|
||||
|
||||
|
@ -349,7 +349,7 @@ export function SegmentedRequestProvider(Private, config) {
|
|||
}
|
||||
}
|
||||
|
||||
SegmentedReq.prototype.mergedSegment = notify.timed('merge response segment', SegmentedReq.prototype.mergedSegment);
|
||||
SegmentedSearchRequest.prototype.mergedSegment = notify.timed('merge response segment', SegmentedSearchRequest.prototype.mergedSegment);
|
||||
|
||||
return SegmentedReq;
|
||||
return SegmentedSearchRequest;
|
||||
}
|
|
@ -22,17 +22,17 @@ import expect from 'expect.js';
|
|||
|
||||
import StubIndexPatternProvider from 'test_utils/stub_index_pattern';
|
||||
|
||||
import { RequestFetchParamsToBodyProvider } from '../request_fetch_params_to_body_provider';
|
||||
import { SerializeFetchParamsProvider } from '../serialize_fetch_params_provider';
|
||||
|
||||
describe('RequestFetchParamsToBodyProvider', () => {
|
||||
let requestFetchParamsToBody;
|
||||
describe('SerializeFetchParamsProvider', () => {
|
||||
let serializeFetchParams;
|
||||
let IndexPattern;
|
||||
|
||||
require('test_utils/no_digest_promises').activateForSuite();
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
beforeEach(ngMock.inject((Private) => {
|
||||
requestFetchParamsToBody = Private(RequestFetchParamsToBodyProvider);
|
||||
serializeFetchParams = Private(SerializeFetchParamsProvider);
|
||||
IndexPattern = Private(StubIndexPatternProvider);
|
||||
}));
|
||||
|
||||
|
@ -60,7 +60,7 @@ describe('RequestFetchParamsToBodyProvider', () => {
|
|||
body: { foo: 'saturn' }
|
||||
}
|
||||
];
|
||||
return requestFetchParamsToBody(reqsFetchParams).then(value => {
|
||||
return serializeFetchParams(reqsFetchParams).then(value => {
|
||||
const indexLineMatch = value.match(/"index":\[".kibana"\]/g);
|
||||
expect(indexLineMatch).to.not.be(null);
|
||||
expect(indexLineMatch.length).to.be(2);
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { SerializeFetchParamsProvider } from './serialize_fetch_params_provider';
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { toJson } from '../../../../../core_plugins/kibana/common/utils/aggressive_parse';
|
||||
import { toJson } from '../../../../../../core_plugins/kibana/common/utils/aggressive_parse';
|
||||
|
||||
function emptySearch() {
|
||||
return {
|
||||
|
@ -44,7 +44,7 @@ function emptySearch() {
|
|||
* @param sessionId
|
||||
* @return {Promise.<string>}
|
||||
*/
|
||||
export function requestFetchParamsToBody(
|
||||
export function serializeFetchParams(
|
||||
requestsFetchParams,
|
||||
Promise,
|
||||
timeFilter,
|
|
@ -17,12 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { requestFetchParamsToBody } from './request_fetch_params_to_body';
|
||||
import { serializeFetchParams } from './serialize_fetch_params';
|
||||
import _ from 'lodash';
|
||||
|
||||
const DEFAULT_SESSION_ID = '1';
|
||||
|
||||
function requestFetchParamsToBodyWithDefaults(paramOverrides) {
|
||||
function serializeFetchParamsWithDefaults(paramOverrides) {
|
||||
const paramDefaults = {
|
||||
requestFetchParams: [],
|
||||
Promise,
|
||||
|
@ -39,7 +39,7 @@ function requestFetchParamsToBodyWithDefaults(paramOverrides) {
|
|||
};
|
||||
const params = { ...paramDefaults, ...paramOverrides };
|
||||
|
||||
return requestFetchParamsToBody(
|
||||
return serializeFetchParams(
|
||||
params.requestFetchParams,
|
||||
Promise,
|
||||
params.timeFilter,
|
||||
|
@ -58,7 +58,7 @@ test('filters out any body properties that begin with $', () => {
|
|||
body: { foo: 'bar', $foo: 'bar' }
|
||||
}
|
||||
];
|
||||
return requestFetchParamsToBodyWithDefaults({ requestFetchParams }).then(value => {
|
||||
return serializeFetchParamsWithDefaults({ requestFetchParams }).then(value => {
|
||||
expect(_.includes(value, 'foo')).toBe(true);
|
||||
expect(_.includes(value, '$foo')).toBe(false);
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ describe('when indexList is not empty', () => {
|
|||
body: { foo: 'bar', $foo: 'bar' }
|
||||
}
|
||||
];
|
||||
return requestFetchParamsToBodyWithDefaults({ requestFetchParams }).then(value => {
|
||||
return serializeFetchParamsWithDefaults({ requestFetchParams }).then(value => {
|
||||
expect(_.includes(value, '"index":["logstash-123"]')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -101,7 +101,7 @@ describe('when indexList is empty', () => {
|
|||
];
|
||||
|
||||
test('queries the kibana index (.kibana) with a must_not match_all boolean', () => {
|
||||
return requestFetchParamsToBodyWithDefaults({ requestFetchParams }).then(value => {
|
||||
return serializeFetchParamsWithDefaults({ requestFetchParams }).then(value => {
|
||||
expect(_.includes(value, '"index":[".kibana"]')).toBe(true);
|
||||
expect(_.includes(value, emptyMustNotQuery)).toBe(true);
|
||||
});
|
||||
|
@ -120,7 +120,7 @@ describe('headers', () => {
|
|||
];
|
||||
|
||||
const getHeader = async (paramOverrides) => {
|
||||
const request = await requestFetchParamsToBodyWithDefaults(paramOverrides);
|
||||
const request = await serializeFetchParamsWithDefaults(paramOverrides);
|
||||
const requestParts = request.split('\n');
|
||||
if (requestParts.length < 2) {
|
||||
throw new Error('fetch Body does not contain expected format header newline body.');
|
|
@ -17,13 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { requestFetchParamsToBody } from './request_fetch_params_to_body';
|
||||
import { serializeFetchParams } from './serialize_fetch_params';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
|
||||
export function RequestFetchParamsToBodyProvider(Promise, kbnIndex, sessionId, config, esShardTimeout) {
|
||||
return (requestsFetchParams) => (
|
||||
requestFetchParamsToBody(
|
||||
requestsFetchParams,
|
||||
export function SerializeFetchParamsProvider(Promise, kbnIndex, sessionId, config, esShardTimeout) {
|
||||
return (fetchParams) => (
|
||||
serializeFetchParams(
|
||||
fetchParams,
|
||||
Promise,
|
||||
timefilter,
|
||||
kbnIndex,
|
|
@ -18,3 +18,11 @@
|
|||
*/
|
||||
|
||||
import './courier';
|
||||
export { SavedObjectProvider } from './saved_object';
|
||||
export {
|
||||
SearchSourceProvider,
|
||||
migrateFilter,
|
||||
decorateQuery,
|
||||
buildQueryFromFilters,
|
||||
luceneStringToDsl,
|
||||
} from './search_source';
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import '../../promises';
|
||||
import { fatalError } from '../../notify';
|
||||
|
||||
export function LooperProvider($timeout, Promise) {
|
||||
function Looper(ms, fn) {
|
||||
this._fn = fn;
|
||||
this._ms = ms === void 0 ? 1500 : ms;
|
||||
this._timer = null;
|
||||
this._started = false;
|
||||
|
||||
this._loopTheLoop = _.bind(this._loopTheLoop, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of milliseconds between
|
||||
* each loop
|
||||
*
|
||||
* @param {integer} ms
|
||||
* @chainable
|
||||
*/
|
||||
Looper.prototype.ms = function (ms) {
|
||||
this._ms = _.parseInt(ms) || 0;
|
||||
|
||||
if (!this._started) return;
|
||||
|
||||
if (this._ms) {
|
||||
this.start(false);
|
||||
} else {
|
||||
this._unScheduleLoop();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels the current looper while keeping internal
|
||||
* state as started
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
Looper.prototype.pause = function () {
|
||||
this._unScheduleLoop();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Start the looping madness
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
Looper.prototype.start = function (loopOver) {
|
||||
if (loopOver == null) loopOver = true;
|
||||
|
||||
if (!this._started) {
|
||||
this._started = true;
|
||||
} else {
|
||||
this._unScheduleLoop();
|
||||
}
|
||||
|
||||
if (loopOver) {
|
||||
this._loopTheLoop();
|
||||
} else {
|
||||
this._scheduleLoop();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
Looper.prototype.stop = function () {
|
||||
this._unScheduleLoop();
|
||||
this._started = false;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Restart the looper only if it is already started.
|
||||
* Called automatically when ms is changed
|
||||
*
|
||||
* @chainable
|
||||
*/
|
||||
Looper.prototype.restart = function () {
|
||||
this.start(false);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the looper currently started/running/scheduled/going to execute
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
Looper.prototype.started = function () {
|
||||
return !!this._started;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current loop interval
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
Looper.prototype.loopInterval = function () {
|
||||
return this._ms;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the loop is executed before the previous
|
||||
* run has completed.
|
||||
*
|
||||
* @override
|
||||
* @return {undefined}
|
||||
*/
|
||||
Looper.prototype.onHastyLoop = function () {
|
||||
// override this in subclasses
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps this._fn so that this._fn can be changed
|
||||
* without rescheduling and schedules
|
||||
* the next iteration
|
||||
*
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
Looper.prototype._loopTheLoop = function () {
|
||||
const self = this;
|
||||
|
||||
if (self.active) {
|
||||
self.onHastyLoop();
|
||||
return;
|
||||
}
|
||||
|
||||
self.active = Promise
|
||||
.try(this._fn)
|
||||
.then(function () {
|
||||
self._scheduleLoop();
|
||||
})
|
||||
.catch(function (err) {
|
||||
self.stop();
|
||||
fatalError(err);
|
||||
})
|
||||
.finally(function () {
|
||||
self.active = null;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Schedule the next iteration of the loop
|
||||
*
|
||||
* @private
|
||||
* @return {number} - the timer promise
|
||||
*/
|
||||
Looper.prototype._scheduleLoop = function () {
|
||||
this._unScheduleLoop();
|
||||
this._timer = this._ms ? $timeout(this._loopTheLoop, this._ms) : null;
|
||||
return this._timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the next iteration of the loop
|
||||
*
|
||||
* @private
|
||||
* @return {number} - the timer promise
|
||||
*/
|
||||
Looper.prototype._unScheduleLoop = function () {
|
||||
if (this._timer) {
|
||||
$timeout.cancel(this._timer);
|
||||
this._timer = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* execute the this._fn, and restart the timer
|
||||
*/
|
||||
Looper.prototype.run = function () {
|
||||
this.start();
|
||||
};
|
||||
|
||||
return Looper;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { FetchSoonProvider } from '../fetch';
|
||||
import { requestQueue } from '../_request_queue';
|
||||
import { LooperProvider } from './_looper';
|
||||
|
||||
export function SearchLooperProvider(Private, Promise, $rootScope) {
|
||||
const fetchSoon = Private(FetchSoonProvider);
|
||||
|
||||
const Looper = Private(LooperProvider);
|
||||
|
||||
/**
|
||||
* The Looper which will manage the doc fetch interval
|
||||
* @type {Looper}
|
||||
*/
|
||||
const searchLooper = new Looper(null, function () {
|
||||
$rootScope.$broadcast('courier:searchRefresh');
|
||||
const requests = requestQueue.getInactive();
|
||||
// promise returned from fetch.these() only resolves when
|
||||
// the requests complete, but we want to continue even if
|
||||
// the requests abort so we make our own
|
||||
fetchSoon.these(requests);
|
||||
return Promise.all(requests.map(request => request.getCompleteOrAbortedPromise()));
|
||||
});
|
||||
|
||||
searchLooper.onHastyLoop = function () {
|
||||
if (searchLooper.afterHastyQueued) return;
|
||||
|
||||
searchLooper.afterHastyQueued = Promise.resolve(searchLooper.active)
|
||||
.then(function () {
|
||||
return searchLooper._loopTheLoop();
|
||||
})
|
||||
.finally(function () {
|
||||
searchLooper.afterHastyQueued = null;
|
||||
});
|
||||
};
|
||||
|
||||
return searchLooper;
|
||||
}
|
|
@ -34,7 +34,7 @@ import _ from 'lodash';
|
|||
import { SavedObjectNotFound } from '../../errors';
|
||||
import MappingSetupProvider from '../../utils/mapping_setup';
|
||||
|
||||
import { SearchSourceProvider } from '../data_source/search_source';
|
||||
import { SearchSourceProvider } from '../search_source';
|
||||
import { SavedObjectsClientProvider, findObjectByTitle } from '../../saved_objects';
|
||||
import { migrateLegacyQuery } from '../../utils/migrateLegacyQuery.js';
|
||||
import { recentlyAccessed } from '../../persisted_log';
|
||||
|
|
|
@ -17,4 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { BuildESQueryProvider } from './build_es_query';
|
||||
export { SearchLooperProvider } from './search_looper';
|
190
src/ui/public/courier/search_looper/search_looper.js
Normal file
190
src/ui/public/courier/search_looper/search_looper.js
Normal file
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { fatalError } from '../../notify';
|
||||
import '../../promises';
|
||||
import { requestQueue } from '../_request_queue';
|
||||
import { FetchSoonProvider } from '../fetch';
|
||||
|
||||
export function SearchLooperProvider(Private, Promise, $timeout, $rootScope) {
|
||||
const fetchSoon = Private(FetchSoonProvider);
|
||||
|
||||
class SearchLooper {
|
||||
constructor() {
|
||||
this._intervalInMs = undefined;
|
||||
this._timer = null;
|
||||
this._started = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of milliseconds between
|
||||
* each loop
|
||||
*
|
||||
* @param {integer} intervalInMs
|
||||
*/
|
||||
setIntervalInMs = intervalInMs => {
|
||||
this._intervalInMs = _.parseInt(intervalInMs) || 0;
|
||||
|
||||
if (!this._started) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._intervalInMs) {
|
||||
this.start(false);
|
||||
} else {
|
||||
this._unscheduleLoop();
|
||||
}
|
||||
};
|
||||
|
||||
start = loopOver => {
|
||||
if (loopOver == null) {
|
||||
loopOver = true;
|
||||
}
|
||||
|
||||
if (!this._started) {
|
||||
this._started = true;
|
||||
} else {
|
||||
this._unscheduleLoop();
|
||||
}
|
||||
|
||||
if (loopOver) {
|
||||
this._executeLoop();
|
||||
} else {
|
||||
this._scheduleLoop();
|
||||
}
|
||||
};
|
||||
|
||||
stop = () => {
|
||||
this._unscheduleLoop();
|
||||
this._started = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Restart the looper only if it is already started.
|
||||
* Called automatically when ms is changed
|
||||
*/
|
||||
restart = () => {
|
||||
this.start(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Is the looper currently started/running/scheduled/going to execute
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
started = () => {
|
||||
return !!this._started;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the loop is executed before the previous
|
||||
* run has completed.
|
||||
*
|
||||
* @override
|
||||
* @return {undefined}
|
||||
*/
|
||||
_onHastyLoop = () => {
|
||||
if (this.afterHastyQueued) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.afterHastyQueued = Promise.resolve(this.active)
|
||||
.then(() => {
|
||||
return this._executeLoop();
|
||||
})
|
||||
.finally(() => {
|
||||
this.afterHastyQueued = null;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Wraps this._fn so that this._fn can be changed
|
||||
* without rescheduling and schedules
|
||||
* the next iteration
|
||||
*
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
_executeLoop = () => {
|
||||
if (this.active) {
|
||||
this._onHastyLoop();
|
||||
return;
|
||||
}
|
||||
|
||||
this.active = Promise.try(this._executeLoopAction)
|
||||
.then(() => {
|
||||
this._scheduleLoop();
|
||||
})
|
||||
.catch(err => {
|
||||
this.stop();
|
||||
fatalError(err);
|
||||
})
|
||||
.finally(() => {
|
||||
this.active = null;
|
||||
});
|
||||
};
|
||||
|
||||
_executeLoopAction = () => {
|
||||
$rootScope.$broadcast('courier:searchRefresh');
|
||||
const requests = requestQueue.getInactive();
|
||||
|
||||
// promise returned from fetch.fetchSearchRequests() only resolves when
|
||||
// the requests complete, but we want to continue even if
|
||||
// the requests abort so we make our own
|
||||
fetchSoon.fetchSearchRequests(requests);
|
||||
|
||||
return Promise.all(
|
||||
requests.map(request => request.getCompleteOrAbortedPromise())
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Schedule the next iteration of the loop
|
||||
*
|
||||
* @private
|
||||
* @return {number} - the timer promise
|
||||
*/
|
||||
_scheduleLoop = () => {
|
||||
this._unscheduleLoop();
|
||||
|
||||
this._timer = this._intervalInMs
|
||||
? $timeout(this._executeLoop, this._intervalInMs)
|
||||
: null;
|
||||
|
||||
return this._timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel the next iteration of the loop
|
||||
*
|
||||
* @private
|
||||
* @return {number} - the timer promise
|
||||
*/
|
||||
_unscheduleLoop = () => {
|
||||
if (this._timer) {
|
||||
$timeout.cancel(this._timer);
|
||||
this._timer = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new SearchLooper();
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import expect from 'expect.js';
|
||||
import _ from 'lodash';
|
||||
import { migrateFilter } from '../_migrate_filter';
|
||||
import { migrateFilter } from '../migrate_filter';
|
||||
|
||||
describe('migrateFilter', function () {
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import expect from 'expect.js';
|
||||
import chrome from '../../../chrome';
|
||||
import { decorateQuery } from '../_decorate_query';
|
||||
import { decorateQuery } from '../decorate_query';
|
||||
|
||||
const config = chrome.getUiSettingsClient();
|
||||
describe('Query decorator', function () {
|
|
@ -23,7 +23,7 @@ import ngMock from 'ng_mock';
|
|||
import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js';
|
||||
import { fromKueryExpression, toElasticsearchQuery } from '../../../../kuery';
|
||||
import { luceneStringToDsl } from '../lucene_string_to_dsl';
|
||||
import { decorateQuery } from '../../_decorate_query';
|
||||
import { decorateQuery } from '../../decorate_query';
|
||||
|
||||
let indexPattern;
|
||||
let buildEsQuery;
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
import { buildQueryFromLucene } from '../from_lucene';
|
||||
import { decorateQuery } from '../../_decorate_query.js';
|
||||
import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal.js';
|
||||
import { decorateQuery } from '../../decorate_query';
|
||||
import { expectDeepEqual } from '../../../../../../test_utils/expect_deep_equal';
|
||||
import { luceneStringToDsl } from '../lucene_string_to_dsl';
|
||||
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { groupBy, has } from 'lodash';
|
||||
import { decorateQuery } from '../_decorate_query';
|
||||
import { decorateQuery } from '../decorate_query';
|
||||
import { buildQueryFromKuery } from './from_kuery';
|
||||
import { buildQueryFromFilters } from './from_filters';
|
||||
import { buildQueryFromLucene } from './from_lucene';
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import { migrateFilter } from '../_migrate_filter';
|
||||
import { migrateFilter } from '../migrate_filter';
|
||||
|
||||
/**
|
||||
* Create a filter that can be reversed for filters with negate set
|
22
src/ui/public/courier/search_source/build_query/index.js
Normal file
22
src/ui/public/courier/search_source/build_query/index.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { BuildESQueryProvider } from './build_es_query';
|
||||
export { buildQueryFromFilters } from './from_filters';
|
||||
export { luceneStringToDsl } from './lucene_string_to_dsl';
|
23
src/ui/public/courier/search_source/index.js
Normal file
23
src/ui/public/courier/search_source/index.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { SearchSourceProvider } from './search_source';
|
||||
export { migrateFilter } from './migrate_filter';
|
||||
export { decorateQuery } from './decorate_query';
|
||||
export { buildQueryFromFilters, luceneStringToDsl } from './build_query';
|
|
@ -76,7 +76,7 @@ import '../../promises';
|
|||
|
||||
import { NormalizeSortRequestProvider } from './_normalize_sort_request';
|
||||
import { SearchRequestProvider } from '../fetch/request';
|
||||
import { SegmentedRequestProvider } from '../fetch/request/segmented';
|
||||
import { SegmentedSearchRequestProvider } from '../fetch/request/segmented_search_request';
|
||||
|
||||
import { requestQueue } from '../_request_queue';
|
||||
import { FetchSoonProvider } from '../fetch';
|
||||
|
@ -100,7 +100,7 @@ function isIndexPattern(val) {
|
|||
|
||||
export function SearchSourceProvider(Promise, Private, config) {
|
||||
const SearchRequest = Private(SearchRequestProvider);
|
||||
const SegmentedRequest = Private(SegmentedRequestProvider);
|
||||
const SegmentedSearchRequest = Private(SegmentedSearchRequestProvider);
|
||||
const normalizeSortRequest = Private(NormalizeSortRequestProvider);
|
||||
const fetchSoon = Private(FetchSoonProvider);
|
||||
const buildESQuery = Private(BuildESQueryProvider);
|
||||
|
@ -253,7 +253,7 @@ export function SearchSourceProvider(Promise, Private, config) {
|
|||
reject(error);
|
||||
request.abort();
|
||||
};
|
||||
const req = new SegmentedRequest({ source: self, defer, errorHandler, initFn: initFunction });
|
||||
const req = new SegmentedSearchRequest({ source: self, defer, errorHandler, initFn: initFunction });
|
||||
|
||||
// Return promises created by the completion handler so that
|
||||
// errors will bubble properly
|
||||
|
@ -404,18 +404,16 @@ export function SearchSourceProvider(Promise, Private, config) {
|
|||
req = self._createRequest({ errorHandler });
|
||||
}
|
||||
|
||||
fetchSoon.these([req]);
|
||||
|
||||
fetchSoon.fetchSearchRequests([req]);
|
||||
return req.getCompletePromise();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch all pending requests for this source ASAP
|
||||
* @async
|
||||
*/
|
||||
fetchQueued() {
|
||||
return fetchSoon.these(this._myStartableQueued());
|
||||
return fetchSoon.fetchSearchRequests(this._myStartableQueued());
|
||||
}
|
||||
|
||||
/**
|
|
@ -35,7 +35,7 @@ describe('doc table filter actions', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('add filters', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('invert filters', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('pin filters', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('remove filters', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -36,7 +36,7 @@ describe('toggle filters', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('Filter Bar Directive', function () {
|
|||
ngMock.module('kibana');
|
||||
|
||||
ngMock.module('kibana/courier', function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
});
|
||||
|
||||
ngMock.inject(function (Private, $injector, _$rootScope_, _$compile_) {
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ describe('Filter Bar Directive', function () {
|
|||
'kibana',
|
||||
'kibana/courier',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
}
|
||||
));
|
||||
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
export function FilterBarLibExtractTimeFilterProvider(courier, Promise) {
|
||||
export function FilterBarLibExtractTimeFilterProvider(indexPatterns, Promise) {
|
||||
return Promise.method(function (filters) {
|
||||
// Assume all the index patterns are the same since they will be added
|
||||
// from the same visualization.
|
||||
const id = _.get(filters, '[0].meta.index');
|
||||
if (id == null) return;
|
||||
|
||||
return courier.indexPatterns.get(id).then(function (indexPattern) {
|
||||
return indexPatterns.get(id).then(function (indexPattern) {
|
||||
const filter = _.find(filters, function (obj) {
|
||||
const key = _.keys(obj.range)[0];
|
||||
return key === indexPattern.timeFieldName;
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
|
||||
export function FilterBarLibFilterOutTimeBasedFilterProvider(courier, Promise) {
|
||||
export function FilterBarLibFilterOutTimeBasedFilterProvider(indexPatterns, Promise) {
|
||||
return Promise.method(function (filters) {
|
||||
const id = _.get(filters, '[0].meta.index');
|
||||
if (id == null) return;
|
||||
|
||||
return courier.indexPatterns.get(id).then(function (indexPattern) {
|
||||
return indexPatterns.get(id).then(function (indexPattern) {
|
||||
return _.filter(filters, function (filter) {
|
||||
return !(filter.range && filter.range[indexPattern.timeFieldName]);
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import _ from 'lodash';
|
||||
import { SavedObjectNotFound } from '../../errors';
|
||||
|
||||
export function FilterBarLibMapGeoBoundingBoxProvider(Promise, courier) {
|
||||
export function FilterBarLibMapGeoBoundingBoxProvider(Promise, indexPatterns) {
|
||||
return function (filter) {
|
||||
if (filter.geo_bounding_box) {
|
||||
function getParams(indexPattern) {
|
||||
|
@ -43,8 +43,7 @@ export function FilterBarLibMapGeoBoundingBoxProvider(Promise, courier) {
|
|||
return { type, key, value, params };
|
||||
}
|
||||
|
||||
return courier
|
||||
.indexPatterns
|
||||
return indexPatterns
|
||||
.get(filter.meta.index)
|
||||
.then(getParams)
|
||||
.catch((error) => {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import _ from 'lodash';
|
||||
import { SavedObjectNotFound } from '../../errors';
|
||||
|
||||
export function FilterBarLibMapGeoPolygonProvider(Promise, courier) {
|
||||
export function FilterBarLibMapGeoPolygonProvider(Promise, indexPatterns) {
|
||||
return function (filter) {
|
||||
if (filter.geo_polygon) {
|
||||
function getParams(indexPattern) {
|
||||
|
@ -42,8 +42,7 @@ export function FilterBarLibMapGeoPolygonProvider(Promise, courier) {
|
|||
return { type, key, value, params };
|
||||
}
|
||||
|
||||
return courier
|
||||
.indexPatterns
|
||||
return indexPatterns
|
||||
.get(filter.meta.index)
|
||||
.then(getParams)
|
||||
.catch((error) => {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import _ from 'lodash';
|
||||
import { SavedObjectNotFound } from '../../errors';
|
||||
|
||||
export function FilterBarLibMapPhraseProvider(Promise, courier) {
|
||||
export function FilterBarLibMapPhraseProvider(Promise, indexPatterns) {
|
||||
return function (filter) {
|
||||
const isScriptedPhraseFilter = isScriptedPhrase(filter);
|
||||
if (!_.has(filter, ['query', 'match']) && !isScriptedPhraseFilter) {
|
||||
|
@ -41,8 +41,7 @@ export function FilterBarLibMapPhraseProvider(Promise, courier) {
|
|||
return { type, key, value, params };
|
||||
}
|
||||
|
||||
return courier
|
||||
.indexPatterns
|
||||
return indexPatterns
|
||||
.get(filter.meta.index)
|
||||
.then(getParams)
|
||||
.catch((error) => {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import { has, get } from 'lodash';
|
||||
import { SavedObjectNotFound } from '../../errors';
|
||||
|
||||
export function FilterBarLibMapRangeProvider(Promise, courier) {
|
||||
export function FilterBarLibMapRangeProvider(Promise, indexPatterns) {
|
||||
return function (filter) {
|
||||
const isScriptedRangeFilter = isScriptedRange(filter);
|
||||
if (!filter.range && !isScriptedRangeFilter) {
|
||||
|
@ -51,8 +51,7 @@ export function FilterBarLibMapRangeProvider(Promise, courier) {
|
|||
return { type, key, value, params };
|
||||
}
|
||||
|
||||
return courier
|
||||
.indexPatterns
|
||||
return indexPatterns
|
||||
.get(filter.meta.index)
|
||||
.then(getParams)
|
||||
.catch((error) => {
|
||||
|
|
|
@ -46,7 +46,7 @@ describe('Filter Manager', function () {
|
|||
'kibana/courier',
|
||||
'kibana/global_state',
|
||||
function ($provide) {
|
||||
$provide.service('courier', require('fixtures/mock_courier'));
|
||||
$provide.service('indexPatterns', require('fixtures/mock_index_patterns'));
|
||||
|
||||
appState = new MockState({ filters: [] });
|
||||
$provide.service('getAppState', function () {
|
||||
|
|
|
@ -18,4 +18,5 @@
|
|||
*/
|
||||
|
||||
export { KbnUrlProvider } from './url';
|
||||
export { RedirectWhenMissingProvider } from './redirect_when_missing';
|
||||
export { modifyUrl } from './modify_url';
|
||||
|
|
|
@ -17,7 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import { SavedObjectNotFound } from '../errors';
|
||||
import { uiModules } from '../modules';
|
||||
|
||||
uiModules.get('kibana/url')
|
||||
.service('redirectWhenMissing', function (Private) { return Private(RedirectWhenMissingProvider); });
|
||||
|
||||
export function RedirectWhenMissingProvider($location, kbnUrl, Notifier, Promise) {
|
||||
const notify = new Notifier();
|
||||
|
@ -39,8 +44,11 @@ export function RedirectWhenMissingProvider($location, kbnUrl, Notifier, Promise
|
|||
// if this error is not "404", rethrow
|
||||
const savedObjectNotFound = err instanceof SavedObjectNotFound;
|
||||
const unknownVisType = err.message.indexOf('Invalid type') === 0;
|
||||
if (unknownVisType) err.savedObjectType = 'visualization';
|
||||
else if (!savedObjectNotFound) throw err;
|
||||
if (unknownVisType) {
|
||||
err.savedObjectType = 'visualization';
|
||||
} else if (!savedObjectNotFound) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
let url = mapping[err.savedObjectType] || mapping['*'];
|
||||
if (!url) url = '/';
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { VisRequestHandlersRegistryProvider } from '../../registry/vis_request_handlers';
|
||||
import { calculateObjectHash } from '../lib/calculate_object_hash';
|
||||
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
|
||||
|
|
|
@ -36,7 +36,7 @@ import { onBrushEvent } from '../utils/brush_event';
|
|||
import { FilterBarQueryFilterProvider } from '../filter_bar/query_filter';
|
||||
import { FilterBarClickHandlerProvider } from '../filter_bar/filter_bar_click_handler';
|
||||
import { updateVisualizationConfig } from './vis_update';
|
||||
import { SearchSourceProvider } from '../courier/data_source/search_source';
|
||||
import { SearchSourceProvider } from '../courier/search_source';
|
||||
import { SavedObjectsClientProvider } from '../saved_objects';
|
||||
import { timefilter } from 'ui/timefilter';
|
||||
|
||||
|
|
|
@ -527,6 +527,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
|
|||
if (sliceValue) {
|
||||
await testSubjects.click(`pieSlice-${sliceValue}`);
|
||||
} else {
|
||||
// If no pie slice has been provided, find the first one available.
|
||||
await retry.try(async () => {
|
||||
const slices = await find.allByCssSelector('svg > g > g.arcs > path.slice');
|
||||
log.debug('Slices found:' + slices.length);
|
||||
|
|
|
@ -5,13 +5,15 @@
|
|||
*/
|
||||
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { SavedObjectProvider } from 'ui/courier';
|
||||
|
||||
const module = uiModules.get('app/dashboard');
|
||||
|
||||
export function SavedWorkspaceProvider(courier) {
|
||||
export function SavedWorkspaceProvider(Private) {
|
||||
// SavedWorkspace constructor. Usually you'd interact with an instance of this.
|
||||
// ID is option, without it one will be generated on save.
|
||||
class SavedWorkspace extends courier.SavedObject {
|
||||
const SavedObject = Private(SavedObjectProvider);
|
||||
class SavedWorkspace extends SavedObject {
|
||||
constructor(id) {
|
||||
// Gives our SavedWorkspace the properties of a SavedObject
|
||||
super ({
|
||||
|
|
|
@ -17,12 +17,10 @@ import rison from 'rison-node';
|
|||
import 'plugins/kibana/visualize/styles/main.less';
|
||||
import 'plugins/ml/components/form_filter_input';
|
||||
|
||||
import 'ui/courier';
|
||||
import chrome from 'ui/chrome';
|
||||
import uiRoutes from 'ui/routes';
|
||||
import { notify } from 'ui/notify';
|
||||
import { luceneStringToDsl } from 'ui/courier/data_source/build_query/lucene_string_to_dsl.js';
|
||||
import { decorateQuery } from 'ui/courier/data_source/_decorate_query';
|
||||
import { decorateQuery, luceneStringToDsl } from 'ui/courier';
|
||||
|
||||
import { ML_JOB_FIELD_TYPES, KBN_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types';
|
||||
import { kbnTypeToMLJobType } from 'plugins/ml/util/field_types_utils';
|
||||
|
|
|
@ -472,7 +472,7 @@ module.controller('MlNewJob',
|
|||
// mappings should be fully set up, but the Kibana mappings then
|
||||
// need to be refreshed to reflect the Elasticsearch mappings for
|
||||
// any new analytical fields that have been configured in the job.
|
||||
//courier.indexPatterns.get('.ml-anomalies-*')
|
||||
//indexPatterns.get('.ml-anomalies-*')
|
||||
//.then((indexPattern) => {
|
||||
// indexPattern.refreshFields()
|
||||
// .then(() => {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { migrateFilter } from 'ui/courier/data_source/_migrate_filter.js';
|
||||
import { migrateFilter } from 'ui/courier';
|
||||
import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed';
|
||||
import { mlJobService } from 'plugins/ml/services/job_service';
|
||||
|
||||
|
|
|
@ -9,39 +9,39 @@
|
|||
import { notify } from 'ui/notify';
|
||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||
|
||||
let indexPatterns = [];
|
||||
let indexPatternCache = [];
|
||||
let fullIndexPatterns = [];
|
||||
let currentIndexPattern = null;
|
||||
let currentSavedSearch = null;
|
||||
|
||||
export function loadIndexPatterns(Private, courier) {
|
||||
fullIndexPatterns = courier.indexPatterns;
|
||||
export function loadIndexPatterns(Private, indexPatterns) {
|
||||
fullIndexPatterns = indexPatterns;
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
return savedObjectsClient.find({
|
||||
type: 'index-pattern',
|
||||
fields: ['title'],
|
||||
perPage: 10000
|
||||
}).then((response) => {
|
||||
indexPatterns = response.savedObjects;
|
||||
return indexPatterns;
|
||||
indexPatternCache = response.savedObjects;
|
||||
return indexPatternCache;
|
||||
});
|
||||
}
|
||||
|
||||
export function getIndexPatterns() {
|
||||
return indexPatterns;
|
||||
return indexPatternCache;
|
||||
}
|
||||
|
||||
export function getIndexPatternIdFromName(name) {
|
||||
for (let j = 0; j < indexPatterns.length; j++) {
|
||||
if (indexPatterns[j].get('title') === name) {
|
||||
return indexPatterns[j].id;
|
||||
for (let j = 0; j < indexPatternCache.length; j++) {
|
||||
if (indexPatternCache[j].get('title') === name) {
|
||||
return indexPatternCache[j].id;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function loadCurrentIndexPattern(courier, $route) {
|
||||
fullIndexPatterns = courier.indexPatterns;
|
||||
export function loadCurrentIndexPattern(indexPatterns, $route) {
|
||||
fullIndexPatterns = indexPatterns;
|
||||
currentIndexPattern = fullIndexPatterns.get($route.current.params.index);
|
||||
return currentIndexPattern;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export function getIndexPatternById(id) {
|
|||
return fullIndexPatterns.get(id);
|
||||
}
|
||||
|
||||
export function loadCurrentSavedSearch(courier, $route, savedSearches) {
|
||||
export function loadCurrentSavedSearch($route, savedSearches) {
|
||||
currentSavedSearch = savedSearches.get($route.current.params.savedSearchId);
|
||||
return currentSavedSearch;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue