Rust - 无法从 Rocket State 访问 r2d2 池连接
Rust - Cannot Access r2d2 pool connection from Rocket State
我目前正在学习 Rust 和 Rocket
使用 Rust 1.54.0+Rocket 0.5.0_rc1+ Diesel 1.4.7 + r2d2 0.8.9
我用 r2d2 创建了一个 DB Postgres 连接池。我想在 requests/Routes 之间共享连接池,为此我正在尝试使用 Rocket Managed State。 https://rocket.rs/v0.5-rc/guide/state/#managed-state
我创建了一个数据库连接池,将其保存在状态中,但是当我尝试从路由访问该数据库连接池时。我在同一行收到 2 个错误
Cell<i32> cannot be shared between threads safely
RefCell<HashMap<StatementCacheKey<Pg>, pg::connection::stmt::Statement>> cannot be shared between threads safely
这是我的代码
pub async fn establish_pooled_connection() -> Result<PooledConnection<ConnectionManager<PgConnection>>, r2d2_diesel::Error> {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let manager = ConnectionManager::<PgConnection>::new(&database_url);
let pool = r2d2::Pool::builder().build(manager).expect("Failed to create pool.");
let conn = pool.clone().get().unwrap();
Ok(conn)
}
struct DBPool{
db_pool: PooledConnection<ConnectionManager<PgConnection>>
}
#[rocket::main]
async fn main() {
let pool = establish_pooled_connection();
rocket::build()
.mount("/",routes![callapi])
.manage(DBPool{db_pool: pool})
.launch()
.await.ok();
}
#[post("/callapi", data = "<request>")]
async fn callapi(request: RequestAPI<'_>, _dbpool: &State<DBPool>) -> Json<models::api_response::ApiResponse> {
......
这个参数的错误
_dbpool: &State<DBPool>
提前致谢
终于,我能够完成这项工作了。
我主要使用这个 GitHub 存储库作为基础
https://github.com/practical-rust-web-development/mystore/tree/v1.1
回购协议使用 Actix,但我使用的是 Rocket。
我想我的主要误解是基本的 PostgreSQL 连接是一个 PGConnection,而你从池中得到的是一个 PGPooledConnection,它最后是相同的。
这是我的代码
db_connection.rs
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
use diesel::r2d2::{ Pool, PooledConnection, ConnectionManager, PoolError };
pub type PgPool = Pool<ConnectionManager<PgConnection>>;
pub type PgPooledConnection = PooledConnection<ConnectionManager<PgConnection>>;
//Connects to Postgres and call init pool
pub fn establish_connection() -> PgPool {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
init_pool(&database_url).expect("Failed to create pool")
}
//Creates a default R2D2 Postgres DB Pool
fn init_pool(database_url: &str) -> Result<PgPool, PoolError> {
let manager = ConnectionManager::<PgConnection>::new(database_url);
Pool::builder().build(manager)
}
//this functions returns a connection from the Pool
pub fn pg_pool_handler(pool: &PgPool) -> Result<PgPooledConnection, PoolError> {
let _pool = pool.get().unwrap();
Ok(_pool)
}
main.rs
mod db_connection;
use db_connection::{PgPool};
#[rocket::main]
async fn main() {
rocket::build()
.mount("/API",routes![demo])
.manage(db_connection::establish_connection()) //here is where you pass the pool to Rocket state.
.launch()
.await.ok();
}
#[post("/demo", data = "<request>")]
async fn demo _dbpool: &State<PgPool>) -> Json<models::Response> {
let connection = db_connection::pg_pool_handler(_dbpool).unwrap();
let results = users.limit(1)
.load::<User>(&connection)
.expect("Error loading users");
........
这是基本代码,可以改进代码以更好地处理错误。
我目前正在学习 Rust 和 Rocket
使用 Rust 1.54.0+Rocket 0.5.0_rc1+ Diesel 1.4.7 + r2d2 0.8.9
我用 r2d2 创建了一个 DB Postgres 连接池。我想在 requests/Routes 之间共享连接池,为此我正在尝试使用 Rocket Managed State。 https://rocket.rs/v0.5-rc/guide/state/#managed-state
我创建了一个数据库连接池,将其保存在状态中,但是当我尝试从路由访问该数据库连接池时。我在同一行收到 2 个错误
Cell<i32> cannot be shared between threads safely
RefCell<HashMap<StatementCacheKey<Pg>, pg::connection::stmt::Statement>> cannot be shared between threads safely
这是我的代码
pub async fn establish_pooled_connection() -> Result<PooledConnection<ConnectionManager<PgConnection>>, r2d2_diesel::Error> {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
let manager = ConnectionManager::<PgConnection>::new(&database_url);
let pool = r2d2::Pool::builder().build(manager).expect("Failed to create pool.");
let conn = pool.clone().get().unwrap();
Ok(conn)
}
struct DBPool{
db_pool: PooledConnection<ConnectionManager<PgConnection>>
}
#[rocket::main]
async fn main() {
let pool = establish_pooled_connection();
rocket::build()
.mount("/",routes![callapi])
.manage(DBPool{db_pool: pool})
.launch()
.await.ok();
}
#[post("/callapi", data = "<request>")]
async fn callapi(request: RequestAPI<'_>, _dbpool: &State<DBPool>) -> Json<models::api_response::ApiResponse> {
......
这个参数的错误
_dbpool: &State<DBPool>
提前致谢
终于,我能够完成这项工作了。
我主要使用这个 GitHub 存储库作为基础 https://github.com/practical-rust-web-development/mystore/tree/v1.1 回购协议使用 Actix,但我使用的是 Rocket。
我想我的主要误解是基本的 PostgreSQL 连接是一个 PGConnection,而你从池中得到的是一个 PGPooledConnection,它最后是相同的。
这是我的代码
db_connection.rs
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;
use diesel::r2d2::{ Pool, PooledConnection, ConnectionManager, PoolError };
pub type PgPool = Pool<ConnectionManager<PgConnection>>;
pub type PgPooledConnection = PooledConnection<ConnectionManager<PgConnection>>;
//Connects to Postgres and call init pool
pub fn establish_connection() -> PgPool {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
init_pool(&database_url).expect("Failed to create pool")
}
//Creates a default R2D2 Postgres DB Pool
fn init_pool(database_url: &str) -> Result<PgPool, PoolError> {
let manager = ConnectionManager::<PgConnection>::new(database_url);
Pool::builder().build(manager)
}
//this functions returns a connection from the Pool
pub fn pg_pool_handler(pool: &PgPool) -> Result<PgPooledConnection, PoolError> {
let _pool = pool.get().unwrap();
Ok(_pool)
}
main.rs
mod db_connection;
use db_connection::{PgPool};
#[rocket::main]
async fn main() {
rocket::build()
.mount("/API",routes![demo])
.manage(db_connection::establish_connection()) //here is where you pass the pool to Rocket state.
.launch()
.await.ok();
}
#[post("/demo", data = "<request>")]
async fn demo _dbpool: &State<PgPool>) -> Json<models::Response> {
let connection = db_connection::pg_pool_handler(_dbpool).unwrap();
let results = users.limit(1)
.load::<User>(&connection)
.expect("Error loading users");
........
这是基本代码,可以改进代码以更好地处理错误。