pinafore/routes/_utils/RealmStore.js

73 lines
2.1 KiB
JavaScript
Raw Normal View History

2018-01-31 05:55:23 +00:00
// A store where you can divide data into "realms" that are backed with an LRU cache.
// Each realm has self-contained data that you can set with setForRealm() and compute
// with computeForRealm(). The maxSize determines how many realms to keep in the LRU cache.
import { Store } from 'svelte/store.js'
import QuickLRU from 'quick-lru'
2018-01-31 16:37:59 +00:00
import { mark, stop } from './marks'
2018-01-31 05:55:23 +00:00
export class RealmStore extends Store {
2018-02-09 06:29:29 +00:00
constructor (init, maxSize) {
2018-01-31 05:55:23 +00:00
super(init)
this.set({realms: new QuickLRU({maxSize: maxSize})})
2018-01-31 16:37:59 +00:00
this._batches = {}
2018-01-31 05:55:23 +00:00
}
2018-02-09 06:29:29 +00:00
setCurrentRealm (realm) {
2018-01-31 05:55:23 +00:00
this.set({currentRealm: realm})
}
2018-02-09 06:29:29 +00:00
setForRealm (obj) {
2018-01-31 05:55:23 +00:00
let realmName = this.get('currentRealm')
let realms = this.get('realms')
realms.set(realmName, Object.assign(realms.get(realmName) || {}, obj))
this.set({realms: realms})
}
2018-02-09 06:29:29 +00:00
computeForRealm (key, defaultValue) {
2018-01-31 05:55:23 +00:00
this.compute(key,
['realms', 'currentRealm'],
(realms, currentRealm) => {
2018-02-09 06:29:29 +00:00
let realmData = realms.get(currentRealm)
return (realmData && realmData[key]) || defaultValue
})
2018-01-31 05:55:23 +00:00
}
2018-01-31 16:37:59 +00:00
/*
* Update several values at once in a realm, assuming the key points
* to a plain old javascript object.
*/
2018-02-09 06:29:29 +00:00
batchUpdateForRealm (key, subKey, value) {
2018-01-31 16:37:59 +00:00
let realm = this.get('currentRealm')
let realmBatches = this._batches[realm]
if (!realmBatches) {
realmBatches = this._batches[realm] = {}
}
let batch = realmBatches[key]
if (!batch) {
batch = realmBatches[key] = {}
}
batch[subKey] = value
requestAnimationFrame(() => {
let batch = this._batches[realm] && this._batches[realm][key]
if (!batch) {
return
}
let updatedKeys = Object.keys(batch)
if (!updatedKeys.length) {
return
}
mark('batchUpdate')
let obj = this.get(key)
for (let otherKey of updatedKeys) {
obj[otherKey] = batch[otherKey]
}
delete this._batches[realm][key]
let realms = this.get('realms')
realms.set(realm, Object.assign(realms.get(realm) || {}, {[key]: obj}))
this.set({realms: realms})
stop('batchUpdate')
})
}
2018-02-09 06:29:29 +00:00
}