github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/utils/classes/abstract-stats-tracker.js (about) 1 import Ember from 'ember'; 2 import Mixin from '@ember/object/mixin'; 3 import { assert } from '@ember/debug'; 4 import { task, timeout } from 'ember-concurrency'; 5 import jsonWithDefault from 'nomad-ui/utils/json-with-default'; 6 7 // eslint-disable-next-line ember/no-new-mixins 8 export default Mixin.create({ 9 url: '', 10 11 // The max number of data points tracked. Once the max is reached, 12 // data points at the head of the list are removed in favor of new 13 // data appended at the tail 14 bufferSize: 500, 15 16 // The number of consecutive request failures that can occur before an 17 // empty frame is appended 18 maxFrameMisses: 5, 19 20 fetch() { 21 assert('StatsTrackers need a fetch method, which should have an interface like window.fetch'); 22 }, 23 24 append(/* frame */) { 25 assert( 26 'StatsTrackers need an append method, which takes the JSON response from a request to url as an argument' 27 ); 28 }, 29 30 pause() { 31 assert( 32 'StatsTrackers need a pause method, which takes no arguments but adds a frame of data at the current timestamp with null as the value' 33 ); 34 }, 35 36 frameMisses: 0, 37 38 handleResponse(frame) { 39 if (frame.error) { 40 this.incrementProperty('frameMisses'); 41 if (this.frameMisses >= this.maxFrameMisses) { 42 // Missing enough data consecutively is effectively a pause 43 this.pause(); 44 this.set('frameMisses', 0); 45 } 46 return; 47 } else { 48 this.set('frameMisses', 0); 49 50 // Only append non-error frames 51 this.append(frame); 52 } 53 }, 54 55 // Uses EC as a form of debounce to prevent multiple 56 // references to the same tracker from flooding the tracker, 57 // but also avoiding the issue where different places where the 58 // same tracker is used needs to coordinate. 59 poll: task(function*() { 60 // Interrupt any pause attempt 61 this.signalPause.cancelAll(); 62 63 try { 64 const url = this.url; 65 assert('Url must be defined', url); 66 67 yield this.fetch(url) 68 .then(jsonWithDefault({ error: true })) 69 .then(frame => this.handleResponse(frame)); 70 } catch (error) { 71 throw new Error(error); 72 } 73 74 yield timeout(Ember.testing ? 0 : 2000); 75 }).drop(), 76 77 signalPause: task(function*() { 78 // wait 2 seconds 79 yield timeout(Ember.testing ? 0 : 2000); 80 // if no poll called in 2 seconds, pause 81 this.pause(); 82 }).drop(), 83 });