Skip to content

Commit c4ee110

Browse files
ma2bdclaude
authored andcommitted
Fix storage cache reads dropping Arc before use (linera-io#6046)
## Motivation After linera-io#5967 introduced Arc-shared caches with weak-index deduplication, several DbStorage read methods (read_confirmed_block, read_blob, read_event, etc.) used an insert-then-get pattern: ```rust self.caches.confirmed_block.insert(&hash, block); Ok(self.caches.confirmed_block.get(&hash)) ``` The Arc returned by insert is dropped immediately. If the bounded cache (S3-FIFO) evicts the entry before get runs -- e.g., under high cache pressure or concurrent inserts -- and no other consumer holds a strong reference, the weak index entry becomes dead and get returns None. This turns a successful DB read into a spurious None, causing errors like `Missing confirmed block` in the chain listener. ## Proposal Use the Arc returned by insert directly instead of round-tripping through get: ```rust Ok(Some(self.caches.confirmed_block.insert(&hash, block))) ``` Fixed in 5 call sites: - read_confirmed_block - read_confirmed_blocks - read_blob - read_certificates_raw - read_event ## Test Plan - Existing CI tests pass - Verified no other insert-then-get pattern exists (insert_hashed/get_hashed callers do not use this pattern) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0147e65 commit c4ee110

1 file changed

Lines changed: 13 additions & 18 deletions

File tree

linera-storage/src/db_storage.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -775,10 +775,7 @@ where
775775
.with_label_values(&[metrics::DB])
776776
.inc();
777777
match value {
778-
Some(block) => {
779-
self.caches.confirmed_block.insert(&hash, block);
780-
Ok(self.caches.confirmed_block.get(&hash))
781-
}
778+
Some(block) => Ok(Some(self.caches.confirmed_block.insert(&hash, block))),
782779
None => Ok(None),
783780
}
784781
}
@@ -807,10 +804,11 @@ where
807804
for (miss_idx, root_key) in misses.iter().zip(root_keys) {
808805
let store = self.database.open_shared(&root_key)?;
809806
if let Some(block) = store.read_value::<ConfirmedBlock>(BLOCK_KEY).await? {
810-
self.caches
811-
.confirmed_block
812-
.insert(&hashes[*miss_idx], block);
813-
results[*miss_idx] = self.caches.confirmed_block.get(&hashes[*miss_idx]);
807+
results[*miss_idx] = Some(
808+
self.caches
809+
.confirmed_block
810+
.insert(&hashes[*miss_idx], block),
811+
);
814812
}
815813
}
816814
}
@@ -851,8 +849,7 @@ where
851849
match maybe_blob_bytes {
852850
Some(blob_bytes) => {
853851
let blob = Blob::new_with_id_unchecked(blob_id, blob_bytes);
854-
self.caches.blob.insert(&blob_id, blob);
855-
Ok(self.caches.blob.get(&blob_id))
852+
Ok(Some(self.caches.blob.insert(&blob_id, blob)))
856853
}
857854
None => Ok(None),
858855
}
@@ -1090,10 +1087,11 @@ where
10901087
let store = self.database.open_shared(&root_key)?;
10911088
let values = store.read_multi_values_bytes(&get_block_keys()).await?;
10921089
if let (Some(lite), Some(block)) = (values[0].as_ref(), values[1].as_ref()) {
1093-
self.caches
1094-
.certificate_raw
1095-
.insert(&hashes[*miss_idx], (lite.clone(), block.clone()));
1096-
results[*miss_idx] = self.caches.certificate_raw.get(&hashes[*miss_idx]);
1090+
results[*miss_idx] = Some(
1091+
self.caches
1092+
.certificate_raw
1093+
.insert(&hashes[*miss_idx], (lite.clone(), block.clone())),
1094+
);
10971095
}
10981096
}
10991097
}
@@ -1248,10 +1246,7 @@ where
12481246
.with_label_values(&[metrics::DB])
12491247
.inc();
12501248
match event {
1251-
Some(event_bytes) => {
1252-
self.caches.event.insert(&event_id, event_bytes);
1253-
Ok(self.caches.event.get(&event_id))
1254-
}
1249+
Some(event_bytes) => Ok(Some(self.caches.event.insert(&event_id, event_bytes))),
12551250
None => Ok(None),
12561251
}
12571252
}

0 commit comments

Comments
 (0)