refactoring
This commit is contained in:
parent
6c0a6ff8b0
commit
9c00610d00
@ -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,6 +32,113 @@ 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 _wrapData = (data) => ({
|
||||||
|
...data,
|
||||||
|
_timestamp: Date.now(),
|
||||||
|
_version: VERSION
|
||||||
|
})
|
||||||
|
|
||||||
|
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) {
|
||||||
|
console.debug('Valid storage on server found, no local cache found, using live as source of truth')
|
||||||
|
result.recent = live
|
||||||
|
result.stale = cache
|
||||||
|
} else {
|
||||||
|
console.debug('Both sources have valid data, figuring things out...')
|
||||||
|
console.log(live._timestamp, cache._timestamp)
|
||||||
|
if (live._timestamp === cache._timestamp && live._version === cache._version) {
|
||||||
|
console.debug('Same version/timestamp on both source, source of truth irrelevant')
|
||||||
|
result.recent = cache
|
||||||
|
result.stale = live
|
||||||
|
} else {
|
||||||
|
console.debug('Different timestamp, figuring out which one is more recent')
|
||||||
|
if (live._timestamp < cache._timestamp) {
|
||||||
|
result.recent = cache
|
||||||
|
result.stale = live
|
||||||
|
} else {
|
||||||
|
result.recent = live
|
||||||
|
result.stale = cache
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export const _getAllFlags = (recent = {}, stale = {}) => {
|
||||||
|
return Array.from(new Set([
|
||||||
|
...Object.keys(toRaw(recent.flagStorage || {})),
|
||||||
|
...Object.keys(toRaw(stale.flagStorage || {}))
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const _mergeFlags = (recent, stale, allFlagKeys) => {
|
||||||
|
return Object.fromEntries(allFlagKeys.map(flag => {
|
||||||
|
const recentFlag = recent.flagStorage[flag]
|
||||||
|
const staleFlag = stale.flagStorage[flag]
|
||||||
|
// use flag that is of higher value
|
||||||
|
return [flag, recentFlag > staleFlag ? recentFlag : staleFlag]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const _resetFlags = (totalFlags, allFlagKeys) => {
|
||||||
|
// flag reset functionality
|
||||||
|
if (totalFlags.reset >= COMMAND_TRIM_FLAGS && totalFlags.reset <= COMMAND_TRIM_FLAGS_AND_RESET) {
|
||||||
|
console.debug('Received command to trim the flags')
|
||||||
|
const knownKeys = new Set(Object.keys(defaultState.flagStorage))
|
||||||
|
allFlagKeys.forEach(flag => {
|
||||||
|
if (!knownKeys.has(flag)) {
|
||||||
|
delete totalFlags[flag]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (totalFlags.reset === COMMAND_TRIM_FLAGS_AND_RESET) {
|
||||||
|
// 1001 - and reset everything to 0
|
||||||
|
console.debug('Received command to reset the flags')
|
||||||
|
allFlagKeys.forEach(flag => { totalFlags[flag] = 0 })
|
||||||
|
} else {
|
||||||
|
// reset the reset 0
|
||||||
|
totalFlags.reset = 0
|
||||||
|
}
|
||||||
|
} else if (totalFlags.reset > 0 && totalFlags.reset < 9000) {
|
||||||
|
console.debug('Received command to reset the flags')
|
||||||
|
allFlagKeys.forEach(flag => { totalFlags[flag] = 0 })
|
||||||
|
// for good luck
|
||||||
|
totalFlags.reset = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {
|
const serverSideStorage = {
|
||||||
state: {
|
state: {
|
||||||
...defaultState
|
...defaultState
|
||||||
@ -40,93 +146,50 @@ const serverSideStorage = {
|
|||||||
mutations: {
|
mutations: {
|
||||||
setServerSideStorage (state, userData) {
|
setServerSideStorage (state, userData) {
|
||||||
const live = userData.storage
|
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 userNew = userData.created_at > NEW_USER_DATE
|
||||||
const flagsTemplate = userNew ? newUserFlags : defaultState.defaultState
|
const flagsTemplate = userNew ? newUserFlags : defaultState.defaultState
|
||||||
state.raw = live
|
let dirty = false
|
||||||
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 = {
|
if (recent === null) {
|
||||||
_timestamp: Date.now(),
|
console.debug(`Data is empty, initializing for ${userNew ? 'new' : 'existing'} user`)
|
||||||
_version: VERSION,
|
recent = _wrapData({
|
||||||
flagStorage: { ...flagsTemplate }
|
flagStorage: { ...flagsTemplate }
|
||||||
}
|
})
|
||||||
}
|
|
||||||
} else if (!cacheValid) {
|
|
||||||
console.debug('Valid storage on server found, no local cache found, using live as source of truth')
|
|
||||||
recent = live
|
|
||||||
} else {
|
|
||||||
console.debug('Both sources have valid data, figuring things out...')
|
|
||||||
console.log(live._timestamp, cache._timestamp)
|
|
||||||
if (live._timestamp === cache._timestamp && live._version === cache._version) {
|
|
||||||
console.debug('Same version/timestamp on both source, source of truth irrelevant')
|
|
||||||
recent = cache
|
|
||||||
} else {
|
|
||||||
state.dirty = true
|
|
||||||
console.debug('Different timestamp, figuring out which one is more recent')
|
|
||||||
let stale
|
|
||||||
if (live._timestamp < cache._timestamp) {
|
|
||||||
recent = cache
|
|
||||||
stale = live
|
|
||||||
} else {
|
|
||||||
recent = live
|
|
||||||
stale = cache
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge the flags
|
|
||||||
console.debug('Merging the flags...')
|
|
||||||
recent.flagStorage = recent.flagStorage || { ...flagsTemplate }
|
|
||||||
stale.flagStorage = stale.flagStorage || { ...flagsTemplate }
|
|
||||||
const allFlags = Array.from(new Set([
|
|
||||||
...Object.keys(toRaw(recent.flagStorage)),
|
|
||||||
...Object.keys(toRaw(stale.flagStorage))
|
|
||||||
]))
|
|
||||||
|
|
||||||
const totalFlags = Object.fromEntries(allFlags.map(flag => {
|
|
||||||
const recentFlag = recent.flagStorage[flag]
|
|
||||||
const staleFlag = stale.flagStorage[flag]
|
|
||||||
// use flag that is of higher value
|
|
||||||
return [flag, recentFlag > staleFlag ? recentFlag : staleFlag]
|
|
||||||
}))
|
|
||||||
|
|
||||||
console.debug('AAA', totalFlags)
|
|
||||||
// flag reset functionality
|
|
||||||
if (totalFlags.reset >= COMMAND_TRIM_FLAGS && totalFlags.reset <= COMMAND_TRIM_FLAGS_AND_RESET) {
|
|
||||||
console.debug('Received command to trim the flags')
|
|
||||||
const knownKeys = new Set(Object.keys(defaultState.flagStorage))
|
|
||||||
allFlags.forEach(flag => {
|
|
||||||
if (!knownKeys.has(flag)) {
|
|
||||||
delete totalFlags[flag]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (totalFlags.reset === COMMAND_TRIM_FLAGS_AND_RESET) {
|
|
||||||
// 1001 - and reset everything to 0
|
|
||||||
console.debug('Received command to reset the flags')
|
|
||||||
allFlags.forEach(flag => { totalFlags[flag] = 0 })
|
|
||||||
} else {
|
|
||||||
// reset the reset 0
|
|
||||||
totalFlags.reset = 0
|
|
||||||
}
|
|
||||||
} else if (totalFlags.reset > 0 && totalFlags.reset < 9000) {
|
|
||||||
console.debug('Received command to reset the flags')
|
|
||||||
allFlags.forEach(flag => { totalFlags[flag] = 0 })
|
|
||||||
// for good luck
|
|
||||||
totalFlags.reset = 0
|
|
||||||
}
|
|
||||||
console.log('AAAA', totalFlags)
|
|
||||||
state.cache.flagStorage = totalFlags
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 })
|
||||||
|
Loading…
Reference in New Issue
Block a user