github.com/hernad/nomad@v1.6.112/ui/app/services/stats-trackers-registry.js (about) 1 /** 2 * Copyright (c) HashiCorp, Inc. 3 * SPDX-License-Identifier: MPL-2.0 4 */ 5 6 import { computed } from '@ember/object'; 7 import Service, { inject as service } from '@ember/service'; 8 import { LRUMap } from 'lru_map'; 9 import NodeStatsTracker from 'nomad-ui/utils/classes/node-stats-tracker'; 10 import AllocationStatsTracker from 'nomad-ui/utils/classes/allocation-stats-tracker'; 11 12 // An unbounded number of stat trackers is a great way to gobble up all the memory 13 // on a machine. This max number is unscientific, but aims to balance losing 14 // stat trackers a user is likely to return to with preventing gc from freeing 15 // memory occupied by stat trackers a user is likely to no longer care about 16 const MAX_STAT_TRACKERS = 10; 17 let registry; 18 19 const exists = (tracker, prop) => 20 tracker.get(prop) && 21 !tracker.get(prop).isDestroyed && 22 !tracker.get(prop).isDestroying; 23 24 export default class StatsTrackersRegistryService extends Service { 25 @service token; 26 27 constructor() { 28 super(...arguments); 29 30 // The LRUMap limits the number of trackers tracked by making room for 31 // new entries beyond the limit by removing the least recently used entry. 32 registry = new LRUMap(MAX_STAT_TRACKERS); 33 } 34 35 // A read-only way of getting a reference to the registry. 36 // Since this could be overwritten by a bad actor, it isn't 37 // used in getTracker 38 @computed 39 get registryRef() { 40 return registry; 41 } 42 43 getTracker(resource) { 44 if (!resource) return; 45 46 const type = resource && resource.constructor.modelName; 47 const key = `${type}:${resource.get('id')}`; 48 const Constructor = 49 type === 'node' ? NodeStatsTracker : AllocationStatsTracker; 50 const resourceProp = type === 'node' ? 'node' : 'allocation'; 51 52 const cachedTracker = registry.get(key); 53 if (cachedTracker) { 54 // It's possible for the resource on a cachedTracker to have been 55 // deleted. Rebind it if that's the case. 56 if (!exists(cachedTracker, resourceProp)) 57 cachedTracker.set(resourceProp, resource); 58 return cachedTracker; 59 } 60 61 const tracker = Constructor.create({ 62 fetch: (url) => this.token.authorizedRequest(url), 63 [resourceProp]: resource, 64 }); 65 66 registry.set(key, tracker); 67 68 return tracker; 69 } 70 }