fix(storage): populate cache before write buffer for read-after-write consistency

Cloud storage adapters (GCS, S3, R2, Azure) use write buffers in
high-volume mode to batch network operations. However, the cache was
not being populated when items were added to the buffer, causing
add() to return successfully but immediate relate() calls to fail
with "Source entity not found".

This fix ensures the cache is populated BEFORE adding to the write
buffer, guaranteeing read-after-write consistency even when writes
are buffered for asynchronous flushing.

Affected adapters:
- GcsStorage: saveNode, saveEdge
- S3CompatibleStorage: saveNode
- R2Storage: saveNode, saveEdge
- AzureBlobStorage: saveNode, saveEdge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
David Snelling 2025-12-02 13:23:18 -08:00
parent e4bbd7fb0e
commit 2d27bd01af
4 changed files with 42 additions and 0 deletions

View file

@ -531,6 +531,13 @@ export class AzureBlobStorage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && this.nounWriteBuffer) {
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
// 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)
if (node.vector && Array.isArray(node.vector) && node.vector.length > 0) {
this.nounCacheManager.set(node.id, node)
}
await this.nounWriteBuffer.add(node.id, node)
return
} else if (!this.highVolumeMode) {
@ -1033,6 +1040,10 @@ export class AzureBlobStorage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && this.verbWriteBuffer) {
this.logger.trace(`📝 BUFFERING: Adding verb ${edge.id} to write buffer`)
// v6.2.6: CRITICAL FIX - Populate cache BEFORE buffering for read-after-write consistency
this.verbCacheManager.set(edge.id, edge)
await this.verbWriteBuffer.add(edge.id, edge)
return
}

View file

@ -442,6 +442,14 @@ export class GcsStorage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && this.nounWriteBuffer) {
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
// 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 (GCS production bug)
// The buffer flushes asynchronously, but cache ensures immediate reads succeed
if (node.vector && Array.isArray(node.vector) && node.vector.length > 0) {
this.nounCacheManager.set(node.id, node)
}
await this.nounWriteBuffer.add(node.id, node)
return
} else if (!this.highVolumeMode) {
@ -833,6 +841,11 @@ export class GcsStorage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && this.verbWriteBuffer) {
this.logger.trace(`📝 BUFFERING: Adding verb ${edge.id} to write buffer`)
// v6.2.6: CRITICAL FIX - Populate cache BEFORE buffering for read-after-write consistency
// Without this, relate() might not find the verb immediately after creation
this.verbCacheManager.set(edge.id, edge)
await this.verbWriteBuffer.add(edge.id, edge)
return
}

View file

@ -486,6 +486,13 @@ export class R2Storage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && 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)
if (node.vector && Array.isArray(node.vector) && node.vector.length > 0) {
this.nounCacheManager.set(node.id, node)
}
await this.nounWriteBuffer.add(node.id, node)
return
}
@ -759,6 +766,9 @@ export class R2Storage extends BaseStorage {
this.checkVolumeMode()
if (this.highVolumeMode && this.verbWriteBuffer) {
// v6.2.6: CRITICAL FIX - Populate cache BEFORE buffering for read-after-write consistency
this.verbCacheManager.set(edge.id, edge)
await this.verbWriteBuffer.add(edge.id, edge)
return
}

View file

@ -1069,6 +1069,14 @@ export class S3CompatibleStorage extends BaseStorage {
// Use write buffer in high-volume mode
if (this.highVolumeMode && this.nounWriteBuffer) {
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
// 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)
// The buffer flushes asynchronously, but cache ensures immediate reads succeed
if (node.vector && Array.isArray(node.vector) && node.vector.length > 0) {
this.nounCacheManager.set(node.id, node)
}
await this.nounWriteBuffer.add(node.id, node)
return
} else if (!this.highVolumeMode) {