diff --git a/packages/app/src/collection.ts b/packages/app/src/collection.ts index b2d1a88..b950773 100644 --- a/packages/app/src/collection.ts +++ b/packages/app/src/collection.ts @@ -1,7 +1,7 @@ import {readable, derived, type Readable} from 'svelte/store' import {indexBy, type Maybe, now} from '@welshman/lib' import {withGetter} from '@welshman/store' -import {getFreshness, setFreshness} from './freshness' +import {getFreshness, setFreshnessThrottled} from './freshness' export const collection = ({ name, @@ -42,7 +42,7 @@ export const collection = ({ loadAttempts.set(key, attempt + 1) - setFreshness(name, key, now()) + setFreshnessThrottled({ns: name, key, ts: now()}) const promise = load(key, ...args) diff --git a/packages/app/src/freshness.ts b/packages/app/src/freshness.ts index 4e271e0..61f4c2c 100644 --- a/packages/app/src/freshness.ts +++ b/packages/app/src/freshness.ts @@ -1,7 +1,13 @@ import {writable} from 'svelte/store' -import {assoc} from '@welshman/lib' +import {assoc, batch} from '@welshman/lib' import {withGetter} from '@welshman/store' +export type FreshnessUpdate = { + ns: string + key: string + ts: number +} + export const freshness = withGetter(writable>({})) 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) => 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)) -export const setFreshnessBulk = (ns: string, updates: Record) => +export const setFreshnessThrottled = batch(100, (updates: FreshnessUpdate[]) => freshness.update($freshness => { - for (const [key, ts] of Object.entries(updates)) { - $freshness[key] = ts + for (const {ns, key, ts} of updates) { + $freshness[getFreshnessKey(ns, key)] = ts } return $freshness }) +) diff --git a/packages/app/src/storage.ts b/packages/app/src/storage.ts index c788c52..f605751 100644 --- a/packages/app/src/storage.ts +++ b/packages/app/src/storage.ts @@ -3,7 +3,7 @@ import type {IDBPDatabase} from "idb" import {throttle} from "throttle-debounce" import {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 {Tracker} from "@welshman/net" 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 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 if (updatedRecords.length > 0) { - await bulkPut(name, updatedRecords) } @@ -141,24 +140,24 @@ export const storageAdapters = { fromObjectStore: (store: Writable>, options: StorageAdapterOptions = {}) => ({ options, keyPath: "key", - store: throttled(options.throttle || 0, adapter({ - store: store, + store: adapter({ + store: throttled(options.throttle || 0, store), forward: ($data: Record) => Object.entries($data).map(([key, value]) => ({key, value})), backward: (data: {key: string, value: T}[]) => fromPairs(data.map(({key, value}) => [key, value])), - })), + }), }), fromMapStore: (store: Writable>, options: StorageAdapterOptions = {}) => ({ options, keyPath: "key", - store: throttled(options.throttle || 0, adapter({ - store: store, + store: adapter({ + store: throttled(options.throttle || 0, store), forward: ($data: Map) => Array.from($data.entries()).map(([key, value]) => ({key, value})), backward: (data: {key: string, value: T}[]) => new Map(data.map(({key, value}) => [key, value])), - })), + }), }), fromTracker: (tracker: Tracker, options: StorageAdapterOptions = {}) => ({ options,