commit: 9c00610d0031969cce4d50c0f947098a632ca712
parent 6c0a6ff8b0e1717704a636ca172c52958590adaf
Author: Henry Jameson <me@hjkos.com>
Date: Thu, 4 Aug 2022 17:20:11 +0300
refactoring
Diffstat:
1 file changed, 155 insertions(+), 96 deletions(-)
diff --git a/src/modules/serverSideStorage.js b/src/modules/serverSideStorage.js
@@ -1,15 +1,14 @@
import { toRaw } from 'vue'
+import { isEqual } from 'lodash'
-const VERSION = 1
-const NEW_USER_DATE = new Date('04-08-2022') // date of writing this, basically
+export const VERSION = 1
+export const NEW_USER_DATE = new Date('04-08-2022') // date of writing this, basically
-const COMMAND_TRIM_FLAGS = 1000
-const COMMAND_TRIM_FLAGS_AND_RESET = 1001
+export const COMMAND_TRIM_FLAGS = 1000
+export const COMMAND_TRIM_FLAGS_AND_RESET = 1001
const defaultState = {
- // last timestamp
- timestamp: 0,
- // need to update server
+ // do we need to update data on server?
dirty: false,
// storage of flags - stuff that can only be set and incremented
flagStorage: {
@@ -33,6 +32,113 @@ const newUserFlags = {
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 = {
state: {
...defaultState
@@ -40,93 +146,50 @@ const serverSideStorage = {
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
- 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(),
- _version: VERSION,
- flagStorage: { ...flagsTemplate }
- }
- }
- } else if (!cacheValid) {
- console.debug('Valid storage on server found, no local cache found, using live as source of truth')
- recent = live
+ 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 {
- 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
- }
+ 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.flagStorage = state.cache.flagStorage
},
@@ -137,15 +200,11 @@ const serverSideStorage = {
},
actions: {
pushServerSideStorage ({ state, rootState, commit }, { force = false } = {}) {
- console.log('PUSH')
const needPush = state.dirty || force
if (!needPush) return
- state.cache = {
- _timestamp: Date.now(),
- _version: VERSION,
+ state.cache = _wrapData({
flagStorage: toRaw(state.flagStorage)
- }
- console.log('YES')
+ })
const params = { pleroma_settings_store: { 'pleroma-fe': state.cache } }
rootState.api.backendInteractor
.updateProfile({ params })