refactoring

This commit is contained in:
Henry Jameson 2022-08-04 17:20:11 +03:00
parent 6c0a6ff8b0
commit 9c00610d00

View file

@ -1,15 +1,14 @@
import { toRaw } from 'vue' import { toRaw } from 'vue'
import { isEqual } from 'lodash'
const VERSION = 1 export const VERSION = 1
const NEW_USER_DATE = new Date('04-08-2022') // date of writing this, basically export const NEW_USER_DATE = new Date('04-08-2022') // date of writing this, basically
const COMMAND_TRIM_FLAGS = 1000 export const COMMAND_TRIM_FLAGS = 1000
const COMMAND_TRIM_FLAGS_AND_RESET = 1001 export const COMMAND_TRIM_FLAGS_AND_RESET = 1001
const defaultState = { const defaultState = {
// last timestamp // do we need to update data on server?
timestamp: 0,
// need to update server
dirty: false, dirty: false,
// storage of flags - stuff that can only be set and incremented // storage of flags - stuff that can only be set and incremented
flagStorage: { flagStorage: {
@ -33,78 +32,70 @@ const newUserFlags = {
updateCounter: 1 // new users don't need to see update notification updateCounter: 1 // new users don't need to see update notification
} }
const serverSideStorage = { const _wrapData = (data) => ({
state: { ...data,
...defaultState
},
mutations: {
setServerSideStorage (state, userData) {
const live = userData.storage
const userNew = userData.created_at > NEW_USER_DATE
const flagsTemplate = userNew ? newUserFlags : defaultState.defaultState
state.raw = live
console.log(1111, live._timestamp)
let recent = null
const cache = state.cache || {}
const cacheValid = cache._timestamp > 0 && cache._version > 0
const liveValid = live._timestamp > 0 && live._version > 0
if (!liveValid) {
state.dirty = true
console.debug('Nothing valid stored on server, assuming cache to be source of truth')
if (cacheValid) {
recent = cache
} else {
console.debug(`Local cache is empty, initializing for ${userNew ? 'new' : 'existing'} user`)
recent = {
_timestamp: Date.now(), _timestamp: Date.now(),
_version: VERSION, _version: VERSION
flagStorage: { ...flagsTemplate } })
}
} export const _checkValidity = (data) => data._timestamp > 0 && data._version > 0
export const _getRecentData = (cache, live) => {
const result = { recent: null, stale: null, needUpload: false }
const cacheValid = _checkValidity(cache || {})
const liveValid = _checkValidity(live || {})
if (!liveValid) {
result.needUpload = true
console.debug('Nothing valid stored on server, assuming cache to be source of truth')
result.recent = cache
result.stale = live
} else if (!cacheValid) { } else if (!cacheValid) {
console.debug('Valid storage on server found, no local cache found, using live as source of truth') console.debug('Valid storage on server found, no local cache found, using live as source of truth')
recent = live result.recent = live
result.stale = cache
} else { } else {
console.debug('Both sources have valid data, figuring things out...') console.debug('Both sources have valid data, figuring things out...')
console.log(live._timestamp, cache._timestamp) console.log(live._timestamp, cache._timestamp)
if (live._timestamp === cache._timestamp && live._version === cache._version) { if (live._timestamp === cache._timestamp && live._version === cache._version) {
console.debug('Same version/timestamp on both source, source of truth irrelevant') console.debug('Same version/timestamp on both source, source of truth irrelevant')
recent = cache result.recent = cache
result.stale = live
} else { } else {
state.dirty = true
console.debug('Different timestamp, figuring out which one is more recent') console.debug('Different timestamp, figuring out which one is more recent')
let stale
if (live._timestamp < cache._timestamp) { if (live._timestamp < cache._timestamp) {
recent = cache result.recent = cache
stale = live result.stale = live
} else { } else {
recent = live result.recent = live
stale = cache result.stale = cache
} }
}
}
return result
}
// Merge the flags export const _getAllFlags = (recent = {}, stale = {}) => {
console.debug('Merging the flags...') return Array.from(new Set([
recent.flagStorage = recent.flagStorage || { ...flagsTemplate } ...Object.keys(toRaw(recent.flagStorage || {})),
stale.flagStorage = stale.flagStorage || { ...flagsTemplate } ...Object.keys(toRaw(stale.flagStorage || {}))
const allFlags = Array.from(new Set([
...Object.keys(toRaw(recent.flagStorage)),
...Object.keys(toRaw(stale.flagStorage))
])) ]))
}
const totalFlags = Object.fromEntries(allFlags.map(flag => { export const _mergeFlags = (recent, stale, allFlagKeys) => {
return Object.fromEntries(allFlagKeys.map(flag => {
const recentFlag = recent.flagStorage[flag] const recentFlag = recent.flagStorage[flag]
const staleFlag = stale.flagStorage[flag] const staleFlag = stale.flagStorage[flag]
// use flag that is of higher value // use flag that is of higher value
return [flag, recentFlag > staleFlag ? recentFlag : staleFlag] return [flag, recentFlag > staleFlag ? recentFlag : staleFlag]
})) }))
}
console.debug('AAA', totalFlags) export const _resetFlags = (totalFlags, allFlagKeys) => {
// flag reset functionality // flag reset functionality
if (totalFlags.reset >= COMMAND_TRIM_FLAGS && totalFlags.reset <= COMMAND_TRIM_FLAGS_AND_RESET) { if (totalFlags.reset >= COMMAND_TRIM_FLAGS && totalFlags.reset <= COMMAND_TRIM_FLAGS_AND_RESET) {
console.debug('Received command to trim the flags') console.debug('Received command to trim the flags')
const knownKeys = new Set(Object.keys(defaultState.flagStorage)) const knownKeys = new Set(Object.keys(defaultState.flagStorage))
allFlags.forEach(flag => { allFlagKeys.forEach(flag => {
if (!knownKeys.has(flag)) { if (!knownKeys.has(flag)) {
delete totalFlags[flag] delete totalFlags[flag]
} }
@ -112,21 +103,93 @@ const serverSideStorage = {
if (totalFlags.reset === COMMAND_TRIM_FLAGS_AND_RESET) { if (totalFlags.reset === COMMAND_TRIM_FLAGS_AND_RESET) {
// 1001 - and reset everything to 0 // 1001 - and reset everything to 0
console.debug('Received command to reset the flags') console.debug('Received command to reset the flags')
allFlags.forEach(flag => { totalFlags[flag] = 0 }) allFlagKeys.forEach(flag => { totalFlags[flag] = 0 })
} else { } else {
// reset the reset 0 // reset the reset 0
totalFlags.reset = 0 totalFlags.reset = 0
} }
} else if (totalFlags.reset > 0 && totalFlags.reset < 9000) { } else if (totalFlags.reset > 0 && totalFlags.reset < 9000) {
console.debug('Received command to reset the flags') console.debug('Received command to reset the flags')
allFlags.forEach(flag => { totalFlags[flag] = 0 }) allFlagKeys.forEach(flag => { totalFlags[flag] = 0 })
// for good luck // for good luck
totalFlags.reset = 0 totalFlags.reset = 0
} }
console.log('AAAA', totalFlags) }
state.cache.flagStorage = totalFlags
export const _doMigrations = (cache) => {
if (cache._version < VERSION) {
console.debug('Local cached data has older version, seeing if there any migrations that can be applied')
// no migrations right now since we only have one version
console.debug('No migrations found')
}
if (cache._version > VERSION) {
console.debug('Local cached data has newer version, seeing if there any reverse migrations that can be applied')
// no reverse migrations right now but we leave a possibility of loading a hotpatch if need be
if (window._PLEROMA_HOTPATCH) {
if (window._PLEROMA_HOTPATCH.reverseMigrations) {
console.debug('Found hotpatch migration, applying')
return window._PLEROMA_HOTPATCH.reverseMigrations('serverSideStorage', { from: cache._version, to: VERSION }, cache)
} }
} }
}
return cache
}
const serverSideStorage = {
state: {
...defaultState
},
mutations: {
setServerSideStorage (state, userData) {
const live = userData.storage
state.raw = live
let cache = state.cache
cache = _doMigrations(cache)
let { recent, stale, needsUpload } = _getRecentData(cache, live)
const userNew = userData.created_at > NEW_USER_DATE
const flagsTemplate = userNew ? newUserFlags : defaultState.defaultState
let dirty = false
if (recent === null) {
console.debug(`Data is empty, initializing for ${userNew ? 'new' : 'existing'} user`)
recent = _wrapData({
flagStorage: { ...flagsTemplate }
})
}
if (!needsUpload && recent && stale) {
console.debug('Checking if data needs merging...')
// discarding timestamps and versions
const { _timestamp: _0, _version: _1, ...recentData } = recent
const { _timestamp: _2, _version: _3, ...staleData } = stale
dirty = !isEqual(recentData, staleData)
console.debug(`Data ${dirty ? 'needs' : 'doesn\'t need'} merging`)
}
const allFlagKeys = _getAllFlags(recent, stale)
let totalFlags
if (dirty) {
// Merge the flags
console.debug('Merging the flags...')
totalFlags = _mergeFlags(recent, stale, allFlagKeys)
} else {
totalFlags = recent.flagStorage
}
// This does side effects on totalFlags !!!
// only resets if needed (checks are inside)
_resetFlags(totalFlags, allFlagKeys)
recent.flagStorage = totalFlags
state.dirty = dirty || needsUpload
state.cache = recent state.cache = recent
state.flagStorage = state.cache.flagStorage state.flagStorage = state.cache.flagStorage
}, },
@ -137,15 +200,11 @@ const serverSideStorage = {
}, },
actions: { actions: {
pushServerSideStorage ({ state, rootState, commit }, { force = false } = {}) { pushServerSideStorage ({ state, rootState, commit }, { force = false } = {}) {
console.log('PUSH')
const needPush = state.dirty || force const needPush = state.dirty || force
if (!needPush) return if (!needPush) return
state.cache = { state.cache = _wrapData({
_timestamp: Date.now(),
_version: VERSION,
flagStorage: toRaw(state.flagStorage) flagStorage: toRaw(state.flagStorage)
} })
console.log('YES')
const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } } const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } }
rootState.api.backendInteractor rootState.api.backendInteractor
.updateProfile({ params }) .updateProfile({ params })