92 lines
2.2 KiB
JavaScript
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; |