I use sqlx for initializing mysql connection (asynchronous) using lazy_static
but weird errors occurred.
This is the code that I wrote:
use actix_web::middleware::Logger;
use actix_web::web::{Data, JsonConfig};
use actix_web::{App, HttpServer};
lazy_static::lazy_static! {
static ref MYSQL_DB: async_once::AsyncOnce<sqlx::Pool<sqlx::MySql>> = async_once::AsyncOnce::new(async {
dotenv::dotenv().expect("Failed to read .env file");
let uri = std::env::var("DATABASE_URL").unwrap();
sqlx::MySqlPool::connect(uri.as_str()).await.unwrap()
});
static ref DB_CLIENT : DBClient = DBClient{};
}
#[derive(Clone, Copy)]
pub struct DBClient;
impl DBClient {
pub fn get() -> &'static DBClient {
&DB_CLIENT
}
pub async fn mysql_pool(self) -> &'static sqlx::Pool<sqlx::MySql> {
MYSQL_DB.get().await
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// start_tracing();
let db_client = Data::new(DBClient::get());
dotenv::dotenv().expect("Failed to read .env file");
HttpServer::new(move || {
App::new()
.wrap(Logger::default())
.app_data(Data::new(JsonConfig::default().limit(4096)))
.app_data(db_client.clone())
})
.bind(format!(
"{}:{}",
std::env::var("HOST").unwrap(),
std::env::var("PORT").unwrap()
))
.expect("Server binding exception")
.run()
.await
}
This is my Cargo.toml file:
[package]
name = "untitled"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4.0.1"
sqlx = { version = "0.5.*", features = ["mysql", "runtime-async-std-native-tls"] }
actix-rt = "2.*"
juniper = { version = "0.15.9", features = ["chrono"] }
uuid = { version = "=0.8", features = ["serde", "v4"] }
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
dotenv = "0.15.0"
lazy_static = "1.4.*"
async_once = "0.2.6"
validator = { version = "0.12", features = ["derive"] }
This is my .env file:
DATABASE_URL=mysql://user_name:password@localhost:3306/db_name
HOST=127.0.0.1
PORT=3000
And these are my errors:
error[E0277]: `*const Pool<MySql>` cannot be sent between threads safely
--> src/main.rs:6:1
|
6 | / lazy_static::lazy_static! {
7 | | static ref MYSQL_DB: async_once::AsyncOnce<sqlx::Pool<sqlx::MySql>> = async_once::AsyncOnce::new(async {
8 | | dotenv::dotenv().expect("Failed to read .env file");
9 | | let uri = env::var("DATABASE_URL").unwrap();
... |
12 | | static ref DB_CLIENT : DBClient = DBClient{};
13 | | }
| |_^ `*const Pool<MySql>` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `*const Pool<MySql>`
= note: required because of the requirements on the impl of `Send` for `Cell<*const Pool<MySql>>`
= note: required because it appears within the type `AsyncOnce<Pool<MySql>>`
= note: required because of the requirements on the impl of `Sync` for `spin::once::Once<AsyncOnce<Pool<MySql>>>`
= note: required because it appears within the type `lazy_static::lazy::Lazy<AsyncOnce<Pool<MySql>>>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `__lazy_static_create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `(dyn std::future::Future<Output = Pool<MySql>> + 'static)` cannot be sent between threads safely
--> src/main.rs:6:1
|
6 | / lazy_static::lazy_static! {
7 | | static ref MYSQL_DB: async_once::AsyncOnce<sqlx::Pool<sqlx::MySql>> = async_once::AsyncOnce::new(async {
8 | | dotenv::dotenv().expect("Failed to read .env file");
9 | | let uri = env::var("DATABASE_URL").unwrap();
... |
12 | | static ref DB_CLIENT : DBClient = DBClient{};
13 | | }
| |_^ `(dyn std::future::Future<Output = Pool<MySql>> + 'static)` cannot be sent between threads safely
|
= help: the trait `Send` is not implemented for `(dyn std::future::Future<Output = Pool<MySql>> + 'static)`
= note: required because of the requirements on the impl of `Send` for `Unique<(dyn std::future::Future<Output = Pool<MySql>> + 'static)>`
= note: required because it appears within the type `Box<(dyn std::future::Future<Output = Pool<MySql>> + 'static)>`
= note: required because it appears within the type `Pin<Box<(dyn std::future::Future<Output = Pool<MySql>> + 'static)>>`
= note: required because it appears within the type `Result<Pool<MySql>, Pin<Box<(dyn std::future::Future<Output = Pool<MySql>> + 'static)>>>`
= note: required because of the requirements on the impl of `Send` for `Mutex<Result<Pool<MySql>, Pin<Box<(dyn std::future::Future<Output = Pool<MySql>> + 'static)>>>>`
= note: required because it appears within the type `AsyncOnce<Pool<MySql>>`
= note: required because of the requirements on the impl of `Sync` for `spin::once::Once<AsyncOnce<Pool<MySql>>>`
= note: required because it appears within the type `lazy_static::lazy::Lazy<AsyncOnce<Pool<MySql>>>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `__lazy_static_create` (in Nightly builds, run with -Z macro-backtrace for more info)
I don't know the reason of the errors, but when I do the following it builds successfully:
Replace the connection with
Pool<Postgres>
Change the
mysql
topostgres
in sqlx'sfeatures
section in Cargo.toml.Change
DATABASE_URL
in the .env file to Postgres URI
I got help from this question in stackoverflow: Rust lazy_static with async/await?