durable-execution-storage-test-utils
Version:
Test utilities for validating durable-execution storage implementations
179 lines • 7.54 kB
TypeScript
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