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            inner: Arc::clone(&self.inner),
50        }
51        .scan_collection(collection, cursor, limit)
52    }
53}
54
55impl Drop for RuntimeConnection {
56    fn drop(&mut self) {
57        let runtime = RedDBRuntime {
58            inner: Arc::clone(&self.inner),
59        };
60        // Cleanup targets this lease, independently of the dropping thread's
61        // current connection. Never recycle a lease whose cleanup failed.
62        let reusable = match runtime.rollback_connection(self.id) {
63            Ok(_) => true,
64            Err(error) => {
65                tracing::error!(connection_id = self.id, %error, "connection rollback failed");
66                false
67            }
68        };
69        let mut pool = self
70            .inner
71            .pool
72            .lock()
73            .unwrap_or_else(|poisoned| poisoned.into_inner());
74        pool.active = pool.active.saturating_sub(1);
75        if self.uses_pool_slot {
76            pool.pooled_active = pool.pooled_active.saturating_sub(1);
77        }
78        if reusable && pool.idle.len() < self.inner.pool_config.max_idle {
79            pool.idle.push(self.id);
80        }
81        drop(pool);
82        // Issue #1245 — record the disconnect after releasing the pool lock.
83        self.inner.node_load_telemetry.record_disconnect();
84    }
85}