Skip to content

Commit

Permalink
Make Beholder be gentler on HTTP server (#1075)
Browse files Browse the repository at this point in the history
- Navigating away from Beholder tab will now abort XHRs and clear timers.
- The "FPS" timeout is now throttled by how quickly the web server responds.
- Missing semicolons were added.
  • Loading branch information
jart authored and nfelt committed Mar 27, 2018
1 parent d3a6974 commit b22d92e
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@
value="{{_FPS}}"
type="number"
step="1"
min="0"
min="1"
max="30"
pin="true"
disabled="[[_controls_disabled]]">
Expand Down Expand Up @@ -483,6 +483,7 @@ <h3>No Beholder data was found.</h3>
tf_tensorboard.registerDashboard({
plugin: 'beholder',
elementName: 'tf-beholder-dashboard',
shouldRemoveDom: true,
});
</script>
</dom-module>
Original file line number Diff line number Diff line change
Expand Up @@ -49,39 +49,81 @@
"use strict";
(function() {

const INFO_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/section-info')
const INFO_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/section-info');

Polymer({
is: "tf-beholder-info",
properties: {
_requestManager: {
type: Object,
value: () => new tf_backend.RequestManager(),
fps: { // Not actually FPS!
type: Number,
value: 10,
},

xhrTimeout: {
type: Number,
value: 10000,
},

items: {
type: Array,
value: [{name:'Loading...'}],
},

_xhr: Object,
_timer: Object,
},

_reloaditems() {
window.setTimeout(function(){
this._requestManager.request(INFO_ROUTE).then(function(response){
this.splice('items', 0)
attached() {
this._load();
},

for (var item of response) {
this.push('items', item)
}
}.bind(this))
detached() {
this._clear();
},

_load() {
this._clear();
this._xhr = new XMLHttpRequest();
this._xhr.open('GET', INFO_ROUTE, true);
this._xhr.timeout = this.xhrTimeout;
this._xhr.onload = this._onLoad.bind(this);
this._xhr.onerror = this._retry.bind(this, this._getSleep());
this._xhr.ontimeout = this._retry.bind(this, 1);
this._xhr.send(null);
},

_onLoad() {
if (this._xhr.status == 200) {
const response = JSON.parse(this._xhr.responseText);
this.splice('items', 0);
for (var item of response) {
this.push('items', item);
}
}
this._retry(this._getSleep());
},

_retry(delay) {
this._timer = window.setTimeout(this._load.bind(this), delay);
},

_getSleep() {
return 1000 / (this.fps === 0 ? 1 : this.fps);
},

this._reloaditems()
}.bind(this), 1000/(this.fps === 0 ? 1 : this.fps))
_clear() {
if (this._timer) {
window.clearTimeout(this._timer);
this._timer = null;
}
if (this._xhr) {
if (this._xhr.readyState < 4 /* DONE */) {
this._xhr.abort();
}
this._xhr = null;
}
},

ready() {
this._reloaditems()
}
});
})();
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<template>

<div id="container">
<img id="video" src='[[_imageURL]]'></img>
<img id="video" src="[[_imageURL]]">
</div>

<style>
Expand All @@ -37,50 +37,82 @@
"use strict";
(function() {

const FEED_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/beholder-frame')
const PING_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/ping')

var connectionFailed = false
const BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
const FEED_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/beholder-frame');
const PING_ROUTE = tf_backend.getRouter().pluginRoute('beholder', '/ping');

Polymer({
is: "tf-beholder-video",
properties: {
_requestManager: {
type: Object,
value: () => new tf_backend.RequestManager(),
pingSleep: {
type: Number,
value: 1000,
},

xhrTimeout: {
type: Number,
value: 2500,
},

_imageURL: {
type: String,
value: FEED_ROUTE
}
value: BLANK,
},

_xhr: Object,
_timer: Object,
_isDead: Boolean,
},

attached() {
this.set('_imageURL', FEED_ROUTE);
this._ping();
},

ready() {
// Periodically check the connection, restart if needed.
window.setInterval(function(){
this._requestManager.request(PING_ROUTE).then(
function(response){
if (connectionFailed) {
this.restartVideo()
}
connectionFailed = false
}.bind(this),
function(error){
connectionFailed = true
}.bind(this))
}.bind(this), 1000)
detached() {
this._clear();
this.set('_imageURL', BLANK);
},

restartVideo() {
var newImage = document.createElement('img')
newImage.src = FEED_ROUTE + '?t=' + new Date().getTime()
newImage.id = 'video'
newImage.className = 'style-scope beholder-video'
this.$.container.appendChild(newImage)
_ping() {
this._clear();
this._xhr = new XMLHttpRequest();
this._xhr.open('GET', PING_ROUTE, true);
this._xhr.timeout = this.xhrTimeout;
this._xhr.onload = this._onPingLoad.bind(this);
this._xhr.onerror = this._onPing.bind(this, false, this.pingSleep);
this._xhr.ontimeout = this._onPing.bind(this, false, 1);
this._xhr.send(null);
},

_onPingLoad() {
if (this._xhr.status == 200) {
const response = JSON.parse(this._xhr.responseText);
this._onPing(response['status'] == 'alive', this.pingSleep);
return;
}
this._onPing(false, this.pingSleep);
},

_onPing(isAlive, retryMs) {
if (isAlive && this._isDead) {
this.set('_imageURL', FEED_ROUTE + '?t=' + new Date().getTime());
}
this._isDead = !isAlive;
this._timer = window.setTimeout(this._ping.bind(this), retryMs);
},

this.$.container.removeChild(this.$.video)
this.$.video = newImage
_clear() {
if (this._timer) {
window.clearTimeout(this._timer);
this._timer = null;
}
if (this._xhr) {
if (this._xhr.readyState < 4 /* DONE */) {
this._xhr.abort();
}
this._xhr = null;
}
},

});
Expand Down

0 comments on commit b22d92e

Please sign in to comment.