oxide_framework_mongodb/
lib.rs1use async_trait::async_trait;
2use mongodb::{Client, Database};
3use oxide_framework_core::{App, FrameworkError, ReadinessCheck};
4
5#[derive(Clone, Debug)]
6pub struct MongoConfig {
7 pub uri: String,
8 pub database: String,
9 pub strict: bool,
10}
11
12impl MongoConfig {
13 pub fn new(uri: impl Into<String>, database: impl Into<String>) -> Self {
14 Self {
15 uri: uri.into(),
16 database: database.into(),
17 strict: false,
18 }
19 }
20
21 pub fn strict(mut self, strict: bool) -> Self {
22 self.strict = strict;
23 self
24 }
25}
26
27#[derive(Clone)]
28pub struct MongoHandle {
29 pub client: Client,
30 pub db: Database,
31}
32
33impl MongoHandle {
34 pub async fn connect(config: &MongoConfig) -> Result<Self, FrameworkError> {
35 let client = Client::with_uri_str(&config.uri)
36 .await
37 .map_err(|e| FrameworkError::Internal(format!("mongodb connect failed: {e}")))?;
38 let db = client.database(&config.database);
39 Ok(Self { client, db })
40 }
41
42 pub async fn ping(&self) -> Result<(), FrameworkError> {
43 self.db
44 .run_command(mongodb::bson::doc! { "ping": 1 })
45 .await
46 .map(|_| ())
47 .map_err(|e| FrameworkError::ReadinessFailed {
48 check: "mongodb",
49 message: e.to_string(),
50 })
51 }
52}
53
54#[derive(Clone)]
55struct MongoReady(MongoHandle);
56
57#[async_trait]
58impl ReadinessCheck for MongoReady {
59 fn name(&self) -> &'static str {
60 "mongodb"
61 }
62
63 async fn check(&self) -> Result<(), FrameworkError> {
64 self.0.ping().await
65 }
66}
67
68pub trait AppMongoExt {
69 fn mongodb(self, config: MongoConfig) -> Self;
70}
71
72impl AppMongoExt for App {
73 fn mongodb(self, config: MongoConfig) -> Self {
74 let strict = config.strict;
75 let cfg_for_init = config.clone();
76 let handle = std::thread::spawn(move || {
77 let rt = tokio::runtime::Runtime::new()
78 .expect("failed to create runtime for mongodb init");
79 rt.block_on(MongoHandle::connect(&cfg_for_init))
80 })
81 .join()
82 .expect("failed to join mongodb init thread")
83 .expect("failed to initialize mongodb client");
84
85 let app = self.state(handle.clone());
86 if strict {
87 app.readiness_check(MongoReady(handle))
88 } else {
89 app
90 }
91 }
92}