diff --git a/packages/registry/src/node-registry-cache.ts b/packages/registry/src/node-registry-cache.ts index b44c10d..6a3bb89 100644 --- a/packages/registry/src/node-registry-cache.ts +++ b/packages/registry/src/node-registry-cache.ts @@ -1,22 +1,22 @@ import type { AsyncCache } from '@nodarium/types'; import { openDB, type IDBPDatabase } from 'idb'; -export class IndexDBCache implements AsyncCache { +export class IndexDBCache implements AsyncCache { size: number = 100; - db: Promise>; - private _cache = new Map(); + db: Promise>; + private _cache = new Map(); constructor(id: string) { - this.db = openDB('cache/' + id, 1, { + this.db = openDB('cache/' + id, 1, { upgrade(db) { db.createObjectStore('keyval'); }, }); } - async get(key: string) { + async get(key: string): Promise { let res = this._cache.get(key); if (!res) { res = await (await this.db).get('keyval', key); @@ -24,13 +24,33 @@ export class IndexDBCache implements AsyncCache { if (res) { this._cache.set(key, res); } - return res; + return res as T; } - async set(key: string, value: ArrayBuffer) { + + async getArrayBuffer(key: string) { + const res = await this.get(key); + if (!res) return; + if (res instanceof ArrayBuffer) { + return res; + } + return + } + + async getString(key: string) { + const res = await this.get(key); + if (!res) return; + if (typeof res === "string") { + return res; + } + return + } + + async set(key: string, value: unknown) { this._cache.set(key, value); const db = await this.db; await db.put('keyval', value, key); } + clear() { this.db.then(db => db.clear('keyval')); } diff --git a/packages/registry/src/node-registry-client.ts b/packages/registry/src/node-registry-client.ts index ec00263..e10d9ce 100644 --- a/packages/registry/src/node-registry-client.ts +++ b/packages/registry/src/node-registry-client.ts @@ -13,32 +13,63 @@ export class RemoteNodeRegistry implements NodeRegistry { status: "loading" | "ready" | "error" = "loading"; private nodes: Map = new Map(); - async fetchJson(url: string) { - const response = await fetch(`${this.url}/${url}`); - - if (!response.ok) { - log.error(`Failed to load ${url}`, { response, url, host: this.url }); - throw new Error(`Failed to load ${url}`); - } - - return response.json(); - } - - async fetchArrayBuffer(url: string) { - const response = await fetch(`${this.url}/${url}`); - if (!response.ok) { - log.error(`Failed to load ${url}`, { response, url, host: this.url }); - throw new Error(`Failed to load ${url}`); - } - - return response.arrayBuffer(); - } constructor( private url: string, - private cache?: AsyncCache, + private cache?: AsyncCache, ) { } + async fetchJson(url: string, skipCache = false) { + + const finalUrl = `${this.url}/${url}`; + + if (!skipCache && this.cache) { + const cachedValue = await this.cache?.get(finalUrl); + if (cachedValue) { + // fetch again in the background, maybe implement that only refetch after a certain time + this.fetchJson(url, true) + return JSON.parse(cachedValue); + } + } + + const response = await fetch(finalUrl); + + if (!response.ok) { + log.error(`Failed to load ${url}`, { response, url, host: this.url }); + throw new Error(`Failed to load ${url}`); + } + + const result = await response.json(); + + this.cache?.set(finalUrl, JSON.stringify(result)); + + return result; + } + + async fetchArrayBuffer(url: string, skipCache = false) { + + const finalUrl = `${this.url}/${url}`; + + if (!skipCache && this.cache) { + const cachedNode = await this.cache?.get(finalUrl); + if (cachedNode) { + // fetch again in the background, maybe implement that only refetch after a certain time + this.fetchArrayBuffer(url, true) + return cachedNode; + } + } + + const response = await fetch(finalUrl); + if (!response.ok) { + log.error(`Failed to load ${url}`, { response, url, host: this.url }); + throw new Error(`Failed to load ${url}`); + } + + const buffer = await response.arrayBuffer(); + this.cache?.set(finalUrl, buffer); + return buffer; + } + async fetchUsers() { return this.fetchJson(`nodes/users.json`); } @@ -48,7 +79,8 @@ export class RemoteNodeRegistry implements NodeRegistry { } async fetchCollection(userCollectionId: `${string}/${string}`) { - return this.fetchJson(`nodes/${userCollectionId}.json`); + const col = await this.fetchJson(`nodes/${userCollectionId}.json`); + return col } async fetchNodeDefinition(nodeId: `${string}/${string}/${string}`) { @@ -56,10 +88,6 @@ export class RemoteNodeRegistry implements NodeRegistry { } private async fetchNodeWasm(nodeId: `${string}/${string}/${string}`) { - const cachedNode = await this.cache?.get(nodeId); - if (cachedNode) { - return cachedNode; - } const node = await this.fetchArrayBuffer(`nodes/${nodeId}.wasm`); if (!node) { diff --git a/packages/types/src/components.ts b/packages/types/src/components.ts index 4174ca1..9308abb 100644 --- a/packages/types/src/components.ts +++ b/packages/types/src/components.ts @@ -83,7 +83,7 @@ export interface AsyncCache { * @param key - The key to get the value for * @returns The value for the given key, or undefined if no such value exists */ - get: (key: string) => Promise; + get: (key: string) => Promise; /** * Set the value for the given key * @param key - The key to set the value for