Is pools close if their ownership moves?
Necoo33 opened this issue · 6 comments
Hello, i'm currently trying to use your package but i have some issues.
Here is my code:
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let ip_address_and_port = match env::var("IP_ADDRESS_AND_PORT") {
Ok(variable) => variable,
Err(_) => panic!("Cannot found 'IP_ADDRESS_AND_PORT' env variable."),
};
let db_conn_string = match env::var("DB_CONN_URL") {
Ok(variable) => variable,
Err(_) => panic!("Cannot found 'DB_CONN_STRING' env variable."),
};
let pool = database::create_db_pool(db_conn_string.as_str()).await;
let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.wrap(from_fn(authlogic::refresh_cookies))
.service(navctrl::home_controller)
.service(navctrl::about_us_controller)
.service(navctrl::contact_controller)
.service(routers::admin_panel_router())
.service(routers::posts_router())
});
server.bind((ip_address_and_port.as_str()))?.run().await?;
Ok(())
}
in this code, the pool variable is released when the server variable ends because of the move semantics and the pool variable freed from memory. In this case, is connection closed or not in the end of that code?
Hi.
In this case, is connection closed or not in the end of that code?
Which one? I mean that i see no code here that creates a connection so it's hard to answer the question.
in this code, the pool variable is released when the server variable ends because of the move semantics and the pool variable freed from memory
Note that Conn
if created from a pool holds a copy of this pool so it won't vanish while Conn
s exists. Also I believe that the copy is also alive within the factory closure
let pool = database::create_db_pool(db_conn_string.as_str()).await;
obviously the pool variable, just this code: let pool = database::create_db_pool(db_conn_string.as_str()).await;
. I don't think this isn't obvious, the source code is this:
pub async fn create_db_pool(url: &str) -> mysql_async::Pool {
return mysql_async::Pool::new(url);
}
Also i don't create a standalone connection, i create a connection pool.
If i pass that pool value with web::Data::new()
code that inside in the "server" variable takes the ownership of that pool variable, even that value is a clone. So i'm curious about if that variable freed from memory due to move of ownership, is that connection pool closed?
Oh, I see - pool is a reference-counted smart pointer. Every clone of a pool instance points to the same pool instance (see corresponding section in the docs)
Practically this means that pool won't close as long as there exist a clone.
Oh, I see - pool is a reference-counted smart pointer. Every clone of a pool instance points to the same pool instance (see corresponding section in the docs)
Practically this means that pool won't close as long as there exist a clone.
This is so abstract answer, because of that i'm writing this for make things Clear: my assumption is if there is no unclosed single connection and if ownership moves into another data structure that means pool were closed automatically. Is that right?
I mean, there is no way to explicitly disconnect that pool after that value passed on server variable, i tried many things and also there is no way to reach that connection later than that server variable. This should make it closed after moving.
Hmm..
First let me mention that there is no such thing as "async destructor" in Rust, that's why you have to explicitly call pool.disconnect()
to disconnect it gracefully. Now if pool instance is moved (say in a way it is moved into a closure in your example) than it won't be disconnected nor deallocated even if it is the only instance of this pool.
If you want to gracefully close the pool you need to keep a clone somewhere so that you can call disconnect (see docs):
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
let ip_address_and_port = match env::var("IP_ADDRESS_AND_PORT") {
Ok(variable) => variable,
Err(_) => panic!("Cannot found 'IP_ADDRESS_AND_PORT' env variable."),
};
let db_conn_string = match env::var("DB_CONN_URL") {
Ok(variable) => variable,
Err(_) => panic!("Cannot found 'DB_CONN_STRING' env variable."),
};
let pool = database::create_db_pool(db_conn_string.as_str()).await;
let pool_clone = pool.clone();
let server = HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.wrap(from_fn(authlogic::refresh_cookies))
.service(navctrl::home_controller)
.service(navctrl::about_us_controller)
.service(navctrl::contact_controller)
.service(routers::admin_panel_router())
.service(routers::posts_router())
});
server.bind((ip_address_and_port.as_str()))?.run().await?;
pool_clone.disconnect().await?;
Ok(())
}
Understand. Because it's an Arc type, that means all the clones are reference to the same pool if we close one of them we'll be close every one of them. Thanks.