apollo_router/context/extensions/
sync.rs1use std::ops::Deref;
2use std::ops::DerefMut;
3use std::sync::Arc;
4#[cfg(debug_assertions)]
5use std::time::Duration;
6#[cfg(debug_assertions)]
7use std::time::Instant;
8
9#[derive(Default, Clone, Debug)]
17pub struct ExtensionsMutex {
18 extensions: Arc<parking_lot::Mutex<super::Extensions>>,
19}
20
21impl ExtensionsMutex {
22 #[deprecated]
31 pub fn lock(&self) -> ExtensionsGuard {
32 ExtensionsGuard::new(&self.extensions)
33 }
34
35 pub fn with_lock<'a, T, F: FnOnce(ExtensionsGuard<'a>) -> T>(&'a self, func: F) -> T {
39 let locked = ExtensionsGuard::new(&self.extensions);
40 func(locked)
41 }
42}
43
44pub struct ExtensionsGuard<'a> {
45 #[cfg(debug_assertions)]
46 start: Instant,
47 guard: parking_lot::MutexGuard<'a, super::Extensions>,
48}
49impl<'a> ExtensionsGuard<'a> {
50 fn new(guard: &'a parking_lot::Mutex<super::Extensions>) -> Self {
51 Self {
54 guard: guard.lock(),
55 #[cfg(debug_assertions)]
56 start: Instant::now(),
57 }
58 }
59}
60
61impl Deref for ExtensionsGuard<'_> {
62 type Target = super::Extensions;
63
64 fn deref(&self) -> &super::Extensions {
65 &self.guard
66 }
67}
68
69impl DerefMut for ExtensionsGuard<'_> {
70 fn deref_mut(&mut self) -> &mut super::Extensions {
71 &mut self.guard
72 }
73}
74
75#[cfg(debug_assertions)]
76impl Drop for ExtensionsGuard<'_> {
77 fn drop(&mut self) {
78 if let Ok(runtime) = tokio::runtime::Handle::try_current() {
81 if runtime.runtime_flavor() == tokio::runtime::RuntimeFlavor::MultiThread {
82 let elapsed = self.start.elapsed();
83 if elapsed > Duration::from_millis(10) {
84 panic!(
85 "ExtensionsGuard held for {}ms. This is probably a bug that will stall the Router and cause performance problems. Run with `RUST_BACKTRACE=1` environment variable to display a backtrace",
86 elapsed.as_millis()
87 );
88 }
89 }
90 }
91 }
92}