1use tokio::time::{sleep, Duration};
2use tokio::sync::Mutex;
3use std::sync::Arc;
4
5pub struct Debouncer {
28 delay: Duration,
29 task: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
30}
31
32impl Debouncer {
33 pub fn new(delay: Duration) -> Self {
35 Debouncer {
36 delay,
37 task: Arc::new(Mutex::new(None)),
38 }
39 }
40
41 pub async fn call<F, Fut, R>(&self, f: F)
43 where
44 F: FnOnce() -> Fut + Send + 'static,
45 Fut: std::future::Future<Output = R> + Send + 'static,
46 {
47 let mut task = self.task.lock().await;
48
49 if let Some(handle) = task.take() {
51 handle.abort();
52 }
53
54 let delay = self.delay;
56 *task = Some(tokio::spawn(async move {
57 sleep(delay).await;
58 f().await;
59 }));
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use std::sync::Arc;
66 use tokio::sync::Mutex;
67 use tokio::time::Duration;
68 use crate::Debouncer;
69
70 #[tokio::test]
71 async fn should_call_last_only_test() {
72 let debouncer = Debouncer::new(Duration::from_secs(1));
73 let counter = Arc::new(Mutex::new(0));
74
75 let counter_clone = Arc::clone(&counter);
76 debouncer.call(move || {
77 async move {
78 let mut num = counter_clone.lock().await;
79 *num += 1;
80 }
81 }).await;
82
83 let counter_clone = Arc::clone(&counter);
84 debouncer.call(move || {
85 async move {
86 let mut num = counter_clone.lock().await;
87 *num += 1;
88 }
89 }).await;
90
91 for _ in 0..5 {
92 let counter_clone = Arc::clone(&counter);
93 debouncer.call(move || {
94 async move {
95 let mut num = counter_clone.lock().await;
96 *num += 1;
97 }
98 }).await;
99 tokio::time::sleep(Duration::from_millis(200)).await;
100 }
101
102 tokio::time::sleep(Duration::from_secs(2)).await;
103
104 let final_value = *counter.lock().await;
105 assert_eq!(final_value, 1, "The final call should be executed once.");
106 }
107
108 #[tokio::test]
109 async fn should_call_all_if_duration_is_short_test() {
110 let debouncer = Debouncer::new(Duration::from_millis(100));
111 let counter = Arc::new(Mutex::new(0));
112
113 let counter_clone = Arc::clone(&counter);
114 debouncer.call(move || {
115 async move {
116 let mut num = counter_clone.lock().await;
117 *num += 1;
118 }
119 }).await;
120
121 let counter_clone = Arc::clone(&counter);
122 debouncer.call(move || {
123 async move {
124 let mut num = counter_clone.lock().await;
125 *num += 1;
126 }
127 }).await;
128
129 for _ in 0..5 {
130 let counter_clone = Arc::clone(&counter);
131 debouncer.call(move || {
132 async move {
133 let mut num = counter_clone.lock().await;
134 *num += 1;
135 }
136 }).await;
137 tokio::time::sleep(Duration::from_millis(200)).await;
138 }
139
140 tokio::time::sleep(Duration::from_secs(2)).await;
141
142 let final_value = *counter.lock().await;
143 assert_eq!(final_value, 5, "The final call should be executed every time.");
144 }
145}