homecontrol-control-base/StateUpdateManager.js

92 lines
2.2 KiB
JavaScript

/**
* Optional utility classes can use when states need to be partially updated
*/
class StateUpdateManager {
constructor(initialState) {
this._highestConfirmedId = 0;
this._currentId = 0;
this._nextId = 1;
this._updateHistory = [{ id: 0, state: initialState }];
}
get highestConfirmedId() {
return this._highestConfirmedId;
}
/**
* Returns the latest (unconfirmed state)
*/
get state() {
return this._updateHistory.find(su => su.id == this._currentId).state;
}
/**
* Returns the latest confirmed state
*/
get confirmedState() {
return this._updateHistory.find(su => su.id == this._highestConfirmedId).state;
}
/**
* Registers the potential update of the state
* @param {Object} state
* @returns {Number} id which is used to confirm or reject the update later
*/
registerUpdate(state) {
let updateId = this._nextId;
this._nextId += 1;
this._currentId = updateId; // until rejected, this is the most recent id
this._updateHistory.push({
id: updateId,
state
});
return updateId;
}
/**
* Add a new state and instantly confirm it
* @param {Object} state
*/
insertConfirmedState(state) {
let suid = this.registerUpdate();
this.confirmUpdate(suid);
}
/**
* Confirm the update with the specified id
* Also remove all updates with lower ids, as these are now confirmed to be outdated
* @param {Number} uid
*/
confirmUpdate(uid) {
if (uid < this._highestConfirmedId) return; // already outdated
this._highestConfirmedId = uid;
// remove history entries with lower ids
this._updateHistory = this._updateHistory.filter(su => su.id >= this._highestConfirmedId);
}
/**
* Rejects the update with the specified id
* If the id is outdated it is ignored
* Otherwise it is thrown out, and the currentId decremented if required
* @param {Number} uid
*/
rejectUpdate(uid) {
if (uid < this._highestConfirmedId) return; // already outdated
// remove element from history
this._updateHistory = this._updateHistory.filter(su => su.id != uid);
if (this._currentId == uid) {
// set current id to highest known uid
this._currentId = this._updateHistory.reduce((highest, su) => (su.id > highest) ? su.id : highest, -1);
}
}
}
module.exports = StateUpdateManager;