open-consul/ui-v2/app/services/data-source/service.js
John Cowen 0a47a95588 ui: Add DataSource component (#7448)
* ui: Add data-source component and related services (#6486)

* ui: Add data-source component and related services:

1. DataSource component
2. Repository manager for retrieving repositories based on URIs
3. Blocking data service for injection to the data-source component to
support blocking query types of data sources
4. 'Once' promise based data service for injection for potential
fallback to old style promise based data (would need to be injected via
an initial runtime variable)
5. Several utility functions taken from elsewhere
  - maybeCall - a replication of code from elsewhere for condition
  calling a function based on the result of a promise
  - restartWhenAvailable - used for restarting blocking queries when a
  tab is brought to the front
  - ifNotBlocking - to check if blocking is NOT enabled

* Move to a different organization based on protocols

* Don't call open twice when eager

* Workaround new ember error for reading and writing at the same time

* Add first draft of a README.mdx file
2020-05-12 17:14:18 +00:00

85 lines
2.3 KiB
JavaScript

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
let cache;
// keeps a record of currently in use EventSources
let sources;
// keeps a count of currently in use EventSources
let usage;
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);
cache = new Map();
sources = new Map();
usage = new MultiMap(Set);
this._listeners = this.dom.listeners();
},
willDestroy: function() {
this._listeners.remove();
},
open: function(uri, ref) {
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)) {
const url = new URL(uri);
let pathname = url.pathname;
if (pathname.startsWith('//')) {
pathname = pathname.substr(2);
}
const providerName = url.protocol.substr(0, url.protocol.length - 1);
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);
cache.set(uri, {
currentEvent: source.getCurrentEvent(),
cursor: source.configuration.cursor,
});
// the data is cached delete the EventSource
sources.delete(uri);
},
});
sources.set(uri, source);
} else {
source = sources.get(uri);
}
// set/increase the usage counter
usage.set(source, ref);
source.open();
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();
}
}
},
});