2018-09-19 22:19:06 +00:00
|
|
|
import { computed } from '@ember/object';
|
2018-09-17 22:53:59 +00:00
|
|
|
import Service, { inject as service } from '@ember/service';
|
|
|
|
import { LRUMap } from 'lru_map';
|
|
|
|
import NodeStatsTracker from 'nomad-ui/utils/classes/node-stats-tracker';
|
|
|
|
import AllocationStatsTracker from 'nomad-ui/utils/classes/allocation-stats-tracker';
|
|
|
|
|
|
|
|
// An unbounded number of stat trackers is a great way to gobble up all the memory
|
|
|
|
// on a machine. This max number is unscientific, but aims to balance losing
|
|
|
|
// stat trackers a user is likely to return to with preventing gc from freeing
|
|
|
|
// memory occupied by stat trackers a user is likely to no longer care about
|
|
|
|
const MAX_STAT_TRACKERS = 10;
|
|
|
|
let registry;
|
|
|
|
|
2019-03-29 23:09:14 +00:00
|
|
|
const exists = (tracker, prop) =>
|
2021-12-28 16:08:12 +00:00
|
|
|
tracker.get(prop) &&
|
|
|
|
!tracker.get(prop).isDestroyed &&
|
|
|
|
!tracker.get(prop).isDestroying;
|
2019-03-29 23:09:14 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
export default class StatsTrackersRegistryService extends Service {
|
|
|
|
@service token;
|
2018-09-17 22:53:59 +00:00
|
|
|
|
2020-06-10 13:49:16 +00:00
|
|
|
constructor() {
|
|
|
|
super(...arguments);
|
2019-10-15 18:32:58 +00:00
|
|
|
|
2018-09-17 22:53:59 +00:00
|
|
|
// The LRUMap limits the number of trackers tracked by making room for
|
|
|
|
// new entries beyond the limit by removing the least recently used entry.
|
|
|
|
registry = new LRUMap(MAX_STAT_TRACKERS);
|
2020-06-10 13:49:16 +00:00
|
|
|
}
|
2018-09-17 22:53:59 +00:00
|
|
|
|
2018-09-19 22:19:06 +00:00
|
|
|
// A read-only way of getting a reference to the registry.
|
|
|
|
// Since this could be overwritten by a bad actor, it isn't
|
|
|
|
// used in getTracker
|
2020-06-10 13:49:16 +00:00
|
|
|
@computed
|
|
|
|
get registryRef() {
|
2020-06-09 21:03:28 +00:00
|
|
|
return registry;
|
2020-06-10 13:49:16 +00:00
|
|
|
}
|
2018-09-19 22:19:06 +00:00
|
|
|
|
2018-09-17 22:53:59 +00:00
|
|
|
getTracker(resource) {
|
|
|
|
if (!resource) return;
|
|
|
|
|
|
|
|
const type = resource && resource.constructor.modelName;
|
|
|
|
const key = `${type}:${resource.get('id')}`;
|
2021-12-28 16:08:12 +00:00
|
|
|
const Constructor =
|
|
|
|
type === 'node' ? NodeStatsTracker : AllocationStatsTracker;
|
2018-09-17 22:53:59 +00:00
|
|
|
const resourceProp = type === 'node' ? 'node' : 'allocation';
|
|
|
|
|
2019-03-29 23:09:14 +00:00
|
|
|
const cachedTracker = registry.get(key);
|
|
|
|
if (cachedTracker) {
|
|
|
|
// It's possible for the resource on a cachedTracker to have been
|
|
|
|
// deleted. Rebind it if that's the case.
|
2021-12-28 16:08:12 +00:00
|
|
|
if (!exists(cachedTracker, resourceProp))
|
|
|
|
cachedTracker.set(resourceProp, resource);
|
2019-03-29 23:09:14 +00:00
|
|
|
return cachedTracker;
|
|
|
|
}
|
|
|
|
|
2018-09-17 22:53:59 +00:00
|
|
|
const tracker = Constructor.create({
|
2021-12-28 14:45:20 +00:00
|
|
|
fetch: (url) => this.token.authorizedRequest(url),
|
2018-09-17 22:53:59 +00:00
|
|
|
[resourceProp]: resource,
|
|
|
|
});
|
|
|
|
|
|
|
|
registry.set(key, tracker);
|
|
|
|
|
|
|
|
return tracker;
|
2020-06-10 13:49:16 +00:00
|
|
|
}
|
|
|
|
}
|