UNPKG

@signaldb/core

Version:

SignalDB is a client-side database that provides a simple MongoDB-like interface to the data with first-class typescript support to achieve an optimistic UI. Data persistence can be achieved by using storage providers that store the data through a JSON in

82 lines (81 loc) 3.49 kB
const require_createPersistenceAdapter = require("./index24.cjs.js"); //#region src/persistence/combinePersistenceAdapters.ts /** * Creates a function that executes two asynchronous functions sequentially. * The first function is tried first, and if it resolves, its value is used. * If the first function fails or a fallback is required, the second function is executed. * An optional cache mechanism can store the result temporarily to improve performance. * @template Arguments - The argument types for the promise functions. * @template ReturnValue - The return value type of the promise functions. * @param firstResolvingPromiseFunction - The primary promise-based function to execute. * @param secondResolvingPromiseFunction - The secondary fallback promise-based function to execute. * @param [options] - Optional configuration. * @param [options.onResolve] - Callback executed when a promise resolves. * @param [options.cacheTimeout] - Time (in ms) to cache the resolved result. * @returns A function that executes the two promises as described. */ function createTemporaryFallbackExecutor(firstResolvingPromiseFunction, secondResolvingPromiseFunction, options) { const cacheTimeout = options?.cacheTimeout ?? 0; let isResolved = false; let resolvedValue = null; let timeout = null; let secondaryPromise = null; return (...args) => { if (secondaryPromise == null) { if (timeout) { clearTimeout(timeout); timeout = null; } secondaryPromise = secondResolvingPromiseFunction(...args).then((result) => { if (cacheTimeout > 0) timeout = setTimeout(() => { isResolved = false; resolvedValue = null; secondaryPromise = null; }, cacheTimeout); isResolved = true; resolvedValue = result; if (options?.onResolve) options.onResolve(resolvedValue); return result; }); } else if (isResolved) return secondaryPromise; return firstResolvingPromiseFunction(...args); }; } /** * Combines two persistence adapters (fast and slow) into a single interface. * The fast adapter is used for quick read and write operations, while the slow adapter * ensures data persistence and durability. The adapters sync automatically on read and save operations. * @template T - The type of the persisted data items. * @template I - The type of the identifier for persisted data items. * @param slowAdapter - The slow persistence adapter for long-term storage. * @param fastAdapter - The fast persistence adapter for quick access. * @returns A combined persistence adapter that manages synchronization between the two adapters. */ function combinePersistenceAdapters(slowAdapter, fastAdapter) { let handleChange = null; const readExecutor = createTemporaryFallbackExecutor(() => fastAdapter.load(), () => slowAdapter.load(), { cacheTimeout: 100, onResolve: (result) => { if (handleChange) handleChange(); fastAdapter.save(result.items || [], { added: result.changes?.added || [], modified: result.changes?.modified || [], removed: result.changes?.removed || [] }); } }); return require_createPersistenceAdapter.default({ async register(onChange) { handleChange = onChange; await Promise.all([slowAdapter.register(onChange), fastAdapter.register(onChange)]); }, async load() { return readExecutor(); }, async save(items, changes) { await Promise.all([fastAdapter.save(items, changes), slowAdapter.save(items, changes)]); } }); } //#endregion exports.default = combinePersistenceAdapters;