Improve speed of freshness and storage

This commit is contained in:
Jon Staab
2024-09-18 10:11:00 -07:00
parent 315f53e9b2
commit 2b1cb5fa33
3 changed files with 22 additions and 16 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
import {readable, derived, type Readable} from 'svelte/store' import {readable, derived, type Readable} from 'svelte/store'
import {indexBy, type Maybe, now} from '@welshman/lib' import {indexBy, type Maybe, now} from '@welshman/lib'
import {withGetter} from '@welshman/store' import {withGetter} from '@welshman/store'
import {getFreshness, setFreshness} from './freshness' import {getFreshness, setFreshnessThrottled} from './freshness'
export const collection = <T, LoadArgs extends any[]>({ export const collection = <T, LoadArgs extends any[]>({
name, name,
@@ -42,7 +42,7 @@ export const collection = <T, LoadArgs extends any[]>({
loadAttempts.set(key, attempt + 1) loadAttempts.set(key, attempt + 1)
setFreshness(name, key, now()) setFreshnessThrottled({ns: name, key, ts: now()})
const promise = load(key, ...args) const promise = load(key, ...args)
+12 -5
View File
@@ -1,7 +1,13 @@
import {writable} from 'svelte/store' import {writable} from 'svelte/store'
import {assoc} from '@welshman/lib' import {assoc, batch} from '@welshman/lib'
import {withGetter} from '@welshman/store' import {withGetter} from '@welshman/store'
export type FreshnessUpdate = {
ns: string
key: string
ts: number
}
export const freshness = withGetter(writable<Record<string, number>>({})) export const freshness = withGetter(writable<Record<string, number>>({}))
export const getFreshnessKey = (ns: string, key: string) => `${ns}:${key}` export const getFreshnessKey = (ns: string, key: string) => `${ns}:${key}`
@@ -9,14 +15,15 @@ export const getFreshnessKey = (ns: string, key: string) => `${ns}:${key}`
export const getFreshness = (ns: string, key: string) => export const getFreshness = (ns: string, key: string) =>
freshness.get()[getFreshnessKey(ns, key)] || 0 freshness.get()[getFreshnessKey(ns, key)] || 0
export const setFreshness = (ns: string, key: string, ts: number) => export const setFreshnessImmediate = ({ns, key, ts}: FreshnessUpdate) =>
freshness.update(assoc(getFreshnessKey(ns, key), ts)) freshness.update(assoc(getFreshnessKey(ns, key), ts))
export const setFreshnessBulk = (ns: string, updates: Record<string, number>) => export const setFreshnessThrottled = batch(100, (updates: FreshnessUpdate[]) =>
freshness.update($freshness => { freshness.update($freshness => {
for (const [key, ts] of Object.entries(updates)) { for (const {ns, key, ts} of updates) {
$freshness[key] = ts $freshness[getFreshnessKey(ns, key)] = ts
} }
return $freshness return $freshness
}) })
)
+8 -9
View File
@@ -3,7 +3,7 @@ import type {IDBPDatabase} from "idb"
import {throttle} from "throttle-debounce" import {throttle} from "throttle-debounce"
import {writable} from "svelte/store" import {writable} from "svelte/store"
import type {Unsubscriber, Writable} from "svelte/store" import type {Unsubscriber, Writable} from "svelte/store"
import {indexBy, fromPairs} from "@welshman/lib" import {indexBy, equals, fromPairs} from "@welshman/lib"
import type {TrustedEvent, Repository} from "@welshman/util" import type {TrustedEvent, Repository} from "@welshman/util"
import type {Tracker} from "@welshman/net" import type {Tracker} from "@welshman/net"
import {withGetter, adapter, throttled, custom} from "@welshman/store" import {withGetter, adapter, throttled, custom} from "@welshman/store"
@@ -69,12 +69,11 @@ export const initIndexedDbAdapter = async (name: string, adapter: IndexedDbAdapt
const removedRecords = prevRecords.filter(r => !currentIds.has(r[adapter.keyPath])) const removedRecords = prevRecords.filter(r => !currentIds.has(r[adapter.keyPath]))
const prevRecordsById = indexBy(item => item[adapter.keyPath], prevRecords) const prevRecordsById = indexBy(item => item[adapter.keyPath], prevRecords)
const updatedRecords = currentRecords.filter(r => r !== prevRecordsById.get(r[adapter.keyPath])) const updatedRecords = currentRecords.filter(r => !equals(r, prevRecordsById.get(r[adapter.keyPath])))
prevRecords = currentRecords prevRecords = currentRecords
if (updatedRecords.length > 0) { if (updatedRecords.length > 0) {
await bulkPut(name, updatedRecords) await bulkPut(name, updatedRecords)
} }
@@ -141,24 +140,24 @@ export const storageAdapters = {
fromObjectStore: <T>(store: Writable<Record<string, T>>, options: StorageAdapterOptions = {}) => ({ fromObjectStore: <T>(store: Writable<Record<string, T>>, options: StorageAdapterOptions = {}) => ({
options, options,
keyPath: "key", keyPath: "key",
store: throttled(options.throttle || 0, adapter({ store: adapter({
store: store, store: throttled(options.throttle || 0, store),
forward: ($data: Record<string, T>) => forward: ($data: Record<string, T>) =>
Object.entries($data).map(([key, value]) => ({key, value})), Object.entries($data).map(([key, value]) => ({key, value})),
backward: (data: {key: string, value: T}[]) => backward: (data: {key: string, value: T}[]) =>
fromPairs(data.map(({key, value}) => [key, value])), fromPairs(data.map(({key, value}) => [key, value])),
})), }),
}), }),
fromMapStore: <T>(store: Writable<Map<string, T>>, options: StorageAdapterOptions = {}) => ({ fromMapStore: <T>(store: Writable<Map<string, T>>, options: StorageAdapterOptions = {}) => ({
options, options,
keyPath: "key", keyPath: "key",
store: throttled(options.throttle || 0, adapter({ store: adapter({
store: store, store: throttled(options.throttle || 0, store),
forward: ($data: Map<string, T>) => forward: ($data: Map<string, T>) =>
Array.from($data.entries()).map(([key, value]) => ({key, value})), Array.from($data.entries()).map(([key, value]) => ({key, value})),
backward: (data: {key: string, value: T}[]) => backward: (data: {key: string, value: T}[]) =>
new Map(data.map(({key, value}) => [key, value])), new Map(data.map(({key, value}) => [key, value])),
})), }),
}), }),
fromTracker: (tracker: Tracker, options: StorageAdapterOptions = {}) => ({ fromTracker: (tracker: Tracker, options: StorageAdapterOptions = {}) => ({
options, options,