From f0208c0a2407ab6ca1f50900f11cedefd64b07bc Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Mon, 17 Sep 2018 15:58:28 -0700 Subject: [PATCH] Add request throttling to the abstract stats tracker This is the best of three options 1. Users of stats trackers control polling (old method) 2. Stat tracker is stateful and has start/stop methods (like logging) 3. Stat trackers blindly throttle requests This is the best option because it means N number of concurrent users of a stats tracker can request polling without inundating the tracker with redundant frames (or the network with redundant requests), but they also don't have to coordinate amongst themselves to determine what state a tracker should be in. --- ui/app/components/primary-metric.js | 4 ++-- ui/app/utils/classes/abstract-stats-tracker.js | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ui/app/components/primary-metric.js b/ui/app/components/primary-metric.js index a46a75461..7aae5f33d 100644 --- a/ui/app/components/primary-metric.js +++ b/ui/app/components/primary-metric.js @@ -79,8 +79,8 @@ export default Component.extend({ poller: task(function*() { do { - yield this.get('tracker').poll(); - yield timeout(2000); + yield this.get('tracker.poll').perform(); + yield timeout(10); } while (!Ember.testing); }), diff --git a/ui/app/utils/classes/abstract-stats-tracker.js b/ui/app/utils/classes/abstract-stats-tracker.js index 825851d22..f730936e0 100644 --- a/ui/app/utils/classes/abstract-stats-tracker.js +++ b/ui/app/utils/classes/abstract-stats-tracker.js @@ -1,5 +1,6 @@ import Mixin from '@ember/object/mixin'; import { assert } from '@ember/debug'; +import { task, timeout } from 'ember-concurrency'; export default Mixin.create({ url: '', @@ -16,12 +17,18 @@ export default Mixin.create({ ); }, - poll() { + // 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*() { const url = this.get('url'); assert('Url must be defined', url); - return this.get('fetch')(url) + yield this.get('fetch')(url) .then(res => res.json()) .then(frame => this.append(frame)); - }, + + yield timeout(2000); + }).drop(), });