Add parameter to optimize repository.query, auto-connect when sending, optimize storage adapters

This commit is contained in:
Jon Staab
2025-01-02 09:27:35 -08:00
parent dab93d9b56
commit c1e9d99ad9
6 changed files with 83 additions and 40 deletions
+44 -30
View File
@@ -2,14 +2,20 @@ import {openDB, deleteDB} from "idb"
import type {IDBPDatabase} from "idb"
import {writable} from "svelte/store"
import type {Unsubscriber, Writable} from "svelte/store"
import {indexBy, throttle, fromPairs} from "@welshman/lib"
import {indexBy, equals, throttle, 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"
export type IndexedDbAdapter = {
export type StorageAdapterOptions = {
throttle?: number
migrate?: (items: any[]) => any[]
}
export type StorageAdapter = {
keyPath: string
store: Writable<any[]>
options: StorageAdapterOptions
}
export let db: IDBPDatabase
@@ -44,41 +50,45 @@ export const bulkDelete = async (name: string, ids: string[]) => {
await tx.done
}
export const initIndexedDbAdapter = async (name: string, adapter: IndexedDbAdapter) => {
export const initIndexedDbAdapter = async (name: string, adapter: StorageAdapter) => {
let prevRecords = await getAll(name)
adapter.store.set(prevRecords)
adapter.store.subscribe(async (currentRecords: any[]) => {
if (dead.get()) {
return
}
setTimeout(() => {
adapter.store.subscribe(async (currentRecords: any[]) => {
if (dead.get()) {
return
}
const currentIds = new Set(currentRecords.map(item => item[adapter.keyPath]))
const removedRecords = prevRecords.filter(r => !currentIds.has(r[adapter.keyPath]))
const currentIds = new Set(currentRecords.map(item => item[adapter.keyPath]))
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]))
prevRecords = currentRecords
if (updatedRecords.length > 0) {
await bulkPut(name, updatedRecords)
}
if (removedRecords.length > 0) {
await bulkDelete(
name,
removedRecords.map(item => item[adapter.keyPath]),
const prevRecordsById = indexBy(item => item[adapter.keyPath], prevRecords)
const updatedRecords = currentRecords.filter(
r => !equals(r, prevRecordsById.get(r[adapter.keyPath])),
)
}
})
prevRecords = currentRecords
if (updatedRecords.length > 0) {
await bulkPut(name, updatedRecords)
}
if (removedRecords.length > 0) {
await bulkDelete(
name,
removedRecords.map(item => item[adapter.keyPath]),
)
}
})
}, adapter.options.throttle || 0)
}
export const initStorage = async (
name: string,
version: number,
adapters: Record<string, IndexedDbAdapter>,
adapters: Record<string, StorageAdapter>,
) => {
if (!window.indexedDB) return
@@ -124,15 +134,19 @@ export const clearStorage = async () => {
await deleteDB(db.name)
}
export type StorageAdapterOptions = {
throttle?: number
migrate?: (items: any[]) => any[]
}
const migrate = (data: any[], options: StorageAdapterOptions) =>
options.migrate ? options.migrate(data) : data
export const storageAdapters = {
fromCollectionStore: <T>(
keyPath: string,
store: Writable<T[]>,
options: StorageAdapterOptions = {},
) => ({
options,
keyPath,
store: throttled(options.throttle || 0, store),
}),
fromObjectStore: <T>(
store: Writable<Record<string, T>>,
options: StorageAdapterOptions = {},
+6 -3
View File
@@ -11,6 +11,9 @@ import {
import {repository} from "./core.js"
import {relaysByUrl} from "./relays.js"
const query = (filters: Filter[]) =>
repository.query(filters, {shouldSort: filters.every(f => f.limit === undefined)})
export const hasNegentropy = (url: string) => {
const p = relaysByUrl.get().get(url)?.profile
@@ -26,7 +29,7 @@ export type AppSyncOpts = {
}
export const pull = async ({relays, filters}: AppSyncOpts) => {
const events = repository.query(filters)
const events = query(filters)
await Promise.all(
relays.map(async relay => {
@@ -38,7 +41,7 @@ export const pull = async ({relays, filters}: AppSyncOpts) => {
}
export const push = async ({relays, filters}: AppSyncOpts) => {
const events = repository.query(filters).filter(isSignedEvent)
const events = query(filters).filter(isSignedEvent)
await Promise.all(
relays.map(async relay => {
@@ -50,7 +53,7 @@ export const push = async ({relays, filters}: AppSyncOpts) => {
}
export const sync = async ({relays, filters}: AppSyncOpts) => {
const events = repository.query(filters).filter(isSignedEvent)
const events = query(filters).filter(isSignedEvent)
await Promise.all(
relays.map(async relay => {