github.com/manicqin/nomad@v0.9.5/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  });