/** * 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;