惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Vercel News
Vercel News
博客园_首页
Y
Y Combinator Blog
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
阮一峰的网络日志
阮一峰的网络日志
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
GbyAI
GbyAI
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
博客园 - Franky
Engineering at Meta
Engineering at Meta
量子位
The GitHub Blog
The GitHub Blog
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
N
Netflix TechBlog - Medium

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
File Watching in Rust with notify-rs — Hot Folders for a ...
hiyoyo · 2026-05-14 · via DEV Community

hiyoyo

All tests run on an 8-year-old MacBook Air.
All results from shipping 7 Mac apps as a solo developer. No sponsored opinion.
HiyokoAutoSync watches directories for changes and triggers sync automatically. notify-rs is the Rust crate for this. Here's what I learned using it in a shipping Tauri app.

Basic setup
toml[dependencies]
notify = "6"
rustuse notify::{RecommendedWatcher, RecursiveMode, Watcher, Config};
use std::sync::mpsc;

fn watch_directory(path: &str) -> Result<(), AppError> {
let (tx, rx) = mpsc::channel();

let mut watcher = RecommendedWatcher::new(tx, Config::default())?;
watcher.watch(path.as_ref(), RecursiveMode::Recursive)?;

for res in rx {
    match res {
        Ok(event) => handle_event(event),
        Err(e) => log::error!("Watch error: {:?}", e),
    }
}
Ok(())

Enter fullscreen mode Exit fullscreen mode

}
RecommendedWatcher uses FSEvents on macOS — the native file system event API. Low overhead, fast notification.

The double-fire problem
File save operations often trigger multiple events. A text editor saving a file might fire: Modify, Modify, Create, Modify. You want one sync trigger, not four.
Debounce:
rustuse std::time::{Duration, Instant};
use std::collections::HashMap;

struct Debouncer {
last_seen: HashMap,
delay: Duration,
}

impl Debouncer {
fn should_process(&mut self, path: &PathBuf) -> bool {
let now = Instant::now();
let last = self.last_seen.entry(path.clone()).or_insert(Instant::now() - self.delay * 2);

    if now.duration_since(*last) >= self.delay {
        *last = now;
        true
    } else {
        false
    }
}

Enter fullscreen mode Exit fullscreen mode

}
300-500ms debounce window covers most editor save behaviors without feeling slow.

Filtering what to watch
Not every file change should trigger a sync. Skip:
rustfn should_ignore(path: &Path) -> bool {
let name = path.file_name()
.and_then(|n| n.to_str())
.unwrap_or("");

// Hidden files
name.starts_with('.')
// Temp files
|| name.ends_with(".tmp")
|| name.ends_with('~')
// DS_Store
|| name == ".DS_Store"
// Already syncing
|| name.ends_with(".sync")

Enter fullscreen mode Exit fullscreen mode

}

Running the watcher in Tauri
The watcher needs to run in a background thread, not blocking the Tokio runtime:
ruststd:🧵:spawn(move || {
if let Err(e) = watch_directory(&path) {
log::error!("Watcher failed: {:?}", e);
}
});
Use std:🧵:spawn for the blocking watcher loop. Communicate back to Tauri via channels or the app handle's emit system.

The verdict
notify-rs with FSEvents on macOS is solid. The double-fire problem needs debouncing — build it in from the start. Filter aggressively to avoid triggering on irrelevant changes.

If this was useful, a ❤️ helps more than you'd think — thanks!
Hiyoko PDF Vault → https://hiyokoko.gumroad.com/l/HiyokoPDFVault
X → @hiyoyok