mobc_surrealdb/
lib.rs

1#![doc = include_str!("../README.md")]
2// Import necessary traits and types from external crates
3use mobc::async_trait;
4use mobc::Manager;
5use std::sync::Arc;
6use surrealdb::{Surreal, Error};
7use surrealdb::engine::any; // Enables runtime selection of engine
8
9/// Enum representing the supported connection protocols.
10#[derive(Debug, Clone)]
11pub enum ConnectionProtocol {
12    Http,
13    Https,
14    Ws,
15    Wss,
16}
17
18impl ConnectionProtocol {
19    /// Returns the scheme as a static string slice.
20    pub fn as_str(&self) -> &'static str {
21        match self {
22            ConnectionProtocol::Http => "http://",
23            ConnectionProtocol::Https => "https://",
24            ConnectionProtocol::Ws => "ws://",
25            ConnectionProtocol::Wss => "wss://",
26        }
27    }
28}
29
30/// A high‑performance SurrealDB connection manager using static string slices.
31/// The default connection protocol is WebSocket (ws), but users can override it.
32pub struct SurrealDBConnectionManager {
33    protocol: ConnectionProtocol, // The connection protocol; default is Ws.
34    db_url: &'static str,         // Server address (host:port/path)
35    db_user: &'static str,        // Username for authentication
36    db_password: &'static str,    // Password for authentication
37}
38
39impl SurrealDBConnectionManager {
40    /// Creates a new connection manager with the default protocol (ws).
41    pub fn new(
42        db_url: &'static str,
43        db_user: &'static str,
44        db_password: &'static str,
45    ) -> Self {
46        Self {
47            protocol: ConnectionProtocol::Ws, // Default to ws
48            db_url,
49            db_user,
50            db_password,
51        }
52    }
53
54    /// Creates a new connection manager with a custom protocol.
55    pub fn new_with_protocol(
56        protocol: ConnectionProtocol,
57        db_url: &'static str,
58        db_user: &'static str,
59        db_password: &'static str,
60    ) -> Self {
61        Self {
62            protocol,
63            db_url,
64            db_user,
65            db_password,
66        }
67    }
68}
69
70#[async_trait]
71impl Manager for SurrealDBConnectionManager {
72    // Use Surreal with the 'any' engine for runtime flexibility.
73    type Connection = Arc<Surreal<any::Any>>;
74    type Error = Error;
75
76    /// Establish a new connection.
77    async fn connect(&self) -> Result<Self::Connection, Self::Error> {
78        // Construct the full URL by concatenating the protocol and the server address.
79        let full_url = format!("{}{}", self.protocol.as_str(), self.db_url);
80        let db = any::connect(full_url).await?;
81        // Authenticate using the provided credentials.
82        db.signin(surrealdb::opt::auth::Root {
83            username: self.db_user,
84            password: self.db_password,
85        })
86        .await?;
87        // Return the connection wrapped in an Arc.
88        Ok(Arc::new(db))
89    }
90
91    /// Check the health of an existing connection.
92    async fn check(&self, conn: Self::Connection) -> Result<Self::Connection, Self::Error> {
93        let mut response = conn.query("RETURN 1").await?;
94        let result: Option<i32> = response.take(0)?;
95        if result == Some(1) {
96            Ok(conn)
97        } else {
98            Err(Error::Api(surrealdb::error::Api::Query(
99                "Health check failed".into(),
100            )))
101        }
102    }
103}