2020-03-19 10:28:21 +00:00
|
|
|
import Service, { inject as service } from '@ember/service';
|
|
|
|
|
|
|
|
import MultiMap from 'mnemonist/multi-map';
|
|
|
|
|
|
|
|
// TODO: Expose sizes of things via env vars
|
|
|
|
|
|
|
|
// caches cursors and previous events when the EventSources are destroyed
|
2020-05-11 15:37:11 +00:00
|
|
|
let cache = null;
|
2020-03-19 10:28:21 +00:00
|
|
|
// keeps a record of currently in use EventSources
|
2020-05-11 15:37:11 +00:00
|
|
|
let sources = null;
|
2020-03-19 10:28:21 +00:00
|
|
|
// keeps a count of currently in use EventSources
|
2020-05-11 15:37:11 +00:00
|
|
|
let usage = null;
|
2020-03-19 10:28:21 +00:00
|
|
|
|
|
|
|
export default Service.extend({
|
|
|
|
dom: service('dom'),
|
|
|
|
consul: service('data-source/protocols/http'),
|
|
|
|
settings: service('data-source/protocols/local-storage'),
|
|
|
|
|
|
|
|
init: function() {
|
|
|
|
this._super(...arguments);
|
2020-05-27 10:23:21 +00:00
|
|
|
cache = new Map();
|
|
|
|
sources = new Map();
|
|
|
|
usage = new MultiMap(Set);
|
2020-05-11 15:37:11 +00:00
|
|
|
this._listeners = this.dom.listeners();
|
|
|
|
},
|
|
|
|
resetCache: function() {
|
2020-03-19 10:28:21 +00:00
|
|
|
cache = new Map();
|
|
|
|
},
|
|
|
|
willDestroy: function() {
|
|
|
|
this._listeners.remove();
|
2020-05-27 10:23:21 +00:00
|
|
|
sources.forEach(function(item) {
|
2020-04-21 15:49:11 +00:00
|
|
|
item.close();
|
|
|
|
});
|
|
|
|
cache = null;
|
|
|
|
sources = null;
|
|
|
|
usage = null;
|
2020-03-19 10:28:21 +00:00
|
|
|
},
|
|
|
|
|
2020-07-09 09:08:47 +00:00
|
|
|
open: function(uri, ref, open = false) {
|
2020-03-19 10:28:21 +00:00
|
|
|
let source;
|
|
|
|
// Check the cache for an EventSource that is already being used
|
|
|
|
// for this uri. If we don't have one, set one up.
|
|
|
|
if (uri.indexOf('://') === -1) {
|
|
|
|
uri = `consul://${uri}`;
|
|
|
|
}
|
|
|
|
if (!sources.has(uri)) {
|
2020-04-21 15:49:11 +00:00
|
|
|
let [providerName, pathname] = uri.split('://');
|
2020-03-19 10:28:21 +00:00
|
|
|
const provider = this[providerName];
|
|
|
|
|
|
|
|
let configuration = {};
|
|
|
|
if (cache.has(uri)) {
|
|
|
|
configuration = cache.get(uri);
|
|
|
|
}
|
|
|
|
source = provider.source(pathname, configuration);
|
|
|
|
this._listeners.add(source, {
|
|
|
|
close: e => {
|
|
|
|
const source = e.target;
|
|
|
|
source.removeEventListener('close', close);
|
2020-05-27 10:23:21 +00:00
|
|
|
const event = source.getCurrentEvent();
|
|
|
|
const cursor = source.configuration.cursor;
|
|
|
|
// only cache data if we have any
|
|
|
|
if (typeof event !== 'undefined' && typeof cursor !== 'undefined') {
|
|
|
|
cache.set(uri, {
|
2020-07-09 09:08:47 +00:00
|
|
|
currentEvent: event,
|
|
|
|
cursor: cursor,
|
2020-05-27 10:23:21 +00:00
|
|
|
});
|
|
|
|
}
|
2020-03-19 10:28:21 +00:00
|
|
|
// the data is cached delete the EventSource
|
2020-07-09 09:08:47 +00:00
|
|
|
if (!usage.has(source)) {
|
|
|
|
sources.delete(uri);
|
|
|
|
}
|
2020-03-19 10:28:21 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
sources.set(uri, source);
|
|
|
|
} else {
|
|
|
|
source = sources.get(uri);
|
|
|
|
}
|
2020-07-09 09:08:47 +00:00
|
|
|
// only open if its not already being used
|
|
|
|
// in the case of blocking queries being disabled
|
|
|
|
// you may want to specifically force an open
|
|
|
|
// if blocking queries are enabled then opening an already
|
|
|
|
// open blocking query does nothing
|
|
|
|
if (!usage.has(source) || open) {
|
|
|
|
source.open();
|
|
|
|
}
|
2020-03-19 10:28:21 +00:00
|
|
|
// set/increase the usage counter
|
|
|
|
usage.set(source, ref);
|
|
|
|
return source;
|
|
|
|
},
|
|
|
|
close: function(source, ref) {
|
|
|
|
if (source) {
|
|
|
|
// decrease the usage counter
|
|
|
|
usage.remove(source, ref);
|
|
|
|
// if the EventSource is no longer being used
|
|
|
|
// close it (data caching is dealt with by the above 'close' event listener)
|
|
|
|
if (!usage.has(source)) {
|
|
|
|
source.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|