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