Skip to content

Commit f6993c2

Browse files
committed
track insertion time instead of data time for eviction
1 parent 138fea3 commit f6993c2

2 files changed

Lines changed: 40 additions & 12 deletions

File tree

src/storage/object_storage.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ use crate::storage::TARGETS_ROOT_DIRECTORY;
6363
use crate::storage::field_stats::DATASET_STATS_STREAM_NAME;
6464
use crate::storage::field_stats::calculate_field_stats;
6565
use crate::storage::field_stats::extract_datetime_from_parquet_path_regex;
66-
use crate::sync::ACTIVE_OBJECT_STORE_SYNC_FILES;
66+
use crate::sync::{ACTIVE_OBJECT_STORE_SYNC_FILES, SyncFileEntry};
6767

6868
use super::{
6969
ALERTS_ROOT_DIRECTORY, MANIFEST_FILE, ObjectStorageError, ObjectStoreFormat,
@@ -1078,12 +1078,20 @@ async fn process_parquet_files(
10781078
.stream
10791079
.parquet_files()
10801080
.into_par_iter()
1081-
.filter(|p| !guard.contains(p))
1081+
.filter(|p| !guard.contains_key(p))
10821082
.collect();
10831083

10841084
let mut ret = Vec::with_capacity(parquet_paths.len());
10851085
ret.clone_from(&parquet_paths);
1086-
guard.extend(parquet_paths);
1086+
for path in parquet_paths {
1087+
guard.insert(
1088+
path,
1089+
SyncFileEntry {
1090+
tracked_instant: Instant::now(),
1091+
tracked_utc: Utc::now(),
1092+
},
1093+
);
1094+
}
10871095
ret
10881096
};
10891097

@@ -1212,11 +1220,23 @@ async fn collect_upload_results(
12121220
guard.remove(path);
12131221
}
12141222

1215-
// check if file has been in hashset for more than 5 minutes
1216-
let now = Utc::now();
1217-
guard.retain(|f| {
1218-
!extract_datetime_from_parquet_path_regex(f)
1219-
.is_ok_and(|ts| (now - ts).num_minutes() >= 5)
1223+
// Use monotonic time to ensure the 5-minute eviction window is immune to system clock adjustments.
1224+
let now = Instant::now();
1225+
guard.retain(|path, entry| {
1226+
let elapsed = now.duration_since(entry.tracked_instant);
1227+
// 5 min eviction window
1228+
if elapsed >= Duration::from_secs(300) {
1229+
// Added log for observability and debugging
1230+
warn!(
1231+
"Removing stale sync file: {} (elapsed: {}s, tracked_at: {})",
1232+
path.display(),
1233+
elapsed.as_secs(),
1234+
entry.tracked_utc.to_rfc3339(),
1235+
);
1236+
false
1237+
} else {
1238+
true
1239+
}
12201240
});
12211241
}
12221242
let manifest_files: Vec<_> = uploaded_files

src/sync.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
*
1717
*/
1818

19-
use chrono::{TimeDelta, Timelike};
20-
use datafusion::common::HashSet;
19+
use chrono::{DateTime, TimeDelta, Timelike, Utc};
2120
use futures::FutureExt;
2221
use once_cell::sync::Lazy;
2322
use std::collections::HashMap;
@@ -35,8 +34,17 @@ use tracing::{Instrument, error, info, info_span, trace, warn};
3534
static LOCAL_SYNC_RUNNING: AtomicBool = AtomicBool::new(false);
3635
static REMOTE_SYNC_RUNNING: AtomicBool = AtomicBool::new(false);
3736

38-
pub static ACTIVE_OBJECT_STORE_SYNC_FILES: Lazy<Arc<RwLock<HashSet<PathBuf>>>> =
39-
Lazy::new(|| Arc::new(RwLock::new(HashSet::new())));
37+
// tracks metadata for files being synced to object storage
38+
#[derive(Clone, Debug)]
39+
pub struct SyncFileEntry {
40+
// Monotonic instant when file was added to tracking
41+
pub tracked_instant: std::time::Instant,
42+
// Wall-clock UTC timestamp for observability
43+
pub tracked_utc: DateTime<Utc>,
44+
}
45+
46+
pub static ACTIVE_OBJECT_STORE_SYNC_FILES: Lazy<Arc<RwLock<HashMap<PathBuf, SyncFileEntry>>>> =
47+
Lazy::new(|| Arc::new(RwLock::new(HashMap::new())));
4048
/// RAII guard that clears a sync-running flag on drop, so a panic inside the
4149
/// sync body cannot leave the flag stuck at `true` and wedge future ticks.
4250
struct SyncRunningGuard(&'static AtomicBool);

0 commit comments

Comments
 (0)