feat: cache everything in node store not only wasm

This commit is contained in:
2025-12-05 14:19:29 +01:00
parent 73be4fdd73
commit 3565a18364
3 changed files with 82 additions and 34 deletions

View File

@@ -1,22 +1,22 @@
import type { AsyncCache } from '@nodarium/types';
import { openDB, type IDBPDatabase } from 'idb';
export class IndexDBCache implements AsyncCache<ArrayBuffer> {
export class IndexDBCache implements AsyncCache<unknown> {
size: number = 100;
db: Promise<IDBPDatabase<ArrayBuffer>>;
private _cache = new Map<string, ArrayBuffer>();
db: Promise<IDBPDatabase<unknown>>;
private _cache = new Map<string, unknown>();
constructor(id: string) {
this.db = openDB<ArrayBuffer>('cache/' + id, 1, {
this.db = openDB<unknown>('cache/' + id, 1, {
upgrade(db) {
db.createObjectStore('keyval');
},
});
}
async get(key: string) {
async get<T>(key: string): Promise<T> {
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<ArrayBuffer> {
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'));
}

View File

@@ -13,32 +13,63 @@ export class RemoteNodeRegistry implements NodeRegistry {
status: "loading" | "ready" | "error" = "loading";
private nodes: Map<string, NodeDefinition> = 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<ArrayBuffer>,
private cache?: AsyncCache<ArrayBuffer | string>,
) { }
async fetchJson(url: string, skipCache = false) {
const finalUrl = `${this.url}/${url}`;
if (!skipCache && this.cache) {
const cachedValue = await this.cache?.get<string>(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<ArrayBuffer>(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) {

View File

@@ -83,7 +83,7 @@ export interface AsyncCache<T = unknown> {
* @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<T | undefined>;
get: <A = T>(key: string) => Promise<A | undefined>;
/**
* Set the value for the given key
* @param key - The key to set the value for