From c2a08fbd10048c83688164eb14cd4c621dfcb1db Mon Sep 17 00:00:00 2001 From: Carlo Sala Date: Mon, 11 Nov 2024 11:39:40 +0700 Subject: [PATCH] Revert "cache smoldot db" This reverts commit ca10cf462baa9afc1b76be676614be2564ad074b. --- package.json | 1 - pnpm-lock.yaml | 3 -- src/main.tsx | 10 +---- src/smoldot.ts | 0 src/state/chains/chain.state.ts | 56 ++++++++++++--------------- src/state/chains/smoldot.cache.ts | 4 -- src/state/chains/smoldot.ts | 64 +++++++++++-------------------- src/utils/cyclingLocalCache.ts | 36 ----------------- 8 files changed, 48 insertions(+), 126 deletions(-) create mode 100644 src/smoldot.ts delete mode 100644 src/state/chains/smoldot.cache.ts delete mode 100644 src/utils/cyclingLocalCache.ts diff --git a/package.json b/package.json index 454c332..15b9e4e 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "1.0.4", - "idb-keyval": "^6.2.1", "lucide-react": "^0.456.0", "polkadot-api": "^1.7.3", "react": "^18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d055471..04b5375 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,9 +109,6 @@ importers: cmdk: specifier: 1.0.4 version: 1.0.4(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - idb-keyval: - specifier: ^6.2.1 - version: 6.2.1 lucide-react: specifier: ^0.456.0 version: 0.456.0(react@18.3.1) diff --git a/src/main.tsx b/src/main.tsx index e863812..062d99d 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,7 +5,6 @@ import { BrowserRouter } from "react-router-dom" import { merge } from "rxjs" import App from "./App.tsx" import { dynamicBuilder$ } from "@/state/chains/chain.state" -import { persistSyncState$ } from "./state/chains/chain.state.ts" import { TooltipProvider } from "./components/Tooltip.tsx" import "./index.css" import { explorer$ } from "./pages/Explorer" @@ -13,14 +12,7 @@ import { transactions$ } from "./pages/Transactions" import { ThemeProvider } from "./ThemeProvider.tsx" createRoot(document.getElementById("root")!).render( - + diff --git a/src/smoldot.ts b/src/smoldot.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/state/chains/chain.state.ts b/src/state/chains/chain.state.ts index 965ffcb..b5e82a1 100644 --- a/src/state/chains/chain.state.ts +++ b/src/state/chains/chain.state.ts @@ -1,14 +1,12 @@ -import { cyclingLocalCache } from "@/utils/cyclingLocalCache" import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders" import { getObservableClient } from "@polkadot-api/observable-client" -import { decAnyMetadata } from "@polkadot-api/substrate-bindings" +import { decAnyMetadata, HexString } from "@polkadot-api/substrate-bindings" import { createClient as createSubstrateClient } from "@polkadot-api/substrate-client" import { toHex } from "@polkadot-api/utils" import { sinkSuspense, state, SUSPENSE } from "@react-rxjs/core" import { createSignal } from "@react-rxjs/utils" import { createClient } from "polkadot-api" import { - catchError, concat, EMPTY, filter, @@ -25,15 +23,12 @@ import { createSmoldotSource, getSmoldotProvider, SmoldotSource, - RelayChain, - relayChains, } from "./smoldot" import { createWebsocketSource, getWebsocketProvider, WebsocketSource, } from "./websocket" -import { setCachedSmoldotDb } from "./smoldot.cache" export type ChainSource = WebsocketSource | SmoldotSource @@ -93,18 +88,34 @@ export const unsafeApi$ = chainClient$.pipeState( map(({ client }) => client.getUnsafeApi()), ) -export const uncachedRuntimeCtx$ = chainClient$.pipeState( +const uncachedRuntimeCtx$ = chainClient$.pipeState( switchMap(({ chainHead }) => chainHead.runtime$), filter((v) => !!v), ) -const [getCachedMetadata, setCachedMetadata] = - cyclingLocalCache("metadata-cache") +const getMetadataCache = () => { + const cached = localStorage.getItem(`metadata-cache`) + return new Map( + cached ? JSON.parse(cached) : [], + ) +} +const getCachedMetadata = (id: string) => + getMetadataCache().get(id)?.data ?? null +const setCachedMetadata = (id: string, data: HexString) => { + const cached = getMetadataCache() + cached.set(id, { time: Date.now(), data }) + if (cached.size > 3) { + const oldest = [...cached.entries()].reduce((a, b) => + a[1].time < b[1].time ? a : b, + )[0] + cached.delete(oldest) + } + localStorage.setItem("metadata-cache", JSON.stringify([...cached.entries()])) +} export const runtimeCtx$ = chainClient$.pipeState( - switchMap(({ id }) => - getCachedMetadata(id).then((cached) => ({ id, cached })), - ), - switchMap(({ id, cached }) => { + switchMap(({ id }) => { + const cached = getCachedMetadata(id) + const realCtx$ = uncachedRuntimeCtx$.pipe( tap((v) => { setCachedMetadata(id, toHex(v.metadataRaw)) @@ -133,23 +144,4 @@ export const dynamicBuilder$ = runtimeCtx$.pipeState( map((ctx) => ctx.dynamicBuilder), ) -export const persistSyncState$ = chainClient$.pipe( - switchMap(({ id, client }) => { - if (!relayChains.includes(id as RelayChain)) return EMPTY - - return uncachedRuntimeCtx$.pipe( - switchMap(() => - client._request("chainHead_unstable_finalizedDatabase", []), - ), - catchError(() => EMPTY), - filter((v) => !!v), - map((db) => ({ - id, - db, - })), - ) - }), - tap(({ id, db }) => setCachedSmoldotDb(id, db)), -) - export { networkCategories, type Network } from "./networks" diff --git a/src/state/chains/smoldot.cache.ts b/src/state/chains/smoldot.cache.ts deleted file mode 100644 index a319583..0000000 --- a/src/state/chains/smoldot.cache.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { cyclingLocalCache } from "@/utils/cyclingLocalCache" - -export const [getCachedSmoldotDb, setCachedSmoldotDb] = - cyclingLocalCache("smoldot-db") diff --git a/src/state/chains/smoldot.ts b/src/state/chains/smoldot.ts index 9fd2d12..e2b49ba 100644 --- a/src/state/chains/smoldot.ts +++ b/src/state/chains/smoldot.ts @@ -4,7 +4,6 @@ import { getSmProvider } from "polkadot-api/sm-provider" import { Chain } from "polkadot-api/smoldot" import { startFromWorker } from "polkadot-api/smoldot/from-worker" import SmWorker from "polkadot-api/smoldot/worker?worker" -import { getCachedSmoldotDb } from "./smoldot.cache" const [dotChainSpec, ksmChainSpec, paseoChainSpec, westendChainSpec] = [ import("polkadot-api/chains/polkadot"), @@ -12,18 +11,13 @@ const [dotChainSpec, ksmChainSpec, paseoChainSpec, westendChainSpec] = [ import("polkadot-api/chains/paseo"), import("polkadot-api/chains/westend2"), ].map((x) => x.then((y) => y.chainSpec)) - const smoldot = startFromWorker(new SmWorker(), { logCallback: (level, target, message) => { console.debug("smoldot[%s(%s)] %s", target, level, message) }, }) - -export const relayChains = ["polkadot", "kusama", "paseo", "westend"] as const -export type RelayChain = (typeof relayChains)[number] - -const relaySmoldotChains: Record< - RelayChain, +const relayChains: Record< + string, { chainSpec: Promise; chain: Promise | null } > = { polkadot: { chainSpec: dotChainSpec, chain: null }, @@ -31,39 +25,21 @@ const relaySmoldotChains: Record< paseo: { chainSpec: paseoChainSpec, chain: null }, westend: { chainSpec: westendChainSpec, chain: null }, } -const createChain = async ( - id: string, - chainSpec: string | Promise, - relayChain?: Promise, -) => { - const databaseContent = - (id in relaySmoldotChains && (await getCachedSmoldotDb(id))) || undefined - const solvedChain = relayChain ? await relayChain : undefined - return smoldot.addChain({ - chainSpec: await chainSpec, - databaseContent, - potentialRelayChains: solvedChain ? [solvedChain] : undefined, - }) -} -const getRelayChain = async (name: RelayChain) => { - if (!relaySmoldotChains[name].chain) { - relaySmoldotChains[name].chain = createChain( - name, - relaySmoldotChains[name].chainSpec, - ) +const getRelayChain = async (name: string) => { + if (!relayChains[name].chain) { + relayChains[name].chain = smoldot.addChain({ + chainSpec: await relayChains[name].chainSpec, + }) } - return relaySmoldotChains[name].chain + return relayChains[name].chain } -// Pre-initialize all relay chains -relayChains.forEach(getRelayChain) - export interface SmoldotSource { type: "chainSpec" id: string value: { chainSpec: string - relayChain?: RelayChain + relayChain?: string } } @@ -71,8 +47,8 @@ export function createSmoldotSource( id: string, relayChain?: string, ): Promise { - if (id in relaySmoldotChains) { - return relaySmoldotChains[id as RelayChain].chainSpec.then((chainSpec) => ({ + if (id in relayChains) { + return relayChains[id].chainSpec.then((chainSpec) => ({ id, type: "chainSpec", value: { chainSpec }, @@ -93,12 +69,18 @@ export function createSmoldotSource( export function getSmoldotProvider(source: SmoldotSource): JsonRpcProvider { const chain = source.value.relayChain - ? createChain( - source.id, - source.value.chainSpec, - getRelayChain(source.value.relayChain), + ? getRelayChain(source.value.relayChain).then((chain) => + smoldot.addChain({ + chainSpec: source.value.chainSpec, + potentialRelayChains: [chain], + }), ) - : createChain(source.id, source.value.chainSpec) + : smoldot.addChain({ + chainSpec: source.value.chainSpec, + }) - return withLogsRecorder((v) => console.debug(v), getSmProvider(chain)) + return withLogsRecorder( + (v) => v.includes("initialized") && console.debug(v), + getSmProvider(chain), + ) } diff --git a/src/utils/cyclingLocalCache.ts b/src/utils/cyclingLocalCache.ts deleted file mode 100644 index 33cafb7..0000000 --- a/src/utils/cyclingLocalCache.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { get, set } from "idb-keyval" - -export const cyclingLocalCache = (key: string, limit = 10) => { - const getCache = async () => { - try { - const entries = await get(key) - return new Map(entries) - } catch (_) { - return null - } - } - const getCachedItem = (id: string) => - id === "metadata-cache" - ? Promise.resolve(null) - : getCache().then((cache) => cache?.get(id)?.data ?? null) - const setCachedItem = async (id: string, data: string) => { - const cached = await getCache() - if (!cached) return - - cached.set(id, { time: Date.now(), data }) - if (cached.size > limit) { - const oldest = [...cached.entries()].reduce((a, b) => - a[1].time < b[1].time ? a : b, - )[0] - cached.delete(oldest) - } - - try { - await set(key, [...cached.entries()]) - } catch (_) { - /* empty */ - } - } - - return [getCachedItem, setCachedItem] as const -}