Skip to main content

reddb_server/runtime/
health_connection.rs

1use super::*;
2
3impl HealthProvider for RedDBRuntime {
4    fn health(&self) -> HealthReport {
5        let pool = self
6            .inner
7            .pool
8            .lock()
9            .unwrap_or_else(|poisoned| poisoned.into_inner());
10        let mut report = self.inner.db.health();
11        let (readiness_for_query, readiness_for_write, readiness_for_repair) =
12            self.inner.db.readiness_flags_from_health(&report);
13        report = report.with_diagnostic(
14            "runtime.mode",
15            if self.inner.layout.is_persistent() {
16                "persistent"
17            } else {
18                "in-memory"
19            },
20        );
21        report = report.with_diagnostic("runtime.active_connections", pool.active.to_string());
22        report = report.with_diagnostic("runtime.idle_connections", pool.idle.len().to_string());
23        report = report.with_diagnostic("readiness_for_query", readiness_for_query.to_string());
24        report = report.with_diagnostic("readiness_for_write", readiness_for_write.to_string());
25        report = report.with_diagnostic("readiness_for_repair", readiness_for_repair.to_string());
26        report.with_diagnostic(
27            "runtime.max_connections",
28            self.inner.pool_config.max_connections.to_string(),
29        )
30    }
31}
32
33impl RuntimeConnection {
34    pub fn id(&self) -> u64 {
35        self.id
36    }
37
38    pub fn db(&self) -> Arc<RedDB> {
39        Arc::clone(&self.inner.db)
40    }
41
42    pub fn scan_collection(
43        &self,
44        collection: &str,
45        cursor: Option<ScanCursor>,
46        limit: usize,
47    ) -> RedDBResult<ScanPage> {
48        RedDBRuntime {
49            background_tasks: self.background_tasks.clone(),
50            inner: Arc::clone(&self.inner),
51        }
52        .scan_collection(collection, cursor, limit)
53    }
54}
55
56impl Drop for RuntimeConnection {
57    fn drop(&mut self) {
58        let runtime = RedDBRuntime {
59            background_tasks: self.background_tasks.clone(),
60            inner: Arc::clone(&self.inner),
61        };
62        // Cleanup targets this lease, independently of the dropping thread's
63        // current connection. Never recycle a lease whose cleanup failed.
64        let reusable = match runtime.rollback_connection(self.id) {
65            Ok(_) => true,
66            Err(error) => {
67                tracing::error!(connection_id = self.id, %error, "connection rollback failed");
68                false
69            }
70        };
71        let mut pool = self
72            .inner
73            .pool
74            .lock()
75            .unwrap_or_else(|poisoned| poisoned.into_inner());
76        pool.active = pool.active.saturating_sub(1);
77        if self.uses_pool_slot {
78            pool.pooled_active = pool.pooled_active.saturating_sub(1);
79        }
80        if reusable && pool.idle.len() < self.inner.pool_config.max_idle {
81            pool.idle.push(self.id);
82        }
83        drop(pool);
84        // Issue #1245 — record the disconnect after releasing the pool lock.
85        self.inner.node_load_telemetry.record_disconnect();
86    }
87}