github.com/hernad/nomad@v1.6.112/ui/app/utils/classes/abstract-stats-tracker.js (about)

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