Shared mutable state with websockets in Rust

576 views Asked by At

I am using actix-web to run a webserver and want to be able to mutate state through websocket messages.

My current way of using websockets is through implementing the handle method from actix::StreamHandler. However this limits my ability of passing data to it. How can I access the data (actix_web::web::Data) in my handle method?

The only way I can think of solving this issue is to somehow overwrite the function signature of handle, however that doesn't seem possible

1

There are 1 answers

0
Tim Lin On

Hers is some important code snippets, we have app_name and nonces in app_data:

// main.rs
let nonces = Arc::new(Mutex::new(nonces::Nonces::new()));

HttpServer::new(move || {
    App::new()
        .app_data(web::Data::new(app_data::AppData {
            app_name: String::from("Actix Web"),
            nonces: Arc::clone(&nonces),
        }))

    ...
// app_data.rs
pub struct AppData {
    pub app_name: String,
    pub nonces: Arc<Mutex<nonces::Nonces>>,
}
// ws.rs
struct Ws {
    app_data: web::Data<app_data::AppData>,
}

impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for Ws {
    fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {

        let app_name = &self.app_data.app_name;
        let mut nonces = self.app_data.nonces.lock().unwrap();

        println!(">>> {app_name}");
        println!(">>> {:?}", nonces.nonces);  // I have a nonces data in nonces

        ...
    }
}

async fn index(
    req: HttpRequest, 
    stream: web::Payload, 
    app_data: web::Data<app_data::AppData>,
) -> Result<HttpResponse, Error> {
    ws::start(Ws { app_data: app_data.clone() }, &req, stream)
}