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
move
in front of the closure - compiler complains the borrowed value doesn't live long enough - Dereferencing
config
and wrapping it in a freshArc()
- similar error as original
What's the right way to do this?