Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timefilter Auto Refresh - Closes "Support for auto-refresh #1845" #2196

Merged
merged 95 commits into from
Dec 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
f6d05dd
Adding autorefresh using courier and timefilter
grouma Dec 9, 2014
f0359af
Adding tests for refresh interval feature
grouma Dec 11, 2014
d725327
Added more tests to refresh interval feature. Adding better error che…
grouma Dec 15, 2014
083b63a
Merge branch 'master' of https://github.com/elasticsearch/kibana into…
grouma Dec 15, 2014
67df143
Prevent refresh of data when "off" refresh interval is selected
grouma Dec 16, 2014
8ae871c
moved segmented search into a courier fetch strategy
Dec 16, 2014
e6df20d
[fetch] check for #getIncompleteRequests when strategies complete the…
Dec 16, 2014
40cc3cb
[courier/fetchThese] reformatted and teased a bit
Dec 16, 2014
710581b
[discover/segmentedFetch] disabled the tests for now
Dec 16, 2014
c23525a
[courier/segmentedSearch] expose the #mergeResponse method
Dec 16, 2014
eb3d904
Merge branch 'TimefilterAutoRefresh' of github.com:grouma/kibana into…
Dec 16, 2014
90aed85
Merge pull request #1 from spenceralger/segment_in_courier
grouma Dec 16, 2014
11aa394
Simplifying the refresh UI
grouma Dec 16, 2014
776a1b8
[timepicker] slight modification to navbar css
Dec 16, 2014
2c8c48b
Merge pull request #2 from spenceralger/TimefilterAutoRefresh
grouma Dec 16, 2014
b5debf2
[discover] improve style of discover vis overlay that has been busted…
Dec 16, 2014
5a2a605
Merge branch 'TimefilterAutoRefresh' of github.com:grouma/kibana into…
Dec 16, 2014
09c3fd1
Refresh interval is now saved in session storage. Corresponding tests…
grouma Dec 17, 2014
1a15a78
Fixing issues with refresh interval session storage. Removing unecess…
grouma Dec 17, 2014
dab0dc4
Merge branch 'configure_private' into TimefilterAutoRefresh
Dec 17, 2014
5215fd1
[courier/fetch/segmented] proxy the strategy method to SegmentedState
Dec 17, 2014
735d455
[courier/segmentedState] ensure that events will always emit in order
Dec 17, 2014
7162728
[courier/fetch] broke fetchThese into more manageable pieces
Dec 17, 2014
2e14260
[courier/fetch/segmented] added tests and fixed discovered bugs
Dec 18, 2014
2f3ef3c
Merge branch 'master' into TimefilterAutoRefresh
Dec 18, 2014
f137a65
Merge pull request #3 from spenceralger/TimefilterAutoRefresh
grouma Dec 18, 2014
e8b23c8
[notifier] stop the courier on fatal errors
Dec 18, 2014
e3b50fb
[timepicker] fix invalid html entity
Dec 18, 2014
ad025a2
Merge branch 'master' into TimefilterAutoRefresh
Dec 18, 2014
03f0e51
[timepicker] HTMLPrettify'd that thang
Dec 18, 2014
32be3c3
[courier] warn when refresh interval is too damn high
Dec 18, 2014
be7e9f2
[courier] restart the looper on #fetch(), don't trigger. Fetch direct…
Dec 18, 2014
64b9d7f
Cleaning up refresh interval options.
grouma Dec 18, 2014
8a8526d
[courier] refactored request queue, allowing requests to be restarted
Dec 19, 2014
61537df
[courier/segmentedRequest] only init state at request time
Dec 19, 2014
0a07e71
[courier/looper] track loop completion and rejected promises
Dec 19, 2014
bea6d12
[courier] shorter request class names +1
Dec 19, 2014
f5bfcfe
[courier] restart in progress requests on fetch()
Dec 19, 2014
59db253
[events] update tests to use callbacks
Dec 19, 2014
08f2136
[events] always emit in the same order that emit was called
Dec 19, 2014
5875b37
[errors] default to no error for RequestFailure
Dec 19, 2014
5a3e3a9
[courier/requestQueue] simplify pending request logic
Dec 19, 2014
0260b26
[courier] only call fetch, not both fetch and looper
Dec 19, 2014
288ffe0
[courier/fetch] tease and simplify fetch, added restartable requests
Dec 19, 2014
34d7b70
Merge branch 'TimefilterAutoRefresh' of github.com:grouma/kibana into…
Dec 19, 2014
dd66001
[courier/looper] allow preventing fetch on restart
Dec 19, 2014
3b7ad9c
[timepicker] fix bag merge
Dec 19, 2014
ca7f216
[timepicker] readability improvments
Dec 19, 2014
7d90ce4
Merge branch 'master' into TimefilterAutoRefresh
Dec 19, 2014
12bc607
[courier/fetch] remove fetch method for removed segmented strategy
Dec 19, 2014
2496036
[courier/source] update method used to cancel requests
Dec 19, 2014
a1977a3
[courier] fix moved method
Dec 19, 2014
103297a
[courier/fetch] use ABORT to id canceled es request
Dec 19, 2014
7fcab33
[courier/fetch] added comments
Dec 19, 2014
668b5cf
[kibana] remove debug code
Dec 19, 2014
1fdf755
[courier/fetch/segmented] infer the totalSize from the flattened sear…
Dec 19, 2014
591a3a3
Merge pull request #4 from spenceralger/TimefilterAutoRefresh
grouma Dec 19, 2014
5f49c28
Merge branch 'master' of https://github.com/elasticsearch/kibana into…
Dec 19, 2014
a96f260
[courier/looper] prevent looper from starting until told to
Dec 19, 2014
45b9f00
[courier/DocRequest] cleanup
Dec 19, 2014
f530db2
[indexPatterns] get as many ids as possible
Dec 19, 2014
dcabba8
[tests] reanable all and clear storage before running
Dec 19, 2014
6cd1ab2
[docTitle] fixed test
Dec 19, 2014
2684435
[timepicker] updated tests for new style
Dec 19, 2014
859f56a
[courier] properly abort requests on close
Dec 19, 2014
e186ed1
[courier/fetch] always ignore unavailable indices
Dec 19, 2014
be22579
[courier/fetch] allow requests to filter the errors that cause rejection
Dec 19, 2014
e2c9ae5
[courier] deleted tests for now
Dec 20, 2014
ffe9252
[courier] move fatal callback into Courier to magically fix issue (th…
Dec 20, 2014
fd7f75c
Merge branch 'master' of https://github.com/elasticsearch/kibana into…
Dec 20, 2014
e432638
Merge pull request #5 from spenceralger/TimefilterAutoRefresh
grouma Dec 20, 2014
34d42a1
[courier/looper] convert to kbn Class style
Dec 24, 2014
c86e32b
[courier/looper] only fetch inactive requests
Dec 24, 2014
ee7ab28
[courier/looper] schedule once the previous run is complete
Dec 24, 2014
b030caa
[discover] restart the courier.searchLooper when fetch is complete
Dec 24, 2014
577d92f
remove unused deps
Dec 24, 2014
5a84841
Merge branch 'master' of https://github.com/elasticsearch/kibana into…
Dec 24, 2014
5c4dec6
[courier/fetch] reset the searchLooper after fetching
Dec 24, 2014
424e5ee
use courier.fetch() rather than .fetchQueued()
Dec 24, 2014
3f0bcf2
remove extra reassignment
Dec 24, 2014
cacb033
removed debugging assignment
Dec 24, 2014
98a2cbc
Merge pull request #6 from spenceralger/TimefilterAutoRefresh
grouma Dec 26, 2014
6cb601f
apply 6e7cf2d
Dec 29, 2014
c016970
implement 92d206c
Dec 29, 2014
084dbda
[courier/looper] manage the loopers timer a bit more closely, fixes h…
Dec 29, 2014
c779d01
[courier/fetch/segmented] don't call the initFn until start
Dec 29, 2014
17a0e5a
[discover] always catch errors that are returned
Dec 29, 2014
65e0a87
[discover] update the time on each request
Dec 29, 2014
b139243
Merge branch 'master' of https://github.com/elasticsearch/kibana into…
Dec 29, 2014
844d381
[promises] ensure that Promise.map doesn't throw
Dec 29, 2014
a65b547
[courier/docSource] use courier/fetch to fake responses to requests
Dec 29, 2014
0cb8c09
[courier/fetch/segmented] first emit is for first segment with rows, …
Dec 30, 2014
e83dc4f
[disocver] rely on guaranteed event order
Dec 30, 2014
ba32f62
[discover] only overlay before first results
Dec 30, 2014
8af2ffd
[discover] vertically center the throbber
Dec 30, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions src/kibana/components/courier/_pending_requests.js

This file was deleted.

35 changes: 35 additions & 0 deletions src/kibana/components/courier/_request_queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
define(function (require) {
return function PendingRequestList() {
var _ = require('lodash');

/**
* Queue of pending requests, requests are removed as
* they are processed by fetch.[sourceType]().
* @type {Array}
*/
var queue = [];

queue.getInactive = function (/* strategies */) {
return queue.get.apply(queue, arguments)
.filter(function (req) {
return !req.started;
});
};

queue.get = function (/* strategies.. */) {
var strategies = _.toArray(arguments);
return queue.filter(function (req) {
var strategyMatch = !strategies.length;
if (!strategyMatch) {
strategyMatch = strategies.some(function (strategy) {
return req.strategy === strategy;
});
}

return strategyMatch && req.canStart();
});
};

return queue;
};
});
36 changes: 26 additions & 10 deletions src/kibana/components/courier/courier.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
define(function (require) {
var errors = require('errors');

var _ = require('lodash');

require('services/es');
require('services/promises');
require('components/index_patterns/index_patterns');

require('modules').get('kibana/courier')
.service('courier', function ($rootScope, Private, Promise, indexPatterns) {
.service('courier', function ($rootScope, Private, Promise, indexPatterns, Notifier) {
function Courier() {
var self = this;

var DocSource = Private(require('components/courier/data_source/doc_source'));
var SearchSource = Private(require('components/courier/data_source/search_source'));

var pendingRequests = Private(require('components/courier/_pending_requests'));
var requestQueue = Private(require('components/courier/_request_queue'));
var errorHandlers = Private(require('components/courier/_error_handlers'));

var fetch = Private(require('components/courier/fetch/fetch'));
var docLooper = self.docLooper = Private(require('components/courier/looper/doc'));
var searchLooper = self.searchLooper = Private(require('components/courier/looper/search'));

Expand All @@ -29,7 +32,6 @@ define(function (require) {
self.SearchSource = SearchSource;

var HastyRefresh = errors.HastyRefresh;
var Abort = errors.Abort;

/**
* update the time between automatic search requests
Expand All @@ -47,6 +49,7 @@ define(function (require) {
*/
self.start = function () {
searchLooper.start();
docLooper.start();
return this;
};

Expand All @@ -56,7 +59,9 @@ define(function (require) {
* individual errors are routed to their respective requests.
*/
self.fetch = function () {
return searchLooper.run();
fetch.searches().then(function () {
searchLooper.restart();
});
};


Expand Down Expand Up @@ -105,15 +110,26 @@ define(function (require) {
searchLooper.stop();
docLooper.stop();

[].concat(pendingRequests.splice(0), this._errorHandlers.splice(0))
.forEach(function (req) {
req.defer.reject(new Abort());
});
_.invoke(requestQueue, 'abort');

if (pendingRequests.length) {
if (requestQueue.length) {
throw new Error('Aborting all pending requests failed.');
}
};

// Listen for refreshInterval changes
$rootScope.$watch('timefilter.refreshInterval', function () {
var refreshValue = _.deepGet($rootScope, 'timefilter.refreshInterval.value');
if (_.isNumber(refreshValue)) {
self.fetchInterval(refreshValue);
} else {
self.fetchInterval(0);
}
});

var onFatalDefer = Promise.defer();
onFatalDefer.promise.then(self.close);
Notifier.fatalCallbacks.push(onFatalDefer.resolve);
}

return new Courier();
Expand Down
72 changes: 34 additions & 38 deletions src/kibana/components/courier/data_source/_abstract.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
define(function (require) {
var inherits = require('lodash').inherits;
var _ = require('lodash');
var nextTick = require('utils/next_tick');

return function SourceAbstractFactory(Private, Promise, PromiseEmitter, timefilter) {
var pendingRequests = Private(require('components/courier/_pending_requests'));
return function SourceAbstractFactory(Private, Promise, PromiseEmitter) {
var requestQueue = Private(require('components/courier/_request_queue'));
var errorHandlers = Private(require('components/courier/_error_handlers'));
var courierFetch = Private(require('components/courier/fetch/fetch'));

Expand Down Expand Up @@ -123,8 +121,7 @@ define(function (require) {
var self = this;

return new PromiseEmitter(function (resolve, reject, defer) {
var req = self._createRequest(defer);
pendingRequests.push(req);
self._createRequest(defer);
}, handler);
};

Expand Down Expand Up @@ -154,64 +151,61 @@ define(function (require) {

/**
* Fetch just this source ASAP
* @param {Function} cb - callback
*
* ONLY USE IF YOU WILL BE USING THE RESULTS
* provided by the returned promise, otherwise
* call #fetchQueued()
*
* @async
*/
SourceAbstract.prototype.fetch = function () {
var self = this;
var req = _.first(self._myQueued());

var req = self._createRequest();
pendingRequests.push(req);

// fetch just the requests for this source
courierFetch.these(self._getType(), pendingRequests.splice(0).filter(function (req) {
if (req.source !== self) {
pendingRequests.push(req);
return false;
}
if (!req) {
req = self._createRequest();
}

return true;
}));
courierFetch.these([req]);

return req.defer.promise;
};

/**
* Fetch all pending requests for this source ASAP
* @async
*/
SourceAbstract.prototype.fetchQueued = function () {
return courierFetch.these(this._myQueued());
};

/**
* Cancel all pending requests for this dataSource
* @return {undefined}
*/
SourceAbstract.prototype.cancelPending = function () {
var pending = _.where(pendingRequests, { source: this});
_.pull.apply(_, [pendingRequests].concat(pending));
SourceAbstract.prototype.cancelQueued = function () {
_.invoke(this._myQueued(), 'abort');
};

/**
* Completely destroy the SearchSource.
* @return {undefined}
*/
SourceAbstract.prototype.destroy = function () {
this.cancelPending();
this.cancelQueued();
};

/*****
* PRIVATE API
*****/

SourceAbstract.prototype._createRequest = function (defer) {
var self = this;

var req = {
source: self,
defer: defer || Promise.defer()
};

if (self.history) {
// latest history at the top
self.history.unshift(req);
// trim all entries beyond 19/20
self.history.splice(20);
}
SourceAbstract.prototype._myQueued = function () {
var reqs = requestQueue.get(this._fetchStrategy);
return _.where(reqs, { source: this });
};

return req;
SourceAbstract.prototype._createRequest = function () {
throw new Error('_createRequest must be implemented by subclass');
};

/**
Expand All @@ -233,7 +227,7 @@ define(function (require) {
var current = this;

// call the ittr and return it's promise
return (function ittr(resolve, reject) {
return (function ittr() {
// itterate the _state object (not array) and
// pass each key:value pair to source._mergeProp. if _mergeProp
// returns a promise, then wait for it to complete and call _mergeProp again
Expand All @@ -259,6 +253,8 @@ define(function (require) {
}())
.then(function () {
if (type === 'search') {
flatState.body = flatState.body || {};

// defaults for the query
if (!flatState.body.query) {
flatState.body.query = {
Expand Down
20 changes: 12 additions & 8 deletions src/kibana/components/courier/data_source/_doc_send_to_es.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ define(function (require) {
var errors = require('errors');

return function (Promise, Private, es) {
var pendingRequests = Private(require('components/courier/_pending_requests'));
var requestQueue = Private(require('components/courier/_request_queue'));
var courierFetch = Private(require('components/courier/fetch/fetch'));

/**
* Backend for doUpdate and doIndex
Expand Down Expand Up @@ -44,19 +45,22 @@ define(function (require) {

// clear the queue and filter out the removed items, pushing the
// unmatched ones back in.
pendingRequests.splice(0).filter(function (req) {
var respondTo = requestQueue.splice(0).filter(function (req) {
var isDoc = req.source._getType() === 'doc';
var keyMatches = isDoc && req.source._versionKey() === key;

if (keyMatches) {
// resolve the request with a copy of the response
req.defer.resolve(_.cloneDeep(fetchResp));
return;
// put some request back into the queue
if (!keyMatches) {
requestQueue.push(req);
return false;
}

// otherwise, put the request back into the queue
pendingRequests.push(req);
return true;
});

return courierFetch.fakeFetchThese(respondTo, respondTo.map(function () {
return _.cloneDeep(fetchResp);
}));
});

return resp._id;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
define(function (require) {
return function RootSearchSource(Private, $rootScope, config, Promise, indexPatterns, timefilter, Notifier) {
var _ = require('lodash');
var SearchSource = Private(require('components/courier/data_source/search_source'));

var notify = new Notifier({ location: 'Root Search Source' });
Expand Down
11 changes: 5 additions & 6 deletions src/kibana/components/courier/data_source/doc_source.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
define(function (require) {
var _ = require('lodash');
var errors = require('errors');

var inherits = require('lodash').inherits;

return function DocSourceFactory(Private, Promise, es, sessionStorage) {
var sendToEs = Private(require('components/courier/data_source/_doc_send_to_es'));
var SourceAbstract = Private(require('components/courier/data_source/_abstract'));

var VersionConflict = errors.VersionConflict;
var RequestFailure = errors.RequestFailure;
var DocRequest = Private(require('components/courier/fetch/request/doc'));

_(DocSource).inherits(SourceAbstract);
function DocSource(initialState) {
Expand All @@ -23,6 +18,10 @@ define(function (require) {
* PUBLIC API
*****/

DocSource.prototype._createRequest = function (defer) {
return new DocRequest(this, defer);
};

/**
* List of methods that is turned into a chainable API in the constructor
* @type {Array}
Expand Down
31 changes: 27 additions & 4 deletions src/kibana/components/courier/data_source/search_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ define(function (require) {

return function SearchSourceFactory(Promise, Private) {
var _ = require('lodash');
var errors = require('errors');
var SourceAbstract = Private(require('components/courier/data_source/_abstract'));

var FetchFailure = errors.FetchFailure;
var RequestFailure = errors.RequestFailure;
var SearchRequest = Private(require('components/courier/fetch/request/search'));
var SegmentedRequest = Private(require('components/courier/fetch/request/segmented'));

_(SearchSource).inherits(SourceAbstract);
function SearchSource(initialState) {
Expand Down Expand Up @@ -125,6 +123,18 @@ define(function (require) {
return normal;
};

SearchSource.prototype.onBeginSegmentedFetch = function (initFunction) {
var self = this;
return Promise.try(function addRequest() {
var req = new SegmentedRequest(self, Promise.defer(), initFunction);

// return promises created by the completion handler so that
// errors will bubble properly
return req.defer.promise.then(addRequest);
});
};


/******
* PRIVATE APIS
******/
Expand All @@ -137,6 +147,19 @@ define(function (require) {
return 'search';
};

/**
* Create a common search request object, which should
* be put into the pending request queye, for this search
* source
*
* @param {Deferred} defer - the deferred object that should be resolved
* when the request is complete
* @return {SearchRequest}
*/
SearchSource.prototype._createRequest = function (defer) {
return new SearchRequest(this, defer);
};

/**
* Used to merge properties into the state within ._flatten().
* The state is passed in and modified by the function
Expand Down
Loading