feat: add v5.8.0 features - transactions, pagination, and comprehensive docs
**Transaction System (TIER 1.2)** - Atomic operations with automatic rollback - 36 unit tests + 35 integration tests passing - Full documentation in docs/transactions.md **Duplicate Check Optimization (TIER 1.4)** - Optimized from O(n) to O(log n) using GraphAdjacencyIndex - Uses LSM-tree for efficient lookups - Tests verify performance improvements **GraphIndex Pagination (TIER 1.5)** - Production-scale pagination for high-degree nodes - Backward compatible API - 18 pagination tests passing **Comprehensive Filter Documentation (TIER 1.6)** - Complete operator reference (15 operators) - Compound filters (anyOf, allOf, nested logic) - Common query patterns and troubleshooting guide - 642 lines of new documentation **README Updates** - Added Filter & Query Syntax Guide to Essential Reading - Added Transactions to Core Concepts section All changes tested and production-ready for v5.8.0 release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
52e961760d
commit
e40fee39d8
21 changed files with 5657 additions and 182 deletions
189
src/transaction/TransactionManager.ts
Normal file
189
src/transaction/TransactionManager.ts
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* Transaction Manager
|
||||
*
|
||||
* Manages transaction execution across the system.
|
||||
* Provides high-level API for executing atomic operations.
|
||||
*
|
||||
* Usage:
|
||||
* ```typescript
|
||||
* const txManager = new TransactionManager()
|
||||
*
|
||||
* const result = await txManager.executeTransaction(async (tx) => {
|
||||
* tx.addOperation(operation1)
|
||||
* tx.addOperation(operation2)
|
||||
* return someValue
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
|
||||
import { Transaction } from './Transaction.js'
|
||||
import {
|
||||
TransactionFunction,
|
||||
TransactionResult,
|
||||
TransactionOptions
|
||||
} from './types.js'
|
||||
import { TransactionError } from './errors.js'
|
||||
import { prodLog } from '../utils/logger.js'
|
||||
|
||||
/**
|
||||
* Transaction Manager Statistics
|
||||
*/
|
||||
export interface TransactionStats {
|
||||
totalTransactions: number
|
||||
successfulTransactions: number
|
||||
failedTransactions: number
|
||||
rolledBackTransactions: number
|
||||
averageExecutionTimeMs: number
|
||||
averageOperationsPerTransaction: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction Manager
|
||||
*/
|
||||
export class TransactionManager {
|
||||
private stats: TransactionStats = {
|
||||
totalTransactions: 0,
|
||||
successfulTransactions: 0,
|
||||
failedTransactions: 0,
|
||||
rolledBackTransactions: 0,
|
||||
averageExecutionTimeMs: 0,
|
||||
averageOperationsPerTransaction: 0
|
||||
}
|
||||
|
||||
private totalExecutionTime = 0
|
||||
private totalOperations = 0
|
||||
|
||||
/**
|
||||
* Execute a function within a transaction
|
||||
* All operations succeed atomically or all rollback
|
||||
*
|
||||
* @param fn Function that builds and executes transaction
|
||||
* @param options Transaction execution options
|
||||
* @returns Result from user function
|
||||
* @throws TransactionError if transaction fails
|
||||
*/
|
||||
async executeTransaction<T>(
|
||||
fn: TransactionFunction<T>,
|
||||
options?: TransactionOptions
|
||||
): Promise<T> {
|
||||
const transaction = new Transaction(options)
|
||||
|
||||
this.stats.totalTransactions++
|
||||
|
||||
try {
|
||||
// Execute user function (builds operations list)
|
||||
const result = await fn(transaction)
|
||||
|
||||
// Execute all operations atomically
|
||||
await transaction.execute()
|
||||
|
||||
// Update statistics
|
||||
this.stats.successfulTransactions++
|
||||
this.updateStats(transaction)
|
||||
|
||||
return result
|
||||
|
||||
} catch (error) {
|
||||
// Transaction failed and rolled back
|
||||
this.stats.failedTransactions++
|
||||
|
||||
if (transaction.getState() === 'rolled_back') {
|
||||
this.stats.rolledBackTransactions++
|
||||
}
|
||||
|
||||
this.updateStats(transaction)
|
||||
|
||||
// Re-throw with context
|
||||
if (error instanceof TransactionError) {
|
||||
throw error
|
||||
} else {
|
||||
throw new TransactionError(
|
||||
`Transaction failed: ${(error as Error).message}`,
|
||||
{ cause: error }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a transaction and return detailed result
|
||||
*/
|
||||
async executeTransactionWithResult<T>(
|
||||
fn: TransactionFunction<T>,
|
||||
options?: TransactionOptions
|
||||
): Promise<TransactionResult<T>> {
|
||||
const startTime = Date.now()
|
||||
const transaction = new Transaction(options)
|
||||
|
||||
try {
|
||||
const value = await fn(transaction)
|
||||
await transaction.execute()
|
||||
|
||||
const executionTimeMs = Date.now() - startTime
|
||||
|
||||
return {
|
||||
value,
|
||||
operationCount: transaction.getOperationCount(),
|
||||
executionTimeMs
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
// Transaction failed
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transaction statistics
|
||||
*/
|
||||
getStats(): Readonly<TransactionStats> {
|
||||
return { ...this.stats }
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset transaction statistics
|
||||
*/
|
||||
resetStats(): void {
|
||||
this.stats = {
|
||||
totalTransactions: 0,
|
||||
successfulTransactions: 0,
|
||||
failedTransactions: 0,
|
||||
rolledBackTransactions: 0,
|
||||
averageExecutionTimeMs: 0,
|
||||
averageOperationsPerTransaction: 0
|
||||
}
|
||||
this.totalExecutionTime = 0
|
||||
this.totalOperations = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Update running statistics
|
||||
*/
|
||||
private updateStats(transaction: Transaction): void {
|
||||
const executionTime = transaction.getExecutionTimeMs()
|
||||
const operationCount = transaction.getOperationCount()
|
||||
|
||||
if (executionTime !== undefined) {
|
||||
this.totalExecutionTime += executionTime
|
||||
this.stats.averageExecutionTimeMs =
|
||||
this.totalExecutionTime / this.stats.totalTransactions
|
||||
}
|
||||
|
||||
this.totalOperations += operationCount
|
||||
this.stats.averageOperationsPerTransaction =
|
||||
this.totalOperations / this.stats.totalTransactions
|
||||
}
|
||||
|
||||
/**
|
||||
* Log current statistics
|
||||
*/
|
||||
logStats(): void {
|
||||
prodLog.info('[TransactionManager] Statistics:')
|
||||
prodLog.info(` Total: ${this.stats.totalTransactions}`)
|
||||
prodLog.info(` Successful: ${this.stats.successfulTransactions}`)
|
||||
prodLog.info(` Failed: ${this.stats.failedTransactions}`)
|
||||
prodLog.info(` Rolled back: ${this.stats.rolledBackTransactions}`)
|
||||
prodLog.info(` Avg execution time: ${this.stats.averageExecutionTimeMs.toFixed(2)}ms`)
|
||||
prodLog.info(` Avg operations/tx: ${this.stats.averageOperationsPerTransaction.toFixed(2)}`)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue