UNPKG

durable-execution-storage-test-utils

Version:

Test utilities for validating durable-execution storage implementations

179 lines 7.54 kB
import { type TaskExecutionsStorage } from 'durable-execution'; /** * Runs a comprehensive test suite to validate a TaskExecutionsStorage implementation. * * This function executes an extensive set of tests that verify the correctness of a storage * implementation, including ACID compliance, concurrent access patterns, and all required * storage operations. It tests both high-level DurableExecutor functionality and low-level * storage operations. * * The test suite includes: * - Task execution lifecycle (ready → running → completed/failed) * - Parent-child task relationships and hierarchies * - Sequential task chains * - Retry mechanisms and error handling * - Concurrent task execution (250+ parallel tasks) * - Task expiration and timeout handling * - Promise cancellation flows * - Atomic transactions and batch operations * - Race condition handling * * @example * ```ts * import { InMemoryTaskExecutionsStorage } from 'durable-execution' * import { runStorageTest } from 'durable-execution-storage-test-utils' * * const storage = new InMemoryTaskExecutionsStorage() * await runStorageTest(storage) * ``` * * @example * ```ts * // With cleanup for database storage * const storage = new CustomTaskExecutionsStorage({ url: process.env.DATABASE_URL! }) * await runStorageTest(storage, { * storageCleanup: async () => { * await db.delete(taskExecutions) * }, * }) * ``` * * @param storage - The TaskExecutionsStorage implementation to test * @param options - Optional options * @param options.storageCleanup - Optional cleanup function to run after tests complete (e.g., to * remove test database) * @param options.enableStorageBatching - Whether to enable storage batching. * @param options.storageBackgroundBatchingProcessIntraBatchSleepMs - The sleep duration between * background batching process iterations. Only applicable if storage batching is enabled. If not * provided, defaults to 10ms. * @throws Will throw if any storage operation fails validation or doesn't meet ACID requirements */ export declare function runStorageTest(storage: TaskExecutionsStorage, { storageCleanup, enableStorageBatching, storageBackgroundBatchingProcessIntraBatchSleepMs, }?: { storageCleanup?: () => void | Promise<void>; enableStorageBatching?: boolean; storageBackgroundBatchingProcessIntraBatchSleepMs?: number; }): Promise<void>; /** * Runs a benchmark suite to measure the performance of a TaskExecutionsStorage implementation. * * @example * ```ts * import { InMemoryTaskExecutionsStorage } from 'durable-execution' * import { runStorageBench } from 'durable-execution-storage-test-utils' * * await runStorageBench("in memory", () => new InMemoryTaskExecutionsStorage()) * ``` * * @example * ```ts * // With cleanup for database storage * await runStorageBench( * "custom", * () => new CustomTaskExecutionsStorage({ url: process.env.DATABASE_URL! }), * { * storageCleanup: async (storage) => { * await storage.delete(taskExecutions) * }, * }, * ) * ``` * * @param name - Name of the storage implementation to test * @param getStorage - A function that returns a TaskExecutionsStorage implementation to test * @param options - Optional options object * @param options.storageCleanup - Optional cleanup function to run after tests complete (e.g., to * remove test database) * @param options.storageSlowdownMs - Optional slowdown factor for storage operations. * @param options.executorsCount - Number of executors to run in parallel * @param options.enableStorageBatching - Whether to enable storage batching. If not provided, * defaults to false. * @param options.storageBackgroundBatchingProcessIntraBatchSleepMs - The sleep duration between * background batching process iterations. Only applicable if storage batching is enabled. If not * provided, defaults to 10ms. * @param options.totalIterations - Number of iterations to run the benchmark for. If not provided, * defaults to 2. * @param options.childTasksCount - Number of child tasks to run in parallel * @param options.parentTasksCount - Number of parent tasks to run in parallel * @param options.sequentialTasksCount - Number of sequential tasks to run in parallel * @param options.loopingTasksCount - Number of looping tasks to run in parallel */ export declare function runStorageBench<TStorage extends TaskExecutionsStorage>(name: string, getStorage: (index: number) => TStorage | Promise<TStorage>, { storageCleanup, storageSlowdownMs, executorsCount, enableStorageBatching, storageBackgroundBatchingProcessIntraBatchSleepMs, totalIterations, childTasksCount, parentTasksCount, sequentialTasksCount, loopingTasksCount, }?: { storageCleanup?: (storage: TStorage) => void | Promise<void>; storageSlowdownMs?: number; executorsCount?: number; enableStorageBatching?: boolean; storageBackgroundBatchingProcessIntraBatchSleepMs?: number; totalIterations?: number; childTasksCount?: number; parentTasksCount?: number; sequentialTasksCount?: number; loopingTasksCount?: number; }): Promise<void>; /** * Executes a function with a temporary directory that is automatically cleaned up. * * Creates a temporary directory with a unique name prefixed with '.tmp_' and ensures it's * removed after the function completes, even if an error occurs. * * @example * ```ts * await withTemporaryDirectory(async (tmpDir) => { * const testFile = path.join(tmpDir, 'test.db') * // Use the temporary directory... * await fs.writeFile(testFile, 'test data') * }) * // Directory is automatically cleaned up * ``` * * * @param fn - Function to execute with the temporary directory path * @throws Re-throws any error from the provided function */ export declare function withTemporaryDirectory(fn: (dirPath: string) => Promise<void>): Promise<void>; /** * Executes a function with a temporary file path that is automatically cleaned up. * * Creates a temporary directory, constructs a file path with the given filename, and ensures the * directory is removed after the function completes. The file itself doesn't need to be created - * this just provides a safe file path. * * @example * ```ts * await withTemporaryFile('test.db', async (filePath) => { * const storage = new CustomTaskExecutionsStorage(filePath) * await runStorageTest(storage) * }) * // Temporary directory and file are automatically cleaned up * ``` * * @param filename - Name of the file within the temporary directory * @param fn - Function to execute with the temporary file path * @throws Re-throws any error from the provided function */ export declare function withTemporaryFile(filename: string, fn: (file: string) => Promise<void>): Promise<void>; /** * Cleans up any remaining temporary files and directories created by this library. * * Searches the current working directory for files and directories starting with '.tmp_' and * removes them. This function is safe to call multiple times and ignores any errors during * cleanup. * * Useful for test cleanup hooks or when temporary files weren't properly cleaned up due to * unexpected process termination. * * @example * ```ts * // In a test suite * afterAll(async () => { * await cleanupTemporaryFiles() * }) * ``` * * @example * ```ts * // Manual cleanup * await cleanupTemporaryFiles() * ``` */ export declare function cleanupTemporaryFiles(): Promise<void>; //# sourceMappingURL=index.d.ts.map