我有简单的 Rocket.rs 应用程序和注册路线
这是使用 mongodb 同步驱动程序的服务
pub async fn create_new_user(user_email: &str, password: &str, user_name: &str) -> Result<(), &'static str> {
let users_collection: mongodb::Collection<UserModel> = DB.collection("users");
// check if user with given email or name already exists
let existing_user = users_collection.find_one(
doc! {
"$or": [
{"user_email": user_email},
{"user_name": user_name}
]
},
None
);
if existing_user.is_ok() {
return Err("User with such email or name already exists");
}
// new user struct
let new_user = UserModel {
user_id: /* hash gen fn */,
user_name: user_name.to_string(),
email: user_email.to_string(),
hashed_password: password.to_string(),
verified: false,
};
// insert new user into db
let insert_result = DB.collection("users").insert_one(new_user, None);
if insert_result.is_ok() {
return Ok(());
} else {
return Err("Failed to create user");
}
}
不幸的是,火箭拒绝与同步驱动程序一起工作,我需要一个异步驱动程序
如何添加到应用程序中?因为我不知道,我在谷歌中找到的唯一东西是我不理解的过于复杂的代码或异步驱动程序文档......
// how it was with sync one...
static DB: Lazy<Database> = Lazy::new(
|| {
let client = Client::with_uri_str(&CONFIG.mongodb_uri_string);
client.database("silly-tips")
}
);
// now
static DB: once_cell:unsync::Lazy<Database> = once_cell:unsync::Lazy::new(
async {
let client = Client::with_uri_str(&CONFIG.mongodb_uri_string).await.expect("Error connecting to MongoDB");
client.database("silly-tips")
}
);
`Cell<std::option::Option<fn() -> Database>>` cannot be shared between threads safely
within `once_cell::unsync::Lazy<Database>`, the trait `Sync` is not implemented for `Cell<std::option::Option<fn() -> Database>>`, which is required by `once_cell::unsync::Lazy<Database>: Sync`
if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
shared static variables must have a type that implements `Sync`rustcClick for full compiler diagnostic
实现此目标的一种可能方法是使用管理数据库连接的
Rocket.rs
修改您的 tokio::sync::OnceCell
应用程序,使其与异步 MongoDB 驱动程序一起运行。
[dependencies]
rocket = "0.5.0-rc.2"
tokio = { version = "1", features = ["full"] }
mongodb = { version = "2.0", features = ["tokio-runtime"] }
serde = { version = "1.0", features = ["derive"] }
once_cell = "1.10.0"
use mongodb::{Client, Database};
use once_cell::sync::OnceCell;
use rocket::fairing::AdHoc;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
static DB: OnceCell<Arc<RwLock<Database>>> = OnceCell::new();
#[derive(Serialize, Deserialize)]
struct UserModel {
user_id: String,
user_name: String,
email: String,
hashed_password: String,
verified: bool,
}
async fn init_db() -> Arc<RwLock<Database>> {
let client = Client::with_uri_str("mongodb://localhost:27017").await.expect("Error connecting to MongoDB");
Arc::new(RwLock::new(client.database("silly-tips")))
}
#[rocket::main]
async fn main() {
let db = init_db().await;
DB.set(db).expect("Failed to set DB instance");
rocket::build()
.attach(AdHoc::on_ignite("MongoDB", |rocket| async {
rocket.manage(DB.get().unwrap().clone())
}))
.launch()
.await
.expect("Failed to launch Rocket");
}
create_new_user
函数以使用异步 MongoDB 操作pub async fn create_new_user(user_email: &str, password: &str, user_name: &str) -> Result<(), &'static str> {
let db = DB.get().expect("DB instance not set");
let users_collection = db.read().await.collection::<UserModel>("users");
let existing_user = users_collection.find_one(
doc! {
"$or": [
{"email": user_email},
{"user_name": user_name}
]
},
None
).await;
if let Ok(Some(_)) = existing_user {
return Err("User with such email or name already exists");
}
let new_user = UserModel {
user_id: /* hash gen fn */,
user_name: user_name.to_string(),
email: user_email.to_string(),
hashed_password: password.to_string(),
verified: false,
};
let insert_result = users_collection.insert_one(new_user, None).await;
if insert_result.is_ok() {
Ok(())
} else {
Err("Failed to create user")
}
}