0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-24 22:52:40 +00:00
Files
homebrewery/client/homebrew/utils/versionHistory.js
2024-10-07 21:53:05 +13:00

159 lines
4.3 KiB
JavaScript

import * as IDB from 'idb-keyval/dist/index.js';
export const HISTORY_PREFIX = 'HOMEBREWERY-HISTORY';
export const HISTORY_SLOTS = 5;
// History values in minutes
const DEFAULT_HISTORY_SAVE_DELAYS = {
'0' : 0,
'1' : 2,
'2' : 10,
'3' : 60,
'4' : 12 * 60,
'5' : 2 * 24 * 60
};
const HB_DB = 'HOMEBREWERY-DB';
const HB_STORE = 'HISTORY';
const DEFAULT_GARBAGE_COLLECT_DELAY = 28 * 24 * 60;
let HISTORY_SAVE_DELAYS = DEFAULT_HISTORY_SAVE_DELAYS;
let GARBAGE_COLLECT_DELAY = DEFAULT_GARBAGE_COLLECT_DELAY;
function getKeyBySlot(brew, slot){
// Return a string representing the key for this brew and history slot
return `${HISTORY_PREFIX}-${brew.shareId}-${slot}`;
};
// function getVersionBySlot(brew, slot){
// // Read stored brew data
// // - If it exists, parse data to object
// // - If it doesn't exist, pass default object
// const key = getKeyBySlot(brew, slot);
// const storedVersion = IDB.get(key);
// const output = storedVersion ? storedVersion : { expireAt: '2000-01-01T00:00:00.000Z', shareId: brew.shareId, noData: true };
// return output;
// };
function parseBrewForStorage(brew, slot = 0) {
// Strip out unneeded object properties
// Returns an array of [ key, brew ]
const archiveBrew = {
title : brew.title,
text : brew.text,
style : brew.style,
version : brew.version,
shareId : brew.shareId,
savedAt : brew?.savedAt || new Date(),
expireAt : new Date()
};
if(global.config?.history?.HISTORY_SAVE_DELAYS){
HISTORY_SAVE_DELAYS = global.config?.history?.HISTORY_SAVE_DELAYS;
}
archiveBrew.expireAt.setMinutes(archiveBrew.expireAt.getMinutes() + HISTORY_SAVE_DELAYS[slot]);
const key = getKeyBySlot(brew, slot);
return [key, archiveBrew];
}
async function createHBStore(){
return await IDB.createStore(HB_DB, HB_STORE);
}
export async function historyCheck(brew){
if(!IDB) return false;
const historyExists = await IDB.keys(await createHBStore())
.then((keys)=>{
return [...keys].some((key)=>{
return key.startsWith(`${HISTORY_PREFIX}-${brew.shareId}`);
});
})
.catch(()=>{return false;});
return historyExists;
}
export async function loadHistory(brew){
const DEFAULT_HISTORY_ITEM = { expireAt: '2000-01-01T00:00:00.000Z', shareId: brew.shareId, noData: true };
const historyKeys = [];
// Create array of all history keys
for (let i = 1; i <= HISTORY_SLOTS; i++){
historyKeys.push(getKeyBySlot(brew, i));
};
const history = [];
// Load all keys from IDB at once
await IDB.getMany(historyKeys, await createHBStore())
.then((dataArray)=>{
return dataArray.forEach((data)=>{
history.push(data ?? DEFAULT_HISTORY_ITEM);
});
})
.catch(()=>{
historyKeys.forEach(()=>{
history.push(DEFAULT_HISTORY_ITEM);
});
});
return history;
}
export async function updateHistory(brew) {
const history = await loadHistory(brew);
// Walk each version position
for (let slot = HISTORY_SLOTS - 1; slot >= 0; slot--){
const storedVersion = history[slot];
// If slot has expired, update all lower slots and break
if(new Date() >= new Date(storedVersion.expireAt)){
// Create array of arrays : [ [key1, value1], [key2, value2], ..., [keyN, valueN] ]
// to pass to IDB.setMany
const historyUpdate = [];
for (let updateSlot = slot; updateSlot > 0; updateSlot--){
// Move data from updateSlot to updateSlot + 1
if(!history[updateSlot - 1]?.noData) {
historyUpdate.push(parseBrewForStorage(history[updateSlot - 1], updateSlot + 1));
}
};
// Update the most recent brew
historyUpdate.push(parseBrewForStorage(brew, 1));
IDB.setMany(historyUpdate, await createHBStore());
// Break out of data checks because we found an expired value
break;
}
};
};
export async function versionHistoryGarbageCollection(){
if(global.config?.history?.GARBAGE_COLLECT_DELAY != GARBAGE_COLLECT_DELAY) GARBAGE_COLLECT_DELAY = global.config?.history?.GARBAGE_COLLECT_DELAY;
await IDB.entries(await createHBStore())
.then((entries)=>{
entries.forEach((entry)=>{
const key = entry[0];
const value = entry[1];
if(key.startsWith(`${HISTORY_PREFIX}`)) {
const collectAt = new Date(value.savedAt);
collectAt.setMinutes(collectAt.getMinutes() + GARBAGE_COLLECT_DELAY);
if(new Date() > collectAt){
IDB.del(key);
};
}
});
});
};