- The transact apply budget scales with the batch — max(30s, opCount x 2s) — or is exactly the caller's new TransactOptions.timeoutMs. A flat 30s cap silently limited honest bulk work to ~15 operations on network-attached storage (~2s/op measured in a production import) while looking generous for small batches. Internal batch paths (removeMany chunks) get the same scaling via the shared transactTimeoutBudget helper. - TransactionTimeoutError now reports the operation it stopped at as i/N with the operation's name, elapsed vs budgeted time, and states the batch rolled back atomically and is retryable; context carries the fields programmatically. - The transact operational envelope is documented (optimistic-concurrency guide): budget math, chunking with ifAbsent idempotency, when to reach for addMany vs transact, and the precompute pattern (embedBatch + per-op vector) that keeps inference out of the commit path. - Embedding claims made honest per an end-to-end probe of the built dist: batch and single embedding paths produce bit-identical vectors and a vector-supplied add is fully searchable, but batch throughput on the default WASM engine measures comparable to sequential (~160ms/text) — the 5-10x speedup claim in the addMany JSDoc is replaced with the measured reality and the actual win (inference outside the budgeted write path).
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
/**
|
|
* Transaction System Errors
|
|
*
|
|
* Provides detailed error information for transaction failures.
|
|
*/
|
|
|
|
/**
|
|
* Base class for all transaction errors
|
|
*/
|
|
export class TransactionError extends Error {
|
|
constructor(
|
|
message: string,
|
|
public readonly context?: Record<string, any>
|
|
) {
|
|
super(message)
|
|
this.name = 'TransactionError'
|
|
Error.captureStackTrace(this, this.constructor)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error during transaction execution
|
|
*/
|
|
export class TransactionExecutionError extends TransactionError {
|
|
constructor(
|
|
message: string,
|
|
public readonly operationIndex: number,
|
|
public readonly operationName: string | undefined,
|
|
public override readonly cause: Error
|
|
) {
|
|
super(message, {
|
|
operationIndex,
|
|
operationName,
|
|
cause: cause.message
|
|
})
|
|
this.name = 'TransactionExecutionError'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error during transaction rollback
|
|
*/
|
|
export class TransactionRollbackError extends TransactionError {
|
|
constructor(
|
|
message: string,
|
|
public readonly originalError: Error,
|
|
public readonly rollbackErrors: Error[]
|
|
) {
|
|
super(message, {
|
|
originalError: originalError.message,
|
|
rollbackErrorCount: rollbackErrors.length,
|
|
rollbackErrors: rollbackErrors.map(e => e.message)
|
|
})
|
|
this.name = 'TransactionRollbackError'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error for invalid transaction state
|
|
*/
|
|
export class InvalidTransactionStateError extends TransactionError {
|
|
constructor(
|
|
currentState: string,
|
|
attemptedAction: string
|
|
) {
|
|
super(
|
|
`Cannot ${attemptedAction}: transaction is in state '${currentState}'`,
|
|
{ currentState, attemptedAction }
|
|
)
|
|
this.name = 'InvalidTransactionStateError'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Error for transaction timeout
|
|
*/
|
|
export class TransactionTimeoutError extends TransactionError {
|
|
constructor(
|
|
timeoutMs: number,
|
|
operationIndex: number,
|
|
telemetry?: {
|
|
elapsedMs?: number
|
|
totalOperations?: number
|
|
operationName?: string
|
|
}
|
|
) {
|
|
const progress =
|
|
telemetry?.totalOperations !== undefined
|
|
? `${operationIndex}/${telemetry.totalOperations}`
|
|
: String(operationIndex)
|
|
const name = telemetry?.operationName ? ` ('${telemetry.operationName}')` : ''
|
|
const elapsed =
|
|
telemetry?.elapsedMs !== undefined ? `${telemetry.elapsedMs}ms elapsed, ` : ''
|
|
super(
|
|
`Transaction timed out at operation ${progress}${name} — ${elapsed}budget ${timeoutMs}ms. ` +
|
|
`The batch rolled back atomically; retry with a higher timeoutMs or a smaller batch.`,
|
|
{ timeoutMs, operationIndex, ...telemetry }
|
|
)
|
|
this.name = 'TransactionTimeoutError'
|
|
}
|
|
}
|