proper journal trimming + remove some old workaround to my local bad data
This commit is contained in:
		
							parent
							
								
									8d6e5c1e69
								
							
						
					
					
						commit
						840ce06397
					
				
					 2 changed files with 39 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import { toRaw } from 'vue'
 | 
			
		||||
import { isEqual, uniqWith, cloneDeep, set, get, clamp } from 'lodash'
 | 
			
		||||
import { isEqual, cloneDeep, set, get, clamp, flatten, groupBy, findLastIndex, takeRight } from 'lodash'
 | 
			
		||||
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
 | 
			
		||||
 | 
			
		||||
export const VERSION = 1
 | 
			
		||||
| 
						 | 
				
			
			@ -131,25 +131,32 @@ export const _mergeFlags = (recent, stale, allFlagKeys) => {
 | 
			
		|||
  }))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const _mergeJournal = (a, b) => uniqWith(
 | 
			
		||||
  // TODO use groupBy to group by path, then trim them depending on operations,
 | 
			
		||||
  // i.e. if field got removed in the end - no need to sort it beforehand, if field
 | 
			
		||||
  // got re-added no need to remove it and add it etc.
 | 
			
		||||
  [
 | 
			
		||||
    ...(Array.isArray(a) ? a : []),
 | 
			
		||||
    ...(Array.isArray(b) ? b : [])
 | 
			
		||||
  ].sort((a, b) => a.timestamp > b.timestamp ? -1 : 1),
 | 
			
		||||
  (a, b) => {
 | 
			
		||||
    if (a.operation !== b.operation) return false
 | 
			
		||||
    switch (a.operation) {
 | 
			
		||||
      case 'set':
 | 
			
		||||
      case 'arrangeSet':
 | 
			
		||||
        return a.path === b.path
 | 
			
		||||
      default:
 | 
			
		||||
        return a.path === b.path && a.timestamp === b.timestamp
 | 
			
		||||
const _mergeJournal = (...journals) => {
 | 
			
		||||
  const allJournals = flatten(journals.map(j => Array.isArray(j) ? j : []))
 | 
			
		||||
  const grouped = groupBy(allJournals, 'path')
 | 
			
		||||
  const trimmedGrouped = Object.entries(grouped).map(([path, journal]) => {
 | 
			
		||||
    // side effect
 | 
			
		||||
    journal.sort((a, b) => a.timestamp > b.timestamp ? 1 : -1)
 | 
			
		||||
 | 
			
		||||
    if (path.startsWith('collections')) {
 | 
			
		||||
      const lastRemoveIndex = findLastIndex(journal, ({ operation }) => operation === 'removeFromCollection')
 | 
			
		||||
      // everything before last remove is unimportant
 | 
			
		||||
      if (lastRemoveIndex > 0) {
 | 
			
		||||
        return journal.slice(lastRemoveIndex)
 | 
			
		||||
      } else {
 | 
			
		||||
        // everything else doesn't need trimming
 | 
			
		||||
        return journal
 | 
			
		||||
      }
 | 
			
		||||
    } else if (path.startsWith('simple')) {
 | 
			
		||||
      // Only the last record is important
 | 
			
		||||
      return takeRight(journal)
 | 
			
		||||
    } else {
 | 
			
		||||
      return journal
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
).reverse()
 | 
			
		||||
  })
 | 
			
		||||
  return flatten(trimmedGrouped)
 | 
			
		||||
    .sort((a, b) => a.timestamp > b.timestamp ? 1 : -1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const _mergePrefs = (recent, stale, allFlagKeys) => {
 | 
			
		||||
  if (!stale) return recent
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +176,6 @@ export const _mergePrefs = (recent, stale, allFlagKeys) => {
 | 
			
		|||
  const resultOutput = { ...recentData }
 | 
			
		||||
  const totalJournal = _mergeJournal(staleJournal, recentJournal)
 | 
			
		||||
  totalJournal.forEach(({ path, timestamp, operation, command, args }) => {
 | 
			
		||||
    operation = operation || command
 | 
			
		||||
    if (path.startsWith('_')) {
 | 
			
		||||
      console.error(`journal contains entry to edit internal (starts with _) field '${path}', something is incorrect here, ignoring.`)
 | 
			
		||||
      return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,7 +107,7 @@ describe('The serverSideStorage module', () => {
 | 
			
		|||
      })
 | 
			
		||||
    })
 | 
			
		||||
    describe('setPreference', () => {
 | 
			
		||||
      const { setPreference, updateCache } = mutations
 | 
			
		||||
      const { setPreference, updateCache, addToCollection, removeFromCollection } = mutations
 | 
			
		||||
 | 
			
		||||
      it('should set preference and update journal log accordingly', () => {
 | 
			
		||||
        const state = cloneDeep(defaultState)
 | 
			
		||||
| 
						 | 
				
			
			@ -123,12 +123,15 @@ describe('The serverSideStorage module', () => {
 | 
			
		|||
        })
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      it('should keep journal to a minimum (one entry per path for sets)', () => {
 | 
			
		||||
      it('should keep journal to a minimum', () => {
 | 
			
		||||
        const state = cloneDeep(defaultState)
 | 
			
		||||
        setPreference(state, { path: 'simple.testing', value: 1 })
 | 
			
		||||
        setPreference(state, { path: 'simple.testing', value: 2 })
 | 
			
		||||
        addToCollection(state, { path: 'collections.testing', value: 2 })
 | 
			
		||||
        removeFromCollection(state, { path: 'collections.testing', value: 2 })
 | 
			
		||||
        updateCache(state, { username: 'test' })
 | 
			
		||||
        expect(state.prefsStorage.simple.testing).to.eql(2)
 | 
			
		||||
        expect(state.prefsStorage.collections.testing).to.eql([])
 | 
			
		||||
        expect(state.prefsStorage._journal.length).to.eql(1)
 | 
			
		||||
        expect(state.prefsStorage._journal[0]).to.eql({
 | 
			
		||||
          path: 'simple.testing',
 | 
			
		||||
| 
						 | 
				
			
			@ -137,6 +140,14 @@ describe('The serverSideStorage module', () => {
 | 
			
		|||
          // should have A timestamp, we don't really care what it is
 | 
			
		||||
          timestamp: state.prefsStorage._journal[0].timestamp
 | 
			
		||||
        })
 | 
			
		||||
        expect(state.prefsStorage._journal[1]).to.eql({
 | 
			
		||||
          path: 'collection.testing',
 | 
			
		||||
          operation: 'remove',
 | 
			
		||||
          args: [2],
 | 
			
		||||
          // should have A timestamp, we don't really care what it is
 | 
			
		||||
          timestamp: state.prefsStorage._journal[1].timestamp
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue