Files
xo-stack/packages/stack/src/storage/store-inmemory-synced.ts
T

83 lines
2.2 KiB
TypeScript

import { BaseStore } from './base-store.js';
import { StoreInMemory } from './store-inmemory.js';
/**
* Storage Adapter that takes another Storage Adapter (e.g. IndexedDB) and "syncs" its contents to system memory for faster read access.
*
* All read operations will use system memory - all write operations will use the provided adapter.
*/
export class StoreInMemorySynced extends BaseStore {
constructor(
private inMemoryCache: StoreInMemory,
private store: BaseStore,
) {
super();
// Hook into all write operations so that we can sync the In-Memory cache.
this.store.on('set', async (payload) => {
await this.inMemoryCache.set(payload.key, payload.value);
this.emit('set', { key: payload.key, value: payload.value });
});
this.store.on('delete', async (payload) => {
await this.inMemoryCache.delete(payload.key);
this.emit('delete', { key: payload.key });
});
this.store.on('clear', async () => {
await this.inMemoryCache.clear();
this.emit('clear', undefined);
});
}
static async create(store: BaseStore) {
// Instantiate in-memory cache and IndexedDB.
const inMemoryCache = new StoreInMemory();
// Create instance of this store.
const memorySyncedStore = new this(inMemoryCache, store);
// Sync the data from IndexedDB into the In-Memory cache.
const indexedDBEntries = await store.all();
for (let [key, value] of Object.entries(indexedDBEntries)) {
inMemoryCache.set(key, value);
}
// Return our instance of this store.
return memorySyncedStore;
}
async all<T>() {
return await this.inMemoryCache.all<T>();
}
async keys() {
return await this.inMemoryCache.keys();
}
async get<T>(key: string) {
// TODO: Consider whether you want to structuredClone this to prevent mutation.
return await this.inMemoryCache.get<T>(key);
}
async set<T>(key: string, value: T) {
await this.store.set(key, value);
}
async delete(key: string) {
await this.store.delete(key);
}
async clear() {
await this.store.clear();
}
async has(key: string) {
return await this.inMemoryCache.has(key);
}
async close() {
await this.store.close();
}
}