| Crates.io | tokio-debouncer |
| lib.rs | tokio-debouncer |
| version | 0.3.1 |
| created_at | 2025-05-16 08:58:06.569655+00 |
| updated_at | 2025-05-19 15:57:45.349757+00 |
| description | A minimal async debouncer for signal batching in Tokio |
| homepage | |
| repository | https://github.com/vivsh/tokio-debouncer |
| max_upload_size | |
| id | 1676240 |
| size | 29,188 |
tokio-debouncer is a lightweight, cancel-safe async debouncer for Tokio tasks.
tokio::time::pause for time-based simulationparking_lot support (enabled by default)This crate is especially designed for scenarios where you need to debounce jobs or events in a background worker, and the debounce logic must be integrated with a tokio::select! loop. This is common in job queues, event batching, and async pipelines where you want to coalesce bursts of work and process them efficiently.
Why use tokio-debouncer for job queues?
debouncer.ready() inside a tokio::select! block to respond to multiple signals (timers, shutdown, new jobs) without missing or double-processing events.Add to your Cargo.toml:
[dependencies]
tokio-debouncer = "<latest-version>"
use tokio_debouncer::{Debouncer, DebounceMode};
use tokio::time::Duration;
#[tokio::main]
async fn main() {
// Create a debouncer with a 100ms cooldown in trailing mode
let debouncer = Debouncer::new(Duration::from_millis(100), DebounceMode::Trailing);
debouncer.trigger(); // Signal an event
let _guard = debouncer.ready().await; // Wait until ready; debounce is finalized on drop
// Do your work here
} // guard dropped here, debounce is finalized
Debouncer::new(Duration, DebounceMode) — create a new debouncerDebouncer::trigger() — signal that an event occurredDebouncer::ready() — await until it's appropriate to runNote:
ready()is cancel-safe and does not change internal state.- The debounce state is finalized automatically when the guard is dropped. You do not need to call any method to commit the debounce; simply let the guard go out of scope after acquiring it. This ensures robust, cancellation-safe batching, even if your task is cancelled or panics after acquiring the guard.
| Mode | Behavior |
|---|---|
| Leading | Fires immediately, then cools down |
| Trailing | Waits for cooldown period to elapse after the last trigger |
This is the most robust and idiomatic way to use tokio-debouncer in a job queue or event-driven worker:
use tokio::{select, time::{sleep, Duration}};
use tokio_debouncer::{Debouncer, DebounceMode};
#[tokio::main]
async fn main() {
// Create a debouncer for batching jobs
let debouncer = Debouncer::new(Duration::from_secs(1), DebounceMode::Trailing);
// Simulate jobs arriving from another task
let debouncer2 = debouncer.clone();
tokio::spawn(async move {
loop {
debouncer2.trigger(); // Simulate job arrival
sleep(Duration::from_millis(200)).await;
}
});
loop {
select! {
_ = debouncer.ready() => {
// Now process your batch of jobs
println!("Processing job batch!");
}
_ = sleep(Duration::from_millis(100)) => {
// Handle other events, shutdown, etc.
}
}
}
}
debouncer.trigger() can be called from any thread or task to signal new work.select! to wait for either debounce readiness or other events.The debounce state is now finalized automatically when the guard is dropped. You do not need to call any method to commit the debounce; simply let the guard go out of scope after acquiring it. This ensures robust, cancellation-safe batching, even if your task is cancelled or panics after acquiring the guard.
parking_lot (default): Use parking_lot::Mutex for improved performance and poisoning behavior. Disable with default-features = false to use std::sync::Mutex instead.std: (Always enabled) Use standard library features. Present for compatibility with some dependency managers.Example disabling parking_lot:
[dependencies]
tokio-debouncer = { version = "0.3", default-features = false }
The crate includes comprehensive tests using tokio::time::pause and advance to simulate time.
cargo test
Licensed under the MIT License. See LICENSE for details.