Skip to content

Commit 4b4fe21

Browse files
committed
fix ci
1 parent 2e115bf commit 4b4fe21

13 files changed

Lines changed: 205 additions & 319 deletions

File tree

crates/fff-core/src/background_watcher.rs

Lines changed: 19 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -579,13 +579,6 @@ fn handle_debounced_events(
579579

580580
files_to_update_git_status.reserve(paths_to_add_or_modify.len());
581581
for path in &paths_to_add_or_modify {
582-
// Double-check existence: the debouncer may deliver a Modify event
583-
// for a path that was deleted between event emission and processing
584-
// (Create+Remove merged into just Create by the debouncer).
585-
if !path.exists() {
586-
picker.remove_file_by_path(path);
587-
continue;
588-
}
589582
if picker.handle_create_or_modify(path).is_some() {
590583
files_to_update_git_status.push(path.to_path_buf());
591584
} else {
@@ -594,40 +587,12 @@ fn handle_debounced_events(
594587
}
595588

596589
overflow_count = picker.get_overflow_files().len();
597-
598-
// Reconcile overflow files: stat-check each live overflow file and
599-
// tombstone any that no longer exist on disk. This handles deletions
600-
// where the debouncer swallowed the Remove event.
601-
if overflow_count > 0 {
602-
let base_path = picker.base_path().to_path_buf();
603-
let stale: Vec<PathBuf> = picker
604-
.get_overflow_files()
605-
.iter()
606-
.filter(|f| !f.is_deleted())
607-
.filter_map(|f| {
608-
let abs = f.absolute_path(&*picker, &base_path);
609-
(!abs.exists()).then_some(abs)
610-
})
611-
.collect();
612-
613-
for path in &stale {
614-
picker.remove_file_by_path(path);
615-
}
616-
if !stale.is_empty() {
617-
overflow_count = picker.get_overflow_files().len();
618-
}
619-
}
620590
}
621591

622592
info!(
623593
files_updated = files_to_update_git_status.len(),
624594
overflow_count, "File index changes applied",
625595
);
626-
627-
// Reconcile overflow files unconditionally on every batch: stat-check
628-
// each live overflow file and tombstone any that no longer exist on disk.
629-
// This is the only reliable way to detect deletions when the debouncer
630-
// coalesces Create+Remove for the same path into nothing.
631596
if need_full_rescan || overflow_count > MAX_OVERFLOW_FILES {
632597
info!("Watcher faced limit of index overflow. Triggering rescan");
633598
if let Err(e) = shared_picker.trigger_full_rescan_async(shared_frecency) {
@@ -679,50 +644,47 @@ fn handle_debounced_events(
679644
}
680645
}
681646

682-
// Git status updates are IO-heavy (reads .git/index, stats files) and
683-
// not on the critical path for search correctness. Spawn them on the
684-
// background pool so the debouncer handler returns immediately and can
685-
// process the next event batch without waiting for git.
686-
if need_full_git_rescan || !files_to_update_git_status.is_empty() {
687-
let sp = shared_picker.clone();
688-
let sf = shared_frecency.clone();
689-
let git_workdir = repo.as_ref().map(|r| {
690-
r.workdir()
691-
.unwrap_or_else(|| r.path())
692-
.to_path_buf()
693-
});
694-
let full_rescan = need_full_git_rescan;
695-
let need_picker_rescan = need_full_rescan;
696-
let files = files_to_update_git_status;
647+
// do not try to update the paths if we anyway going to rescan everythign from scracth
648+
if !need_full_rescan && (need_full_git_rescan || !files_to_update_git_status.is_empty()) {
649+
let git_workdir = repo
650+
.as_ref()
651+
.map(|r| r.workdir().unwrap_or_else(|| r.path()).to_path_buf());
652+
653+
let shared_picker = shared_picker.clone();
654+
let shared_frecency = shared_frecency.clone();
697655

656+
// git status query even with a pathspec could be really slow, if we do this syncrhronously
657+
// within the event handler, we actually risk of forming a snow ball of conflicting events
698658
crate::file_picker::BACKGROUND_THREAD_POOL.spawn(move || {
699659
let Some(git_path) = git_workdir else { return };
700660
let Ok(repo) = Repository::open(&git_path) else {
701661
error!("Failed to open git repo for async status update");
702662
return;
703663
};
704664

705-
if full_rescan && !need_picker_rescan {
665+
if need_full_git_rescan && !need_full_rescan {
706666
info!("Async: triggering full git rescan");
707-
if let Err(e) = sp.refresh_git_status(&sf) {
667+
if let Err(e) = shared_picker.refresh_git_status(&shared_frecency) {
708668
error!("Failed to refresh git status: {:?}", e);
709669
}
710670
}
711671

712-
if !files.is_empty() && !full_rescan {
713-
info!("Async: fetching git status for {} files", files.len());
714-
let status = match GitStatusCache::git_status_for_paths(&repo, &files) {
672+
if !files_to_update_git_status.is_empty() {
673+
let status = match GitStatusCache::git_status_for_paths(
674+
&repo,
675+
&files_to_update_git_status,
676+
) {
715677
Ok(s) => s,
716678
Err(e) => {
717679
error!("Failed to query git status: {:?}", e);
718680
return;
719681
}
720682
};
721683

722-
if let Ok(mut guard) = sp.write()
684+
if let Ok(mut guard) = shared_picker.write()
723685
&& let Some(ref mut picker) = *guard
724686
{
725-
if let Err(e) = picker.update_git_statuses(status, &sf) {
687+
if let Err(e) = picker.update_git_statuses(status, &shared_frecency) {
726688
error!("Failed to update git statuses: {:?}", e);
727689
} else {
728690
info!("Async: git statuses updated");

crates/fff-core/src/bigram_filter.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -596,13 +596,7 @@ impl BigramOverlay {
596596
}
597597
}
598598

599-
/// Per-file size cap for bigram indexing. Doubles as the `is_indexable`
600-
/// cutoff in the finalize-sort: files over this size are pushed past
601-
/// `indexable_count` and unconditionally scanned at grep time instead of
602-
/// being bigram-prefiltered. Unifying the two caps guarantees that every
603-
/// file inside the indexed region gets *full* bigram coverage, so the
604-
/// prefilter never produces false negatives on partial-content files.
605-
pub(crate) const BIGRAM_CONTENT_CAP: usize = 2 * 1024 * 1024;
599+
pub(crate) const MAX_INDEXABLE_FILE_SIZE: usize = 2 * 1024 * 1024;
606600
const BIGRAM_CHUNK_FILES: usize = 4 * 64;
607601

608602
/// Sparse-column cutoff for the skip-1 sub-index. Rare skip columns add
@@ -611,16 +605,14 @@ const BIGRAM_CHUNK_FILES: usize = 4 * 64;
611605
const SKIP_INDEX_MIN_DENSITY_PCT: u32 = 12;
612606

613607
thread_local! {
614-
/// Per-rayon-worker reusable read buffer. Allocated via `vec!` to avoid
615-
/// materializing the 2 MiB array on the worker stack (`Box::new([0u8; N])`
616-
/// constructs the array in the current frame first, which overflows the
617-
/// default 2 MiB rayon worker stack).
608+
/// Reusable read buffer that is allocated per thread and used for reading files
618609
static READ_BUF: std::cell::RefCell<Box<[u8]>> =
619-
std::cell::RefCell::new(vec![0u8; BIGRAM_CONTENT_CAP].into_boxed_slice());
610+
std::cell::RefCell::new(vec![0u8; MAX_INDEXABLE_FILE_SIZE].into_boxed_slice());
620611
}
621612

622613
/// reads a chunk for bigram either from new warmed up cache or from the file directly
623614
#[inline]
615+
#[allow(clippy::too_many_arguments)]
624616
fn read_bigram_chunk<'a>(
625617
file: &'a crate::types::FileItem,
626618
base_fd: libc::c_int,
@@ -640,10 +632,10 @@ fn read_bigram_chunk<'a>(
640632
return None;
641633
}
642634

643-
return Some(&cached[..cached.len().min(BIGRAM_CONTENT_CAP)]);
635+
return Some(&cached[..cached.len().min(MAX_INDEXABLE_FILE_SIZE)]);
644636
}
645637

646-
let want = (file.size as usize).min(BIGRAM_CONTENT_CAP);
638+
let want = (file.size as usize).min(MAX_INDEXABLE_FILE_SIZE);
647639
let filled = file.read_trimmed_into_buf(base_fd, base_path, arena, path_buf, &mut buf[..want]);
648640
if filled == 0 {
649641
return None;
@@ -724,7 +716,7 @@ pub(crate) fn build_bigram_index(
724716

725717
// in progress bigram walk + rust's ignore crate allocates shit ton of garbage memory
726718
// all custom allocators would think this is available resource while we do not allocate
727-
// afte the sync, so it's very important to let the unused memory go back to the OS
719+
// after the sync, so it's very important to let the unused memory go back to the OS
728720
crate::file_picker::hint_allocator_collect();
729721

730722
index

0 commit comments

Comments
 (0)