1cca7abcab
This is extracted from #8094, where I have run into some snags. Since these ESLint fixes aren’t actually connected to the Ember 3.16 update but involve changes to many files, we might as well address them separately. Where possible I fixed the problems but in cases where a fix seemed too involved, I added per-line or -file exceptions.
84 lines
2.3 KiB
JavaScript
84 lines
2.3 KiB
JavaScript
import Ember from 'ember';
|
|
import Mixin from '@ember/object/mixin';
|
|
import { assert } from '@ember/debug';
|
|
import { task, timeout } from 'ember-concurrency';
|
|
import jsonWithDefault from 'nomad-ui/utils/json-with-default';
|
|
|
|
// eslint-disable-next-line ember/no-new-mixins
|
|
export default Mixin.create({
|
|
url: '',
|
|
|
|
// The max number of data points tracked. Once the max is reached,
|
|
// data points at the head of the list are removed in favor of new
|
|
// data appended at the tail
|
|
bufferSize: 500,
|
|
|
|
// The number of consecutive request failures that can occur before an
|
|
// empty frame is appended
|
|
maxFrameMisses: 5,
|
|
|
|
fetch() {
|
|
assert('StatsTrackers need a fetch method, which should have an interface like window.fetch');
|
|
},
|
|
|
|
append(/* frame */) {
|
|
assert(
|
|
'StatsTrackers need an append method, which takes the JSON response from a request to url as an argument'
|
|
);
|
|
},
|
|
|
|
pause() {
|
|
assert(
|
|
'StatsTrackers need a pause method, which takes no arguments but adds a frame of data at the current timestamp with null as the value'
|
|
);
|
|
},
|
|
|
|
frameMisses: 0,
|
|
|
|
handleResponse(frame) {
|
|
if (frame.error) {
|
|
this.incrementProperty('frameMisses');
|
|
if (this.frameMisses >= this.maxFrameMisses) {
|
|
// Missing enough data consecutively is effectively a pause
|
|
this.pause();
|
|
this.set('frameMisses', 0);
|
|
}
|
|
return;
|
|
} else {
|
|
this.set('frameMisses', 0);
|
|
|
|
// Only append non-error frames
|
|
this.append(frame);
|
|
}
|
|
},
|
|
|
|
// Uses EC as a form of debounce to prevent multiple
|
|
// references to the same tracker from flooding the tracker,
|
|
// but also avoiding the issue where different places where the
|
|
// same tracker is used needs to coordinate.
|
|
poll: task(function*() {
|
|
// Interrupt any pause attempt
|
|
this.signalPause.cancelAll();
|
|
|
|
try {
|
|
const url = this.url;
|
|
assert('Url must be defined', url);
|
|
|
|
yield this.fetch(url)
|
|
.then(jsonWithDefault({ error: true }))
|
|
.then(frame => this.handleResponse(frame));
|
|
} catch (error) {
|
|
throw new Error(error);
|
|
}
|
|
|
|
yield timeout(Ember.testing ? 0 : 2000);
|
|
}).drop(),
|
|
|
|
signalPause: task(function*() {
|
|
// wait 2 seconds
|
|
yield timeout(Ember.testing ? 0 : 2000);
|
|
// if no poll called in 2 seconds, pause
|
|
this.pause();
|
|
}).drop(),
|
|
});
|