I have a config Struct that I'm sharing across my actix app like so:
pub fn run(addr: &str, pg_pool: PgPool, config: Settings) -> Result<Server, std::io::Error> {
let pool = web::Data::new(pg_pool);
let arc_config = web::Data::new(Arc::new(config)); // <---
let server = HttpServer::new(move || {
App::new()
.service(exhaust)
.app_data(pool.clone())
.app_data(arc_config.clone()) // <---
})
.bind(addr)?
.run();
I then have a handler that is trying to spawn multiple threads and pass that config struct into each:
#[get("/exhaust")]
pub async fn exhaust(pool: web::Data<PgPool>, config: web::Data<Arc<Settings>>) -> impl Responder {
for _ in 1..16 {
let handle = thread::spawn(move || {
let inner_config = Arc::clone(&config);
get_single_tweet(inner_config.as_ref().deref(), "1401287393228038149");
});
}
HttpResponse::Ok()
}
My thinking was that because config is already wrapped in an Arc() I should be able to just Arc::clone() it inside of each thread and then deref into the underlying variable.
But I'm getting this error:
error[E0382]: use of moved value: `config`
--> src/twitter/routes/pull.rs:63:36
|
58 | pub async fn exhaust(pool: web::Data<PgPool>, config: web::Data<Arc<Settings>>) -> impl Responder {
| ------ move occurs because `config` has type `actix_web::web::Data<Arc<Settings>>`, which does not implement the `Copy` trait
...
63 | let handle = thread::spawn(move || {
| ^^^^^^^ value moved into closure here, in previous iteration of loop
64 | let inner_config = Arc::clone(&config);
| ------ use occurs due to use in closure
I'm struggling to understand why this fails. If the config is inside an Arc, then why does the compiler think I'm trying to move it instead of incrementing the reference count?
I've also tried a number of other approaches, all unsuccessful:
- Removing the
movein front of the closure - compiler complains the borrowed value doesn't live long enough - Dereferencing
configand wrapping it in a freshArc()- similar error as original
What's the right way to do this?