1use std::cmp::Eq;
2use std::hash::Hash;
3
4use web_time::Instant;
5
6#[cfg(feature = "async")]
7use {super::CachedAsync, async_trait::async_trait, futures::Future};
8
9use crate::{stores::timed::Status, CloneCached};
10
11use super::{Cached, SizedCache};
12
13#[derive(Clone, Debug)]
22pub struct TimedSizedCache<K, V> {
23 pub(super) store: SizedCache<K, (Instant, V)>,
24 pub(super) size: usize,
25 pub(super) seconds: u64,
26 pub(super) hits: u64,
27 pub(super) misses: u64,
28 pub(super) refresh: bool,
29}
30
31impl<K: Hash + Eq + Clone, V> TimedSizedCache<K, V> {
32 #[must_use]
34 pub fn with_size_and_lifespan(size: usize, seconds: u64) -> TimedSizedCache<K, V> {
35 Self::with_size_and_lifespan_and_refresh(size, seconds, false)
36 }
37
38 #[must_use]
45 pub fn with_size_and_lifespan_and_refresh(
46 size: usize,
47 seconds: u64,
48 refresh: bool,
49 ) -> TimedSizedCache<K, V> {
50 if size == 0 {
51 panic!("`size` of `TimedSizedCache` must be greater than zero.");
52 }
53 TimedSizedCache {
54 store: SizedCache::with_size(size),
55 size,
56 seconds,
57 hits: 0,
58 misses: 0,
59 refresh,
60 }
61 }
62
63 pub fn try_with_size_and_lifespan(
69 size: usize,
70 seconds: u64,
71 ) -> std::io::Result<TimedSizedCache<K, V>> {
72 if size == 0 {
73 return Err(std::io::Error::from_raw_os_error(22));
75 }
76 Ok(TimedSizedCache {
77 store: SizedCache::try_with_size(size)?,
78 size,
79 seconds,
80 hits: 0,
81 misses: 0,
82 refresh: false,
83 })
84 }
85
86 fn iter_order(&self) -> impl Iterator<Item = &(K, (Instant, V))> {
87 let max_seconds = self.seconds;
88 self.store
89 .iter_order()
90 .filter(move |(_k, stamped)| stamped.0.elapsed().as_secs() < max_seconds)
91 }
92
93 pub fn key_order(&self) -> impl Iterator<Item = &K> {
97 self.iter_order().map(|(k, _v)| k)
98 }
99
100 pub fn value_order(&self) -> impl Iterator<Item = &(Instant, V)> {
104 self.iter_order().map(|(_k, v)| v)
105 }
106
107 #[must_use]
109 pub fn refresh(&self) -> bool {
110 self.refresh
111 }
112
113 pub fn set_refresh(&mut self, refresh: bool) {
115 self.refresh = refresh;
116 }
117
118 #[must_use]
120 pub fn get_store(&self) -> &SizedCache<K, (Instant, V)> {
121 &self.store
122 }
123
124 pub fn flush(&mut self) {
126 let seconds = self.seconds;
127 self.store
128 .retain(|_, (instant, _)| instant.elapsed().as_secs() < seconds);
129 }
130
131 fn status<Q>(&mut self, key: &Q) -> Status
132 where
133 K: std::borrow::Borrow<Q>,
134 Q: std::hash::Hash + Eq + ?Sized,
135 {
136 let mut val = self.store.get_mut_if(key, |_| true);
137 if let Some(&mut (instant, _)) = val.as_mut() {
138 if instant.elapsed().as_secs() < self.seconds {
139 if self.refresh {
140 *instant = Instant::now();
141 }
142 Status::Found
143 } else {
144 Status::Expired
145 }
146 } else {
147 Status::NotFound
148 }
149 }
150}
151
152impl<K: Hash + Eq + Clone, V> Cached<K, V> for TimedSizedCache<K, V> {
153 fn cache_get<Q>(&mut self, key: &Q) -> Option<&V>
154 where
155 K: std::borrow::Borrow<Q>,
156 Q: std::hash::Hash + Eq + ?Sized,
157 {
158 match self.status(key) {
159 Status::NotFound => {
160 self.misses += 1;
161 None
162 }
163 Status::Found => {
164 self.hits += 1;
165 self.store.cache_get(key).map(|stamped| &stamped.1)
166 }
167 Status::Expired => {
168 self.misses += 1;
169 self.store.cache_remove(key);
170 None
171 }
172 }
173 }
174
175 fn cache_get_mut<Q>(&mut self, key: &Q) -> std::option::Option<&mut V>
176 where
177 K: std::borrow::Borrow<Q>,
178 Q: std::hash::Hash + Eq + ?Sized,
179 {
180 match self.status(key) {
181 Status::NotFound => {
182 self.misses += 1;
183 None
184 }
185 Status::Found => {
186 self.hits += 1;
187 self.store.cache_get_mut(key).map(|stamped| &mut stamped.1)
188 }
189 Status::Expired => {
190 self.misses += 1;
191 self.store.cache_remove(key);
192 None
193 }
194 }
195 }
196
197 fn cache_get_or_set_with<F: FnOnce() -> V>(&mut self, key: K, f: F) -> &mut V {
198 let setter = || (Instant::now(), f());
199 let max_seconds = self.seconds;
200 let (was_present, was_valid, stamped) =
201 self.store.get_or_set_with_if(key, setter, |stamped| {
202 stamped.0.elapsed().as_secs() < max_seconds
203 });
204 if was_present && was_valid {
205 if self.refresh {
206 stamped.0 = Instant::now();
207 }
208 self.hits += 1;
209 } else {
210 self.misses += 1;
211 }
212 &mut stamped.1
213 }
214
215 fn cache_try_get_or_set_with<F: FnOnce() -> Result<V, E>, E>(
216 &mut self,
217 key: K,
218 f: F,
219 ) -> Result<&mut V, E> {
220 let setter = || Ok((Instant::now(), f()?));
221 let max_seconds = self.seconds;
222 let (was_present, was_valid, stamped) =
223 self.store.try_get_or_set_with_if(key, setter, |stamped| {
224 stamped.0.elapsed().as_secs() < max_seconds
225 })?;
226 if was_present && was_valid {
227 if self.refresh {
228 stamped.0 = Instant::now();
229 }
230 self.hits += 1;
231 } else {
232 self.misses += 1;
233 }
234 Ok(&mut stamped.1)
235 }
236
237 fn cache_set(&mut self, key: K, val: V) -> Option<V> {
238 let stamped = self.store.cache_set(key, (Instant::now(), val));
239 stamped.and_then(|(instant, v)| {
240 if instant.elapsed().as_secs() < self.seconds {
241 Some(v)
242 } else {
243 None
244 }
245 })
246 }
247
248 fn cache_remove<Q>(&mut self, k: &Q) -> Option<V>
249 where
250 K: std::borrow::Borrow<Q>,
251 Q: std::hash::Hash + Eq + ?Sized,
252 {
253 let stamped = self.store.cache_remove(k);
254 stamped.and_then(|(instant, v)| {
255 if instant.elapsed().as_secs() < self.seconds {
256 Some(v)
257 } else {
258 None
259 }
260 })
261 }
262 fn cache_clear(&mut self) {
263 self.store.cache_clear();
264 }
265 fn cache_reset(&mut self) {
266 self.cache_clear();
267 }
268 fn cache_reset_metrics(&mut self) {
269 self.misses = 0;
270 self.hits = 0;
271 }
272 fn cache_size(&self) -> usize {
273 self.store.cache_size()
274 }
275 fn cache_hits(&self) -> Option<u64> {
276 Some(self.hits)
277 }
278 fn cache_misses(&self) -> Option<u64> {
279 Some(self.misses)
280 }
281 fn cache_capacity(&self) -> Option<usize> {
282 Some(self.size)
283 }
284 fn cache_lifespan(&self) -> Option<u64> {
285 Some(self.seconds)
286 }
287 fn cache_set_lifespan(&mut self, seconds: u64) -> Option<u64> {
288 let old = self.seconds;
289 self.seconds = seconds;
290 Some(old)
291 }
292}
293
294impl<K: Hash + Eq + Clone, V: Clone> CloneCached<K, V> for TimedSizedCache<K, V> {
295 fn cache_get_expired<Q>(&mut self, k: &Q) -> (Option<V>, bool)
296 where
297 K: std::borrow::Borrow<Q>,
298 Q: std::hash::Hash + Eq + ?Sized,
299 {
300 match self.status(k) {
301 Status::NotFound => {
302 self.misses += 1;
303 (None, false)
304 }
305 Status::Found => {
306 self.hits += 1;
307 (
308 self.store.cache_get(k).map(|stamped| stamped.1.clone()),
309 false,
310 )
311 }
312 Status::Expired => {
313 self.misses += 1;
314 (self.store.cache_remove(k).map(|stamped| stamped.1), true)
315 }
316 }
317 }
318}
319
320#[cfg(feature = "async")]
321#[async_trait]
322impl<K, V> CachedAsync<K, V> for TimedSizedCache<K, V>
323where
324 K: Hash + Eq + Clone + Send,
325{
326 async fn get_or_set_with<F, Fut>(&mut self, key: K, f: F) -> &mut V
327 where
328 V: Send,
329 F: FnOnce() -> Fut + Send,
330 Fut: Future<Output = V> + Send,
331 {
332 let setter = || async { (Instant::now(), f().await) };
333 let max_seconds = self.seconds;
334 let (was_present, was_valid, stamped) = self
335 .store
336 .get_or_set_with_if_async(key, setter, |stamped| {
337 stamped.0.elapsed().as_secs() < max_seconds
338 })
339 .await;
340 if was_present && was_valid {
341 if self.refresh {
342 stamped.0 = Instant::now();
343 }
344 self.hits += 1;
345 } else {
346 self.misses += 1;
347 }
348 &mut stamped.1
349 }
350
351 async fn try_get_or_set_with<F, Fut, E>(&mut self, key: K, f: F) -> Result<&mut V, E>
352 where
353 V: Send,
354 F: FnOnce() -> Fut + Send,
355 Fut: Future<Output = Result<V, E>> + Send,
356 {
357 let setter = || async {
358 let new_val = f().await?;
359 Ok((Instant::now(), new_val))
360 };
361 let max_seconds = self.seconds;
362 let (was_present, was_valid, stamped) = self
363 .store
364 .try_get_or_set_with_if_async(key, setter, |stamped| {
365 stamped.0.elapsed().as_secs() < max_seconds
366 })
367 .await?;
368 if was_present && was_valid {
369 if self.refresh {
370 stamped.0 = Instant::now();
371 }
372 self.hits += 1;
373 } else {
374 self.misses += 1;
375 }
376 Ok(&mut stamped.1)
377 }
378}
379
380#[cfg(test)]
381mod tests {
383 use std::{thread::sleep, time::Duration};
384
385 use super::*;
386
387 #[test]
388 fn timed_sized_cache() {
389 let mut c = TimedSizedCache::with_size_and_lifespan(5, 2);
390 assert!(c.cache_get(&1).is_none());
391 let misses = c.cache_misses().unwrap();
392 assert_eq!(1, misses);
393
394 assert_eq!(c.cache_set(1, 100), None);
395 assert!(c.cache_get(&1).is_some());
396 let hits = c.cache_hits().unwrap();
397 let misses = c.cache_misses().unwrap();
398 assert_eq!(1, hits);
399 assert_eq!(1, misses);
400
401 assert_eq!(c.cache_set(2, 100), None);
402 assert_eq!(c.cache_set(3, 100), None);
403 assert_eq!(c.cache_set(4, 100), None);
404 assert_eq!(c.cache_set(5, 100), None);
405
406 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [5, 4, 3, 2, 1]);
407
408 sleep(Duration::new(1, 0));
409
410 assert_eq!(c.cache_set(6, 100), None);
411 assert_eq!(c.cache_set(7, 100), None);
412
413 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [7, 6, 5, 4, 3]);
414
415 assert!(c.cache_get(&2).is_none());
416 assert!(c.cache_get(&3).is_some());
417
418 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [3, 7, 6, 5, 4]);
419
420 assert_eq!(2, c.cache_misses().unwrap());
421 assert_eq!(5, c.cache_size());
422
423 sleep(Duration::new(1, 0));
424
425 assert!(c.cache_get(&1).is_none());
426 assert!(c.cache_get(&2).is_none());
427 assert!(c.cache_get(&3).is_none());
428 assert!(c.cache_get(&4).is_none());
429 assert!(c.cache_get(&5).is_none());
430 assert!(c.cache_get(&6).is_some());
431 assert!(c.cache_get(&7).is_some());
432
433 assert_eq!(7, c.cache_misses().unwrap());
434
435 assert!(c.cache_set(1, 100).is_none());
436 assert!(c.cache_set(2, 100).is_none());
437 assert!(c.cache_set(3, 100).is_none());
438 assert_eq!(c.key_order().copied().collect::<Vec<_>>(), [3, 2, 1, 7, 6]);
439
440 sleep(Duration::new(1, 0));
441
442 assert!(c.cache_get(&1).is_some());
443 assert!(c.cache_get(&2).is_some());
444 assert!(c.cache_get(&3).is_some());
445 assert!(c.cache_get(&4).is_none());
446 assert!(c.cache_get(&5).is_none());
447 assert!(c.cache_get(&6).is_none());
448 assert!(c.cache_get(&7).is_none());
449
450 assert_eq!(11, c.cache_misses().unwrap());
451
452 let mut c = TimedSizedCache::with_size_and_lifespan(5, 0);
453 let mut ticker = 0;
454 let setter = || {
455 let v = ticker;
456 ticker += 1;
457 v
458 };
459 assert_eq!(c.cache_get_or_set_with(1, setter), &0);
460 let setter = || {
461 let v = ticker;
462 ticker += 1;
463 v
464 };
465 assert_eq!(c.cache_get_or_set_with(1, setter), &1);
466 }
467
468 #[test]
469 fn timed_cache_refresh() {
470 let mut c = TimedSizedCache::with_size_and_lifespan_and_refresh(2, 2, true);
471 assert!(c.refresh());
472 assert_eq!(c.cache_get(&1), None);
473 let misses = c.cache_misses().unwrap();
474 assert_eq!(1, misses);
475
476 assert_eq!(c.cache_set(1, 100), None);
477 assert_eq!(c.cache_get(&1), Some(&100));
478 let hits = c.cache_hits().unwrap();
479 let misses = c.cache_misses().unwrap();
480 assert_eq!(1, hits);
481 assert_eq!(1, misses);
482
483 assert_eq!(c.cache_set(2, 200), None);
484 assert_eq!(c.cache_get(&2), Some(&200));
485 sleep(Duration::new(1, 0));
486 assert_eq!(c.cache_get(&1), Some(&100));
487 sleep(Duration::new(1, 0));
488 assert_eq!(c.cache_get(&1), Some(&100));
489 assert_eq!(c.cache_get(&2), None);
490 }
491
492 #[test]
493 fn try_new() {
494 let c: std::io::Result<TimedSizedCache<i32, i32>> =
495 TimedSizedCache::try_with_size_and_lifespan(0, 2);
496 assert_eq!(c.unwrap_err().raw_os_error(), Some(22));
497 }
498
499 #[test]
500 fn clear() {
501 let mut c = TimedSizedCache::with_size_and_lifespan(3, 3600);
502
503 assert_eq!(c.cache_set(1, 100), None);
504 assert_eq!(c.cache_set(2, 200), None);
505 assert_eq!(c.cache_set(3, 300), None);
506 c.cache_clear();
507
508 assert_eq!(0, c.cache_size());
509 }
510
511 #[test]
512 fn reset() {
513 let init_capacity = 1;
514 let mut c = TimedSizedCache::with_size_and_lifespan(init_capacity, 100);
515 assert_eq!(c.cache_set(1, 100), None);
516 assert_eq!(c.cache_set(2, 200), None);
517 assert_eq!(c.cache_set(3, 300), None);
518 assert!(init_capacity <= c.store.capacity);
519
520 c.cache_reset();
521 assert!(init_capacity <= c.store.capacity);
522 }
523
524 #[test]
525 fn remove() {
526 let mut c = TimedSizedCache::with_size_and_lifespan(3, 3600);
527
528 assert_eq!(c.cache_set(1, 100), None);
529 assert_eq!(c.cache_set(2, 200), None);
530 assert_eq!(c.cache_set(3, 300), None);
531
532 assert_eq!(Some(100), c.cache_remove(&1));
533 assert_eq!(2, c.cache_size());
534
535 assert_eq!(Some(200), c.cache_remove(&2));
536 assert_eq!(1, c.cache_size());
537
538 assert_eq!(None, c.cache_remove(&2));
539 assert_eq!(1, c.cache_size());
540
541 assert_eq!(Some(300), c.cache_remove(&3));
542 assert_eq!(0, c.cache_size());
543 }
544
545 #[test]
546 fn remove_expired() {
547 let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
548
549 assert_eq!(c.cache_set(1, 100), None);
550 assert_eq!(c.cache_set(1, 200), Some(100));
551 assert_eq!(c.cache_size(), 1);
552
553 std::thread::sleep(std::time::Duration::from_secs(1));
554 assert_eq!(None, c.cache_remove(&1));
555 assert_eq!(0, c.cache_size());
556 }
557
558 #[test]
559 fn insert_expired() {
560 let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
561
562 assert_eq!(c.cache_set(1, 100), None);
563 assert_eq!(c.cache_set(1, 200), Some(100));
564 assert_eq!(c.cache_size(), 1);
565
566 std::thread::sleep(std::time::Duration::from_secs(1));
567 assert_eq!(1, c.cache_size());
568 assert_eq!(None, c.cache_set(1, 300));
569 assert_eq!(1, c.cache_size());
570 }
571
572 #[test]
573 fn get_expired() {
574 let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
575
576 assert_eq!(c.cache_set(1, 100), None);
577 assert_eq!(c.cache_set(1, 200), Some(100));
578 assert_eq!(c.cache_size(), 1);
579
580 std::thread::sleep(std::time::Duration::from_secs(1));
581 assert_eq!(1, c.cache_size());
583 assert_eq!(None, c.cache_get(&1));
584 assert_eq!(0, c.cache_size());
585 }
586
587 #[test]
588 fn get_mut_expired() {
589 let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
590
591 assert_eq!(c.cache_set(1, 100), None);
592 assert_eq!(c.cache_set(1, 200), Some(100));
593 assert_eq!(c.cache_size(), 1);
594
595 std::thread::sleep(std::time::Duration::from_secs(1));
596 assert_eq!(1, c.cache_size());
598 assert_eq!(None, c.cache_get_mut(&1));
599 assert_eq!(0, c.cache_size());
600 }
601
602 #[test]
603 fn flush_expired() {
604 let mut c = TimedSizedCache::with_size_and_lifespan(3, 1);
605
606 assert_eq!(c.cache_set(1, 100), None);
607 assert_eq!(c.cache_set(1, 200), Some(100));
608 assert_eq!(c.cache_size(), 1);
609
610 std::thread::sleep(std::time::Duration::from_secs(2));
611 assert_eq!(1, c.cache_size());
613 c.flush();
614 assert_eq!(0, c.cache_size());
615 }
616
617 #[test]
618 fn get_or_set_with() {
619 let mut c = TimedSizedCache::with_size_and_lifespan(5, 2);
620
621 assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
622 assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
623 assert_eq!(c.cache_get_or_set_with(2, || 2), &2);
624 assert_eq!(c.cache_get_or_set_with(3, || 3), &3);
625 assert_eq!(c.cache_get_or_set_with(4, || 4), &4);
626 assert_eq!(c.cache_get_or_set_with(5, || 5), &5);
627
628 assert_eq!(c.cache_misses(), Some(6));
629
630 assert_eq!(c.cache_get_or_set_with(0, || 0), &0);
631
632 assert_eq!(c.cache_misses(), Some(7));
633
634 assert_eq!(c.cache_get_or_set_with(0, || 42), &0);
635
636 sleep(Duration::new(1, 0));
637
638 assert_eq!(c.cache_get_or_set_with(0, || 42), &0);
639
640 assert_eq!(c.cache_get_or_set_with(1, || 1), &1);
641
642 assert_eq!(c.cache_get_or_set_with(4, || 42), &4);
643
644 assert_eq!(c.cache_get_or_set_with(5, || 42), &5);
645
646 assert_eq!(c.cache_get_or_set_with(6, || 6), &6);
647
648 assert_eq!(c.cache_misses(), Some(9));
649
650 sleep(Duration::new(1, 0));
651
652 assert_eq!(c.cache_get_or_set_with(4, || 42), &42);
653
654 assert_eq!(c.cache_get_or_set_with(5, || 42), &42);
655
656 assert_eq!(c.cache_get_or_set_with(6, || 42), &6);
657
658 assert_eq!(c.cache_misses(), Some(11));
659
660 c.cache_reset();
661 fn _try_get(n: usize) -> Result<usize, String> {
662 if n < 10 {
663 Ok(n)
664 } else {
665 Err("dead".to_string())
666 }
667 }
668
669 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(10));
670 assert!(res.is_err());
671 assert!(c.key_order().next().is_none());
672
673 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(1));
674 assert_eq!(res.unwrap(), &1);
675 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(5));
676 assert_eq!(res.unwrap(), &1);
677 sleep(Duration::new(2, 0));
678 let res: Result<&mut usize, String> = c.cache_try_get_or_set_with(0, || _try_get(5));
679 assert_eq!(res.unwrap(), &5);
680 }
681
682 #[cfg(feature = "async")]
683 #[tokio::test]
684 async fn test_async_trait_timed_sized() {
685 use crate::CachedAsync;
686 let mut c = TimedSizedCache::with_size_and_lifespan(5, 1);
687
688 async fn _get(n: usize) -> usize {
689 n
690 }
691
692 assert_eq!(c.get_or_set_with(0, || async { _get(0).await }).await, &0);
693 assert_eq!(c.get_or_set_with(1, || async { _get(1).await }).await, &1);
694 assert_eq!(c.get_or_set_with(2, || async { _get(2).await }).await, &2);
695 assert_eq!(c.get_or_set_with(3, || async { _get(3).await }).await, &3);
696
697 assert_eq!(c.get_or_set_with(0, || async { _get(3).await }).await, &0);
698 assert_eq!(c.get_or_set_with(1, || async { _get(3).await }).await, &1);
699 assert_eq!(c.get_or_set_with(2, || async { _get(3).await }).await, &2);
700 assert_eq!(c.get_or_set_with(3, || async { _get(1).await }).await, &3);
701
702 sleep(Duration::new(1, 0));
703 assert_eq!(c.get_or_set_with(0, || async { _get(3).await }).await, &3);
705
706 c.cache_reset();
707 async fn _try_get(n: usize) -> Result<usize, String> {
708 if n < 10 {
709 Ok(n)
710 } else {
711 Err("dead".to_string())
712 }
713 }
714
715 assert_eq!(
716 c.try_get_or_set_with(0, || async {
717 match _try_get(0).await {
718 Ok(n) => Ok(n),
719 Err(_) => Err("err".to_string()),
720 }
721 })
722 .await
723 .unwrap(),
724 &0
725 );
726 assert_eq!(
727 c.try_get_or_set_with(0, || async {
728 match _try_get(5).await {
729 Ok(n) => Ok(n),
730 Err(_) => Err("err".to_string()),
731 }
732 })
733 .await
734 .unwrap(),
735 &0
736 );
737
738 c.cache_reset();
739 let res: Result<&mut usize, String> = c
740 .try_get_or_set_with(0, || async { _try_get(10).await })
741 .await;
742 assert!(res.is_err());
743 assert!(c.key_order().next().is_none());
744
745 let res: Result<&mut usize, String> = c
746 .try_get_or_set_with(0, || async { _try_get(1).await })
747 .await;
748 assert_eq!(res.unwrap(), &1);
749 let res: Result<&mut usize, String> = c
750 .try_get_or_set_with(0, || async { _try_get(5).await })
751 .await;
752 assert_eq!(res.unwrap(), &1);
753 sleep(Duration::new(1, 0));
754 let res: Result<&mut usize, String> = c
755 .try_get_or_set_with(0, || async { _try_get(5).await })
756 .await;
757 assert_eq!(res.unwrap(), &5);
758 }
759}