github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/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(
    22        'StatsTrackers need a fetch method, which should have an interface like window.fetch'
    23      );
    24    },
    25  
    26    append(/* frame */) {
    27      assert(
    28        'StatsTrackers need an append method, which takes the JSON response from a request to url as an argument'
    29      );
    30    },
    31  
    32    pause() {
    33      assert(
    34        'StatsTrackers need a pause method, which takes no arguments but adds a frame of data at the current timestamp with null as the value'
    35      );
    36    },
    37  
    38    frameMisses: 0,
    39  
    40    handleResponse(frame) {
    41      if (frame.error) {
    42        this.incrementProperty('frameMisses');
    43        if (this.frameMisses >= this.maxFrameMisses) {
    44          // Missing enough data consecutively is effectively a pause
    45          this.pause();
    46          this.set('frameMisses', 0);
    47        }
    48        return;
    49      } else {
    50        this.set('frameMisses', 0);
    51  
    52        // Only append non-error frames
    53        this.append(frame);
    54      }
    55    },
    56  
    57    // Uses EC as a form of debounce to prevent multiple
    58    // references to the same tracker from flooding the tracker,
    59    // but also avoiding the issue where different places where the
    60    // same tracker is used needs to coordinate.
    61    poll: task(function* () {
    62      // Interrupt any pause attempt
    63      this.signalPause.cancelAll();
    64  
    65      try {
    66        const url = this.url;
    67        assert('Url must be defined', url);
    68  
    69        yield this.fetch(url)
    70          .then(jsonWithDefault({ error: true }))
    71          .then((frame) => this.handleResponse(frame));
    72      } catch (error) {
    73        throw new Error(error);
    74      }
    75  
    76      yield timeout(Ember.testing ? 0 : 2000);
    77    }).drop(),
    78  
    79    signalPause: task(function* () {
    80      // wait 2 seconds
    81      yield timeout(Ember.testing ? 0 : 2000);
    82      // if no poll called in 2 seconds, pause
    83      this.pause();
    84    }).drop(),
    85  });