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:
parent
e4bbd7fb0e
commit
2d27bd01af
4 changed files with 42 additions and 0 deletions
|
|
@ -531,6 +531,13 @@ export class AzureBlobStorage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.nounWriteBuffer) {
|
if (this.highVolumeMode && this.nounWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
|
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)
|
await this.nounWriteBuffer.add(node.id, node)
|
||||||
return
|
return
|
||||||
} else if (!this.highVolumeMode) {
|
} else if (!this.highVolumeMode) {
|
||||||
|
|
@ -1033,6 +1040,10 @@ export class AzureBlobStorage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.verbWriteBuffer) {
|
if (this.highVolumeMode && this.verbWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding verb ${edge.id} to write buffer`)
|
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)
|
await this.verbWriteBuffer.add(edge.id, edge)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,14 @@ export class GcsStorage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.nounWriteBuffer) {
|
if (this.highVolumeMode && this.nounWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
|
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)
|
await this.nounWriteBuffer.add(node.id, node)
|
||||||
return
|
return
|
||||||
} else if (!this.highVolumeMode) {
|
} else if (!this.highVolumeMode) {
|
||||||
|
|
@ -833,6 +841,11 @@ export class GcsStorage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.verbWriteBuffer) {
|
if (this.highVolumeMode && this.verbWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding verb ${edge.id} to write buffer`)
|
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)
|
await this.verbWriteBuffer.add(edge.id, edge)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -486,6 +486,13 @@ export class R2Storage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.nounWriteBuffer) {
|
if (this.highVolumeMode && this.nounWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer`)
|
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)
|
await this.nounWriteBuffer.add(node.id, node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -759,6 +766,9 @@ export class R2Storage extends BaseStorage {
|
||||||
this.checkVolumeMode()
|
this.checkVolumeMode()
|
||||||
|
|
||||||
if (this.highVolumeMode && this.verbWriteBuffer) {
|
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)
|
await this.verbWriteBuffer.add(edge.id, edge)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1069,6 +1069,14 @@ export class S3CompatibleStorage extends BaseStorage {
|
||||||
// Use write buffer in high-volume mode
|
// Use write buffer in high-volume mode
|
||||||
if (this.highVolumeMode && this.nounWriteBuffer) {
|
if (this.highVolumeMode && this.nounWriteBuffer) {
|
||||||
this.logger.trace(`📝 BUFFERING: Adding noun ${node.id} to write buffer (high-volume mode active)`)
|
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)
|
await this.nounWriteBuffer.add(node.id, node)
|
||||||
return
|
return
|
||||||
} else if (!this.highVolumeMode) {
|
} else if (!this.highVolumeMode) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue