Skip to content

Commit 90b79e4

Browse files
authored
Merge pull request #4456 from benthecarman/paginated-follow-ups2
Skip non-key entries in list_paginated
2 parents 4125d5a + 1545ad5 commit 90b79e4

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

lightning-persister/src/fs_store/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ impl FilesystemStoreState {
720720
}
721721
}
722722

723-
fn dir_entry_is_key(dir_entry: &fs::DirEntry) -> Result<bool, lightning::io::Error> {
723+
pub(crate) fn dir_entry_is_key(dir_entry: &fs::DirEntry) -> Result<bool, lightning::io::Error> {
724724
let p = dir_entry.path();
725725
if let Some(ext) = p.extension() {
726726
#[cfg(target_os = "windows")]

lightning-persister/src/fs_store/v2.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Objects related to [`FilesystemStoreV2`] live here.
2-
use crate::fs_store::common::{get_key_from_dir_entry_path, FilesystemStoreState};
2+
use crate::fs_store::common::{
3+
dir_entry_is_key, get_key_from_dir_entry_path, FilesystemStoreState,
4+
};
35

46
use lightning::util::persist::{
57
KVStoreSync, MigratableKVStore, PageToken, PaginatedKVStoreSync, PaginatedListResponse,
@@ -108,6 +110,16 @@ impl FilesystemStoreState {
108110
for dir_entry in fs::read_dir(&prefixed_dest)? {
109111
let dir_entry = dir_entry?;
110112

113+
match dir_entry_is_key(&dir_entry) {
114+
// Entry is not a key (e.g., .tmp file, directory), skip it.
115+
Ok(false) => continue,
116+
// Entry is a valid key file, proceed to collect it.
117+
Ok(true) => {},
118+
// Entry may have been deleted between read_dir and our check. Include
119+
// it anyway to give a more consistent view, matching list's behavior.
120+
Err(_) => {},
121+
}
122+
111123
let key =
112124
get_key_from_dir_entry_path(&dir_entry.path(), prefixed_dest.as_path(), false)?;
113125
// Get modification time as millis since epoch
@@ -616,6 +628,33 @@ mod tests {
616628
assert_eq!(response.keys[3], "apple");
617629
}
618630

631+
#[test]
632+
fn test_paginated_listing_skips_tmp_files() {
633+
use lightning::util::persist::{KVStoreSync, PaginatedKVStoreSync};
634+
635+
let mut temp_path = std::env::temp_dir();
636+
temp_path.push("test_paginated_listing_skips_tmp_files_v2");
637+
let fs_store = FilesystemStoreV2::new(temp_path.clone()).unwrap();
638+
639+
let data = vec![42u8; 32];
640+
641+
// Write some real keys
642+
KVStoreSync::write(&fs_store, "ns", "sub", "key0", data.clone()).unwrap();
643+
std::thread::sleep(std::time::Duration::from_millis(10));
644+
KVStoreSync::write(&fs_store, "ns", "sub", "key1", data.clone()).unwrap();
645+
646+
// Create a .tmp file and a subdirectory directly on disk
647+
let dir = temp_path.join("ns").join("sub");
648+
fs::write(dir.join("inflight.tmp"), &data).unwrap();
649+
fs::create_dir_all(dir.join("stray_dir")).unwrap();
650+
651+
// Paginated listing should only return the two real keys
652+
let response = PaginatedKVStoreSync::list_paginated(&fs_store, "ns", "sub", None).unwrap();
653+
assert_eq!(response.keys.len(), 2);
654+
assert!(response.keys.contains(&"key0".to_string()));
655+
assert!(response.keys.contains(&"key1".to_string()));
656+
}
657+
619658
#[test]
620659
fn test_rejects_v1_data_directory() {
621660
let mut temp_path = std::env::temp_dir();

0 commit comments

Comments
 (0)