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
361
src/transaction/operations/IndexOperations.ts
Normal file
361
src/transaction/operations/IndexOperations.ts
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
/**
|
||||
* Index Operations with Rollback Support
|
||||
*
|
||||
* Provides transactional operations for all indexes:
|
||||
* - TypeAwareHNSWIndex (per-type vector indexes)
|
||||
* - HNSWIndex (legacy/fallback vector index)
|
||||
* - MetadataIndexManager (roaring bitmap filtering)
|
||||
* - GraphAdjacencyIndex (LSM-tree graph storage)
|
||||
*
|
||||
* Each operation can be executed and rolled back atomically.
|
||||
*/
|
||||
|
||||
import type { HNSWIndex } from '../../hnsw/hnswIndex.js'
|
||||
import type { TypeAwareHNSWIndex } from '../../hnsw/typeAwareHNSWIndex.js'
|
||||
import type { MetadataIndexManager } from '../../utils/metadataIndex.js'
|
||||
import type { GraphAdjacencyIndex } from '../../graph/graphAdjacencyIndex.js'
|
||||
import type { NounType } from '../../types/graphTypes.js'
|
||||
import type { GraphVerb } from '../../coreTypes.js'
|
||||
import type { Operation, RollbackAction } from '../types.js'
|
||||
|
||||
/**
|
||||
* Add to HNSW index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Remove item from index
|
||||
*
|
||||
* Note: Works with both HNSWIndex and TypeAwareHNSWIndex
|
||||
*/
|
||||
export class AddToHNSWOperation implements Operation {
|
||||
readonly name = 'AddToHNSW'
|
||||
|
||||
constructor(
|
||||
private readonly index: HNSWIndex,
|
||||
private readonly id: string,
|
||||
private readonly vector: number[]
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Check if item already exists (for rollback decision)
|
||||
const existed = await this.itemExists(this.id)
|
||||
|
||||
// Add to index
|
||||
await this.index.addItem({ id: this.id, vector: this.vector })
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (!existed) {
|
||||
// Remove newly added item
|
||||
await this.index.removeItem(this.id)
|
||||
}
|
||||
// If item existed before, we don't rollback (update is OK)
|
||||
// This prevents index corruption from removing pre-existing items
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item exists in index
|
||||
*/
|
||||
private async itemExists(id: string): Promise<boolean> {
|
||||
try {
|
||||
// Try to get item - if exists, no error
|
||||
await (this.index as any).getItem?.(id)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to TypeAwareHNSW index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Remove item from type-specific index
|
||||
*/
|
||||
export class AddToTypeAwareHNSWOperation implements Operation {
|
||||
readonly name = 'AddToTypeAwareHNSW'
|
||||
|
||||
constructor(
|
||||
private readonly index: TypeAwareHNSWIndex,
|
||||
private readonly id: string,
|
||||
private readonly vector: number[],
|
||||
private readonly nounType: NounType
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Check if item already exists
|
||||
const existed = await this.itemExists(this.id, this.nounType)
|
||||
|
||||
// Add to type-specific index
|
||||
await this.index.addItem({ id: this.id, vector: this.vector }, this.nounType)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (!existed) {
|
||||
// Remove newly added item from type-specific index
|
||||
await this.index.removeItem(this.id, this.nounType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item exists in type-specific index
|
||||
*/
|
||||
private async itemExists(id: string, type: NounType): Promise<boolean> {
|
||||
try {
|
||||
const index = (this.index as any).getIndexForType?.(type)
|
||||
if (index) {
|
||||
await index.getItem?.(id)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from HNSW index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Re-add item to index with original vector
|
||||
*
|
||||
* Note: Requires storing the vector for rollback
|
||||
*/
|
||||
export class RemoveFromHNSWOperation implements Operation {
|
||||
readonly name = 'RemoveFromHNSW'
|
||||
|
||||
constructor(
|
||||
private readonly index: HNSWIndex,
|
||||
private readonly id: string,
|
||||
private readonly vector: number[] // Required for rollback
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Remove from index
|
||||
await this.index.removeItem(this.id)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Re-add item with original vector
|
||||
await this.index.addItem({ id: this.id, vector: this.vector })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from TypeAwareHNSW index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Re-add item to type-specific index with original vector
|
||||
*/
|
||||
export class RemoveFromTypeAwareHNSWOperation implements Operation {
|
||||
readonly name = 'RemoveFromTypeAwareHNSW'
|
||||
|
||||
constructor(
|
||||
private readonly index: TypeAwareHNSWIndex,
|
||||
private readonly id: string,
|
||||
private readonly vector: number[], // Required for rollback
|
||||
private readonly nounType: NounType
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Remove from type-specific index
|
||||
await this.index.removeItem(this.id, this.nounType)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Re-add item with original vector to type-specific index
|
||||
await this.index.addItem({ id: this.id, vector: this.vector }, this.nounType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to metadata index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Remove item from index
|
||||
*/
|
||||
export class AddToMetadataIndexOperation implements Operation {
|
||||
readonly name = 'AddToMetadataIndex'
|
||||
|
||||
constructor(
|
||||
private readonly index: MetadataIndexManager,
|
||||
private readonly id: string,
|
||||
private readonly entity: any // Entity or metadata structure
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Add to metadata index (skipFlush=true for transaction atomicity)
|
||||
await this.index.addToIndex(this.id, this.entity, true)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Remove from metadata index
|
||||
await this.index.removeFromIndex(this.id, this.entity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from metadata index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Re-add item to index with original metadata
|
||||
*/
|
||||
export class RemoveFromMetadataIndexOperation implements Operation {
|
||||
readonly name = 'RemoveFromMetadataIndex'
|
||||
|
||||
constructor(
|
||||
private readonly index: MetadataIndexManager,
|
||||
private readonly id: string,
|
||||
private readonly entity: any // Required for rollback
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Remove from metadata index
|
||||
await this.index.removeFromIndex(this.id, this.entity)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Re-add with original metadata (skipFlush=true)
|
||||
await this.index.addToIndex(this.id, this.entity, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add verb to graph index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Remove verb from graph index
|
||||
*/
|
||||
export class AddToGraphIndexOperation implements Operation {
|
||||
readonly name = 'AddToGraphIndex'
|
||||
|
||||
constructor(
|
||||
private readonly index: GraphAdjacencyIndex,
|
||||
private readonly verb: GraphVerb
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Add verb to graph index
|
||||
await this.index.addVerb(this.verb)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Remove verb from graph index
|
||||
await this.index.removeVerb(this.verb.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove verb from graph index with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Re-add verb to graph index
|
||||
*/
|
||||
export class RemoveFromGraphIndexOperation implements Operation {
|
||||
readonly name = 'RemoveFromGraphIndex'
|
||||
|
||||
constructor(
|
||||
private readonly index: GraphAdjacencyIndex,
|
||||
private readonly verb: GraphVerb // Required for rollback
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Remove verb from graph index
|
||||
await this.index.removeVerb(this.verb.id)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Re-add verb with original data
|
||||
await this.index.addVerb(this.verb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch operation: Add multiple items to HNSW index
|
||||
*
|
||||
* Useful for bulk imports with transaction support.
|
||||
* Rolls back all items if any fail.
|
||||
*/
|
||||
export class BatchAddToHNSWOperation implements Operation {
|
||||
readonly name = 'BatchAddToHNSW'
|
||||
|
||||
private operations: AddToHNSWOperation[]
|
||||
|
||||
constructor(
|
||||
index: HNSWIndex,
|
||||
items: Array<{ id: string; vector: number[] }>
|
||||
) {
|
||||
this.operations = items.map(
|
||||
item => new AddToHNSWOperation(index, item.id, item.vector)
|
||||
)
|
||||
}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
const rollbackActions: RollbackAction[] = []
|
||||
|
||||
// Execute all operations
|
||||
for (const op of this.operations) {
|
||||
const rollback = await op.execute()
|
||||
if (rollback) {
|
||||
rollbackActions.push(rollback)
|
||||
}
|
||||
}
|
||||
|
||||
// Return combined rollback action
|
||||
return async () => {
|
||||
// Execute all rollbacks in reverse order
|
||||
for (let i = rollbackActions.length - 1; i >= 0; i--) {
|
||||
await rollbackActions[i]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch operation: Add multiple entities to metadata index
|
||||
*
|
||||
* Useful for bulk imports with transaction support.
|
||||
*/
|
||||
export class BatchAddToMetadataIndexOperation implements Operation {
|
||||
readonly name = 'BatchAddToMetadataIndex'
|
||||
|
||||
private operations: AddToMetadataIndexOperation[]
|
||||
|
||||
constructor(
|
||||
index: MetadataIndexManager,
|
||||
items: Array<{ id: string; entity: any }>
|
||||
) {
|
||||
this.operations = items.map(
|
||||
item => new AddToMetadataIndexOperation(index, item.id, item.entity)
|
||||
)
|
||||
}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
const rollbackActions: RollbackAction[] = []
|
||||
|
||||
// Execute all operations
|
||||
for (const op of this.operations) {
|
||||
const rollback = await op.execute()
|
||||
if (rollback) {
|
||||
rollbackActions.push(rollback)
|
||||
}
|
||||
}
|
||||
|
||||
// Return combined rollback action
|
||||
return async () => {
|
||||
// Execute all rollbacks in reverse order
|
||||
for (let i = rollbackActions.length - 1; i >= 0; i--) {
|
||||
await rollbackActions[i]()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
301
src/transaction/operations/StorageOperations.ts
Normal file
301
src/transaction/operations/StorageOperations.ts
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
/**
|
||||
* Storage Operations with Rollback Support
|
||||
*
|
||||
* Provides transactional operations for all storage adapters.
|
||||
* Each operation can be executed and rolled back atomically.
|
||||
*
|
||||
* Supports:
|
||||
* - All 8 storage adapters (FileSystem, S3, Memory, OPFS, GCS, Azure, R2, TypeAware)
|
||||
* - Nouns (entities) and Verbs (relationships)
|
||||
* - Metadata and vector data
|
||||
* - COW (Copy-on-Write) storage
|
||||
*/
|
||||
|
||||
import type { StorageAdapter, HNSWNoun, HNSWVerb, NounMetadata, VerbMetadata } from '../../coreTypes.js'
|
||||
import type { Operation, RollbackAction } from '../types.js'
|
||||
|
||||
/**
|
||||
* Save noun metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - If metadata existed: Restore previous metadata
|
||||
* - If metadata was new: Delete metadata
|
||||
*/
|
||||
export class SaveNounMetadataOperation implements Operation {
|
||||
readonly name = 'SaveNounMetadata'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly id: string,
|
||||
private readonly metadata: NounMetadata
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get existing metadata (for rollback)
|
||||
const previousMetadata = await this.storage.getNounMetadata(this.id)
|
||||
|
||||
// Save new metadata
|
||||
await this.storage.saveNounMetadata(this.id, this.metadata)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (previousMetadata) {
|
||||
// Restore previous metadata
|
||||
await this.storage.saveNounMetadata(this.id, previousMetadata)
|
||||
} else {
|
||||
// Delete newly created metadata
|
||||
await this.storage.deleteNounMetadata(this.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save noun (vector data) with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - If noun existed: Restore previous noun
|
||||
* - If noun was new: Delete noun (if deleteNoun exists on adapter)
|
||||
*
|
||||
* Note: Not all adapters implement deleteNoun - this is acceptable
|
||||
* because orphaned vector data without metadata is invisible to queries
|
||||
*/
|
||||
export class SaveNounOperation implements Operation {
|
||||
readonly name = 'SaveNoun'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly noun: HNSWNoun
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get existing noun (for rollback)
|
||||
const previousNoun = await this.storage.getNoun(this.noun.id)
|
||||
|
||||
// Save new noun
|
||||
await this.storage.saveNoun(this.noun)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (previousNoun) {
|
||||
// Restore previous noun (extract just vector data)
|
||||
const nounData: HNSWNoun = {
|
||||
id: previousNoun.id,
|
||||
vector: previousNoun.vector,
|
||||
connections: previousNoun.connections || new Map(),
|
||||
level: previousNoun.level || 0
|
||||
}
|
||||
await this.storage.saveNoun(nounData)
|
||||
} else {
|
||||
// Delete newly created noun (if adapter supports it)
|
||||
// Note: Not all adapters implement deleteNoun
|
||||
// This is acceptable - metadata deletion makes entity invisible
|
||||
if ('deleteNoun' in this.storage && typeof (this.storage as any).deleteNoun === 'function') {
|
||||
await (this.storage as any).deleteNoun(this.noun.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete noun metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Restore deleted metadata
|
||||
*/
|
||||
export class DeleteNounMetadataOperation implements Operation {
|
||||
readonly name = 'DeleteNounMetadata'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly id: string
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get metadata before deletion (for rollback)
|
||||
const previousMetadata = await this.storage.getNounMetadata(this.id)
|
||||
|
||||
if (!previousMetadata) {
|
||||
// Nothing to delete - no rollback needed
|
||||
return async () => {}
|
||||
}
|
||||
|
||||
// Delete metadata
|
||||
await this.storage.deleteNounMetadata(this.id)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Restore deleted metadata
|
||||
await this.storage.saveNounMetadata(this.id, previousMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save verb metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - If metadata existed: Restore previous metadata
|
||||
* - If metadata was new: Delete metadata
|
||||
*/
|
||||
export class SaveVerbMetadataOperation implements Operation {
|
||||
readonly name = 'SaveVerbMetadata'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly id: string,
|
||||
private readonly metadata: VerbMetadata
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get existing metadata (for rollback)
|
||||
const previousMetadata = await this.storage.getVerbMetadata(this.id)
|
||||
|
||||
// Save new metadata
|
||||
await this.storage.saveVerbMetadata(this.id, this.metadata)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (previousMetadata) {
|
||||
// Restore previous metadata
|
||||
await this.storage.saveVerbMetadata(this.id, previousMetadata)
|
||||
} else {
|
||||
// Delete newly created verb (metadata + vector)
|
||||
// Note: StorageAdapter has deleteVerb but not deleteVerbMetadata
|
||||
await this.storage.deleteVerb(this.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save verb (vector data) with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - If verb existed: Restore previous verb
|
||||
* - If verb was new: Delete verb (if deleteVerb exists on adapter)
|
||||
*/
|
||||
export class SaveVerbOperation implements Operation {
|
||||
readonly name = 'SaveVerb'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly verb: HNSWVerb
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get existing verb (for rollback)
|
||||
const previousVerb = await this.storage.getVerb(this.verb.id)
|
||||
|
||||
// Save new verb
|
||||
await this.storage.saveVerb(this.verb)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
if (previousVerb) {
|
||||
// Restore previous verb (extract just vector data)
|
||||
const verbData: HNSWVerb = {
|
||||
id: previousVerb.id,
|
||||
sourceId: previousVerb.sourceId,
|
||||
targetId: previousVerb.targetId,
|
||||
verb: previousVerb.verb,
|
||||
vector: previousVerb.vector,
|
||||
connections: previousVerb.connections || new Map()
|
||||
}
|
||||
await this.storage.saveVerb(verbData)
|
||||
} else {
|
||||
// Delete newly created verb (if adapter supports it)
|
||||
if ('deleteVerb' in this.storage && typeof (this.storage as any).deleteVerb === 'function') {
|
||||
await (this.storage as any).deleteVerb(this.verb.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete verb metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Restore deleted metadata
|
||||
*/
|
||||
export class DeleteVerbMetadataOperation implements Operation {
|
||||
readonly name = 'DeleteVerbMetadata'
|
||||
|
||||
constructor(
|
||||
private readonly storage: StorageAdapter,
|
||||
private readonly id: string
|
||||
) {}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
// Get metadata before deletion (for rollback)
|
||||
const previousMetadata = await this.storage.getVerbMetadata(this.id)
|
||||
|
||||
if (!previousMetadata) {
|
||||
// Nothing to delete - no rollback needed
|
||||
return async () => {}
|
||||
}
|
||||
|
||||
// Delete verb (metadata + vector)
|
||||
// Note: StorageAdapter has deleteVerb but not deleteVerbMetadata
|
||||
await this.storage.deleteVerb(this.id)
|
||||
|
||||
// Return rollback action
|
||||
return async () => {
|
||||
// Restore deleted metadata
|
||||
await this.storage.saveVerbMetadata(this.id, previousMetadata)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update noun metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Restore previous metadata
|
||||
*
|
||||
* Note: This is a convenience operation that wraps SaveNounMetadataOperation
|
||||
* with explicit "update" semantics
|
||||
*/
|
||||
export class UpdateNounMetadataOperation implements Operation {
|
||||
readonly name = 'UpdateNounMetadata'
|
||||
|
||||
private saveOperation: SaveNounMetadataOperation
|
||||
|
||||
constructor(
|
||||
storage: StorageAdapter,
|
||||
id: string,
|
||||
metadata: NounMetadata
|
||||
) {
|
||||
this.saveOperation = new SaveNounMetadataOperation(storage, id, metadata)
|
||||
}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
return await this.saveOperation.execute()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update verb metadata with rollback support
|
||||
*
|
||||
* Rollback strategy:
|
||||
* - Restore previous metadata
|
||||
*/
|
||||
export class UpdateVerbMetadataOperation implements Operation {
|
||||
readonly name = 'UpdateVerbMetadata'
|
||||
|
||||
private saveOperation: SaveVerbMetadataOperation
|
||||
|
||||
constructor(
|
||||
storage: StorageAdapter,
|
||||
id: string,
|
||||
metadata: VerbMetadata
|
||||
) {
|
||||
this.saveOperation = new SaveVerbMetadataOperation(storage, id, metadata)
|
||||
}
|
||||
|
||||
async execute(): Promise<RollbackAction> {
|
||||
return await this.saveOperation.execute()
|
||||
}
|
||||
}
|
||||
34
src/transaction/operations/index.ts
Normal file
34
src/transaction/operations/index.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Transaction Operations
|
||||
*
|
||||
* Re-exports all transactional operations for storage and indexes.
|
||||
* These operations provide atomicity with rollback support.
|
||||
*
|
||||
* @module transaction/operations
|
||||
*/
|
||||
|
||||
// Storage Operations
|
||||
export {
|
||||
SaveNounMetadataOperation,
|
||||
SaveNounOperation,
|
||||
DeleteNounMetadataOperation,
|
||||
SaveVerbMetadataOperation,
|
||||
SaveVerbOperation,
|
||||
DeleteVerbMetadataOperation,
|
||||
UpdateNounMetadataOperation,
|
||||
UpdateVerbMetadataOperation
|
||||
} from './StorageOperations.js'
|
||||
|
||||
// Index Operations
|
||||
export {
|
||||
AddToHNSWOperation,
|
||||
AddToTypeAwareHNSWOperation,
|
||||
RemoveFromHNSWOperation,
|
||||
RemoveFromTypeAwareHNSWOperation,
|
||||
AddToMetadataIndexOperation,
|
||||
RemoveFromMetadataIndexOperation,
|
||||
AddToGraphIndexOperation,
|
||||
RemoveFromGraphIndexOperation,
|
||||
BatchAddToHNSWOperation,
|
||||
BatchAddToMetadataIndexOperation
|
||||
} from './IndexOperations.js'
|
||||
Loading…
Add table
Add a link
Reference in a new issue