perf(storage): simplify cloud adapters to always-on write buffering
Removes dynamic high-volume mode switching complexity from all cloud storage adapters (GCS, S3, R2, Azure). Write buffering is now always enabled for consistent, predictable performance. Changes: - Remove highVolumeMode, lastVolumeCheck, volumeCheckInterval properties - Remove checkVolumeMode() methods (~100 lines in S3 alone) - Remove BRAINY_FORCE_HIGH_VOLUME env var checks - Always use write buffer when available - Preserve v6.2.6 cache-before-buffer fix for consistency Benefits: - Consistent behavior regardless of load - Predictable performance characteristics - -204 lines of code complexity - Cloud storage always benefits from batching 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
6449bb1afe
commit
26510ce7b8
4 changed files with 58 additions and 262 deletions
|
|
@ -112,11 +112,8 @@ export class R2Storage extends BaseStorage {
|
|||
// Request coalescer for deduplication
|
||||
private requestCoalescer: RequestCoalescer | null = null
|
||||
|
||||
// High-volume mode detection (R2-specific thresholds)
|
||||
private highVolumeMode = false
|
||||
private lastVolumeCheck = 0
|
||||
private volumeCheckInterval = 800 // Check more frequently on R2
|
||||
private forceHighVolumeMode = false
|
||||
// v6.2.7: Write buffering always enabled for consistent performance
|
||||
// Removes dynamic mode switching complexity - cloud storage always benefits from batching
|
||||
|
||||
// Multi-level cache manager for efficient data access
|
||||
private nounCacheManager: CacheManager<HNSWNode>
|
||||
|
|
@ -171,12 +168,7 @@ export class R2Storage extends BaseStorage {
|
|||
})
|
||||
this.verbCacheManager = new CacheManager<Edge>(options.cacheConfig)
|
||||
|
||||
// Check for high-volume mode override
|
||||
if (typeof process !== 'undefined' && process.env?.BRAINY_FORCE_HIGH_VOLUME === 'true') {
|
||||
this.forceHighVolumeMode = true
|
||||
this.highVolumeMode = true
|
||||
prodLog.info('🚀 R2: High-volume mode FORCED via environment variable')
|
||||
}
|
||||
// v6.2.7: Write buffering always enabled - no env var check needed
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -417,32 +409,7 @@ export class R2Storage extends BaseStorage {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if high-volume mode should be enabled
|
||||
*/
|
||||
private checkVolumeMode(): void {
|
||||
if (this.forceHighVolumeMode) {
|
||||
return
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
if (now - this.lastVolumeCheck < this.volumeCheckInterval) {
|
||||
return
|
||||
}
|
||||
|
||||
this.lastVolumeCheck = now
|
||||
|
||||
// R2 threshold: enable at 15 pending operations (lower than S3/GCS)
|
||||
const shouldEnable = this.pendingOperations > 15
|
||||
|
||||
if (shouldEnable && !this.highVolumeMode) {
|
||||
this.highVolumeMode = true
|
||||
prodLog.info('🚀 R2: High-volume mode ENABLED (pending:', this.pendingOperations, ')')
|
||||
} else if (!shouldEnable && this.highVolumeMode && !this.forceHighVolumeMode) {
|
||||
this.highVolumeMode = false
|
||||
prodLog.info('🐌 R2: High-volume mode DISABLED (pending:', this.pendingOperations, ')')
|
||||
}
|
||||
}
|
||||
// v6.2.7: Removed checkVolumeMode() - write buffering always enabled for cloud storage
|
||||
|
||||
/**
|
||||
* Flush noun buffer to R2
|
||||
|
|
@ -477,18 +444,16 @@ export class R2Storage extends BaseStorage {
|
|||
|
||||
/**
|
||||
* Save a node to storage
|
||||
* v6.2.7: Always uses write buffer for consistent performance
|
||||
*/
|
||||
protected async saveNode(node: HNSWNode): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
this.checkVolumeMode()
|
||||
|
||||
// Use write buffer in high-volume mode
|
||||
if (this.highVolumeMode && this.nounWriteBuffer) {
|
||||
// v6.2.7: Always use write buffer - cloud storage benefits from batching
|
||||
if (this.nounWriteBuffer) {
|
||||
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer`)
|
||||
|
||||
// v6.2.6: CRITICAL FIX - Populate cache BEFORE buffering for read-after-write consistency
|
||||
// Without this, add() returns but relate() can't find the entity (cloud storage production bug)
|
||||
// v6.2.6: Populate cache BEFORE buffering for read-after-write consistency
|
||||
if (node.vector && Array.isArray(node.vector) && node.vector.length > 0) {
|
||||
this.nounCacheManager.set(node.id, node)
|
||||
}
|
||||
|
|
@ -497,7 +462,7 @@ export class R2Storage extends BaseStorage {
|
|||
return
|
||||
}
|
||||
|
||||
// Direct write in normal mode
|
||||
// Fallback to direct write if buffer not initialized (shouldn't happen after init)
|
||||
await this.saveNodeDirect(node)
|
||||
}
|
||||
|
||||
|
|
@ -761,18 +726,23 @@ export class R2Storage extends BaseStorage {
|
|||
|
||||
// Verb storage methods (similar to noun methods - implementing key methods for space)
|
||||
|
||||
/**
|
||||
* Save an edge to storage
|
||||
* v6.2.7: Always uses write buffer for consistent performance
|
||||
*/
|
||||
protected async saveEdge(edge: Edge): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
this.checkVolumeMode()
|
||||
|
||||
if (this.highVolumeMode && this.verbWriteBuffer) {
|
||||
// v6.2.6: CRITICAL FIX - Populate cache BEFORE buffering for read-after-write consistency
|
||||
// v6.2.7: Always use write buffer - cloud storage benefits from batching
|
||||
if (this.verbWriteBuffer) {
|
||||
// v6.2.6: Populate cache BEFORE buffering for read-after-write consistency
|
||||
this.verbCacheManager.set(edge.id, edge)
|
||||
|
||||
await this.verbWriteBuffer.add(edge.id, edge)
|
||||
return
|
||||
}
|
||||
|
||||
// Fallback to direct write if buffer not initialized (shouldn't happen after init)
|
||||
await this.saveEdgeDirect(edge)
|
||||
}
|
||||
|
||||
|
|
|
|||
Reference in a new issue