durable-execution-storage-test-utils
Version:
Test utilities for validating durable-execution storage implementations
188 lines (141 loc) • 6.98 kB
Markdown
//img.shields.io/npm/v/durable-execution-storage-test-utils)](https://www.npmjs.com/package/durable-execution-storage-test-utils)
[](https://github.com/gpahal/durable-execution/blob/main/LICENSE)
[](https://codecov.io/gh/gpahal/durable-execution?flag=durable-execution-storage-test-utils)
Test utilities for validating [durable-execution](https://github.com/gpahal/durable-execution)
storage implementations.
- npm
```bash
npm install effect durable-execution durable-execution-storage-test-utils
```
- pnpm
```bash
pnpm add effect durable-execution durable-execution-storage-test-utils
```
The primary use case is validating that your storage implementation correctly handles all aspects
of durable task execution:
```ts
import { describe, test } from 'vitest'
import { runStorageTest } from 'durable-execution-storage-test-utils'
import { MyDatabaseStorage } from './my-storage'
describe('MyDatabaseStorage', () => {
test('validates complete storage behavior', async () => {
const storage = new MyDatabaseStorage(connectionString)
await runStorageTest(storage, {
storageCleanup: async () => {
// Cleanup database after tests
await storage.close()
},
})
})
})
```
The test suite will automatically verify:
- ✅ Task lifecycle management (ready → running → completed/failed)
- ✅ Parent-child task relationships and coordination
- ✅ Retry logic with exponential backoff
- ✅ Concurrent execution handling
- ✅ Error propagation and status transitions
- ✅ Background processing (expiration, closure)
- ✅ Storage consistency under high concurrency
See [`tests/index.test.ts`](./tests/index.test.ts) for a complete example using
`InMemoryTaskExecutionsStorage`. The suite internally spins up a `DurableExecutor` and validates
storage behavior across many scenarios.
### Benchmarking
The benchmark suite measures the performance of storage implementations under various workloads.
```ts
import { runStorageBench } from 'durable-execution-storage-test-utils'
import { InMemoryTaskExecutionsStorage } from 'durable-execution'
await runStorageBench("in memory", () => new InMemoryTaskExecutionsStorage())
```
See [`scripts/bench.ts`](./scripts/bench.ts) for a complete example using
`InMemoryTaskExecutionsStorage`. Benchmarks report per-executor timing stats aggregated across
runs.
The main test suite that comprehensively validates storage implementations through complex
scenarios.
**Parameters:**
- `storage: TaskExecutionsStorage` - The storage implementation to test
- `options?: object` - Optional configuration options
- `storageCleanup?: () => void | Promise<void>` - Cleanup function called after tests complete
(default: no cleanup)
- `enableStorageBatching?: boolean` - Whether to enable storage batching (default: false)
- `storageBackgroundBatchingProcessIntraBatchSleepMs?: number` - Artificial delay to add to
storage batching operations (default: 10ms)
**Features tested:**
- **DurableExecutor integration**: Complex task hierarchies with parent-child relationships
- **Concurrency**: 250+ concurrent tasks with proper coordination
- **Retry mechanisms**: Automatic retry logic with configurable options
- **Error handling**: Various error types and failure scenarios
- **Task types**: Simple tasks, parent tasks, sequential tasks, finalize tasks
- **Storage operations**: CRUD operations, batch updates, status transitions
- **Parent-child relationships**: Nested task hierarchies and active child tracking
- **Background processing**: Task expiration, closure processes, and cleanup
**Example:**
```ts
import { runStorageTest } from 'durable-execution-storage-test-utils'
import { InMemoryTaskExecutionsStorage } from 'durable-execution'
describe('My Storage Implementation', () => {
test('comprehensive storage test', async () => {
const storage = new InMemoryTaskExecutionsStorage()
await runStorageTest(storage)
})
})
```
The benchmark suite that measures the performance of storage implementations under various
workloads.
**Parameters:**
- `name: string` - The name of the storage implementation
- `getStorage: () => TaskExecutionsStorage | Promise<TaskExecutionsStorage>` - A function that
returns the storage implementation to test
- `options?: object` - Optional configuration options
- `storageCleanup?: (storage: TaskExecutionsStorage) => void | Promise<void>` - Cleanup function
called after benchmark completes (default: no cleanup)
- `storageSlowdownMs?: number` - Artificial delay to add to storage operations (default: 0)
- `executorsCount?: number` - Number of concurrent executors to run (default: 1)
- `enableStorageBatching?: boolean` - Whether to enable storage batching. (default: false)
- `storageBackgroundBatchingProcessIntraBatchSleepMs?: number` - Artificial delay to add to
storage batching operations (default: 10ms)
- `childTasksCount?: number` - Number of child tasks per parent task (default: 50)
- `parentTasksCount?: number` - Number of parent tasks to create (default: 100)
- `sequentialTasksCount?: number` - Number of sequential tasks to create (default: 100)
- `pollingTasksCount?: number` - Number of polling tasks to create (default: 100)
**Example:**
```ts
import { runStorageBench } from 'durable-execution-storage-test-utils'
import { InMemoryTaskExecutionsStorage } from 'durable-execution'
await runStorageBench("in memory", () => new InMemoryTaskExecutionsStorage())
// With cleanup for database storage
await runStorageBench(
"custom",
() => new CustomTaskExecutionsStorage({ url: process.env.DATABASE_URL! }),
{
storageCleanup: async (storage) => {
// Clean up database after benchmark
await storage.close()
},
executorsCount: 1,
parentTasksCount: 50,
childTasksCount: 25,
},
)
```
Utilities for managing temporary files and directories in tests:
- `withTemporaryDirectory(fn: (dirPath: string) => Promise<void>)` - Creates and cleans up a
temporary directory
- `withTemporaryFile(filename: string, fn: (filePath: string) => Promise<void>)` - Creates and
cleans up a temporary file
- `cleanupTemporaryFiles()` - Removes any leftover temporary files
- [Durable Execution docs](https://gpahal.github.io/durable-execution)
- [GitHub](https://github.com/gpahal/durable-execution)
- [NPM package](https://www.npmjs.com/package/durable-execution-storage-test-utils)
This project is licensed under the MIT License. See the
[ ](https://github.com/gpahal/durable-execution/blob/main/LICENSE) file for details.
[![NPM Version](https: