Axum Server - Shared Struct

I have an ABC struct with work function which modifies a field on the struct, the field is Arc<Mutex<HashSet<u64>>>,.
My goal is to expose the work method at the do_work endpoint via Axum

// I need to create ABC object since the constructor(`new`) have some init functionality
let worker = ABC::new();
// Now, I want to call worker.work() method when the do_work is called.
let app = Router::new()
   .route("/do_work", get(worker.work))

This code doesn't work.
How can I solve the issue?

// doesn't work as well
async { worker.work().await }

I need new to be called due to init functionality, I need work to call and it's modifies the shared data

If you want to use the worker with multiple routes, you need some kind of shared ownership like an Arc

use std::{
    collections::HashSet,
    sync::{Arc, Mutex},
};

use axum::{routing::get, Router};

struct Worker {
    hash_set: Mutex<HashSet<u64>>,
}

impl Worker {
    async fn health_check(&self) {
        self.hash_set.lock().unwrap().insert(12);
    }
}

#[tokio::main]
async fn main() {
    let worker = Arc::new(Worker {
        hash_set: Mutex::new(HashSet::new()),
    });

    let app = Router::new()
        .route(
            "/",
            get(
                // Note this is just a block that returns a closure.
                // It groups the clone with the closure nicely
                {
                    // Clone the worker so we can move it into the route closure
                    let worker = worker.clone();
                    || async move {
                        worker.health_check().await;
                    }
                },
            ),
        )
        .route(
            "/print",
            // Don't need to clone here since nothing else uses the worker afterwards.
            // We can just move the original Arc into this closure.
            get(|| async move { format!("{:#?}", worker.hash_set.lock().unwrap()) }),
        );

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

Additionally this is possible via axum request extensions, or the new State extractor in 0.6.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.