Only send monitor update on change

This commit is contained in:
DD Liu 2017-05-19 12:28:05 -04:00
parent e9c48d250b
commit 9645a513b1
2 changed files with 85 additions and 9 deletions

View file

@ -2,6 +2,7 @@ const EventEmitter = require('events');
const Sequencer = require('./sequencer');
const Blocks = require('./blocks');
const Thread = require('./thread');
const {Map} = require('immutable');
// Virtual I/O devices.
const Clock = require('../io/clock');
@ -114,7 +115,12 @@ class Runtime extends EventEmitter {
/**
* List of all monitors.
*/
this._monitorState = {};
this._monitorState = Map({});
/**
* Monitor state from last tick
*/
this._prevMonitorState = Map({});
/**
* Whether the project is in "turbo mode."
@ -699,10 +705,10 @@ class Runtime extends EventEmitter {
this._refreshTargets = false;
}
// @todo(vm#570) only emit if monitors has changed since last time.
this.emit(Runtime.MONITORS_UPDATE,
Object.keys(this._monitorState).map(key => this._monitorState[key])
);
if (!this._prevMonitorState.equals(this._monitorState)) {
this.emit(Runtime.MONITORS_UPDATE, this._monitorState.toArray());
}
this._prevMonitorState = this._monitorState;
}
/**
@ -877,7 +883,7 @@ class Runtime extends EventEmitter {
* @param {!object} monitor Monitor to add.
*/
requestAddMonitor (monitor) {
this._monitorState[monitor.id] = monitor;
this._monitorState = this._monitorState.set(monitor.id, monitor);
}
/**
@ -886,18 +892,42 @@ class Runtime extends EventEmitter {
* @param {!object} monitor Monitor to update.
*/
requestUpdateMonitor (monitor) {
if (this._monitorState.hasOwnProperty(monitor.id)) {
this._monitorState[monitor.id] = Object.assign({}, this._monitorState[monitor.id], monitor);
if (this._monitorState.has(monitor.id) &&
this._monitorWouldChange(this._monitorState.get(monitor.id), monitor)) {
this._monitorState =
this._monitorState.set(monitor.id, Object.assign({}, this._monitorState.get(monitor.id), monitor));
}
}
/**
* Whether or not the monitor would change when the new state is applied. New state has its properties
* applied to the current state, it does not completely overwrite the current state. For this to return
* accurately, the changes being applied should be on primitive types, otherwise it may false-positive.
* @param {!object} currentMonitorState the state of a monitor, the values in this._monitorState
* @param {!object} newMonitorDelta the state to be applied to a monitor. The IDs of current and new monitor
* should match.
* @return {boolean} whether the new state, when applied to the current state, would change the current state.
*/
_monitorWouldChange (currentMonitorState, newMonitorDelta) {
for (const prop in newMonitorDelta) {
if (currentMonitorState.hasOwnProperty(prop)) {
// Strict equals to check if properties change; switch this to deep equals if
// we expect monitors to have changing state that is not primative.
if (currentMonitorState[prop] !== newMonitorDelta[prop]) return true;
} else {
return true; // The new state would add a new property to the monitor
}
}
return false;
}
/**
* Removes a monitor from the state. Does nothing if the monitor already does
* not exist in the state.
* @param {!object} monitorId ID of the monitor to remove.
*/
requestRemoveMonitor (monitorId) {
delete this._monitorState[monitorId];
this._monitorState = this._monitorState.delete(monitorId);
}
/**

View file

@ -10,3 +10,49 @@ test('spec', t => {
t.end();
});
test('monitorWouldChange_false', t => {
const r = new Runtime();
const currentMonitorState = {
id: 'xklj4#!',
category: 'data',
label: 'turtle whereabouts',
value: '25',
x: 0,
y: 0
};
const newMonitorDelta = {
id: 'xklj4#!',
value: String(25)
};
t.equals(false, r._monitorWouldChange(currentMonitorState, newMonitorDelta));
t.end();
});
test('monitorWouldChange_true', t => {
const r = new Runtime();
const currentMonitorState = {
id: 'xklj4#!',
category: 'data',
label: 'turtle whereabouts',
value: '25',
x: 0,
y: 0
};
// Value change
let newMonitorDelta = {
id: 'xklj4#!',
value: String(24)
};
t.equal(true, r._monitorWouldChange(currentMonitorState, newMonitorDelta));
// Prop change
newMonitorDelta = {
id: 'xklj4#!',
moose: 7
};
t.equal(true, r._monitorWouldChange(currentMonitorState, newMonitorDelta));
t.end();
});