When I want to store the channel in the hashmap, I encounter the problem of life time

When I want to store the channel in the hashmap, I encounter the problem of life time, and I don't know how to modify my code. How has the ownership changed here? It seems to be different from my commonly used golang.
Here is my demo code.

use std::collections::HashMap;
use std::sync::Arc;
use tokio::{select, task};
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::sync::{mpsc, Mutex};

struct Demo {
    inner: Vec<String>,
    senders: Arc<HashMap<String, Sender<String>>>,
    receivers: Arc<HashMap<String, Mutex<Receiver<String>>>>,
}

impl Demo {
    fn init() -> Self {
        let mut inner = vec![];
        let mut senders = HashMap::new();
        let mut receivers = HashMap::new();
        for i in 0..5 {
            let (tx, rx) = mpsc::channel(10);
            senders.insert(i.to_string(), tx);
            receivers.insert(i.to_string(), Mutex::new(rx));
            inner.push(i.to_string());
        }
        Demo {
            inner,
            senders: Arc::new(senders),
            receivers: Arc::new(receivers),
        }
    }

    async fn run_all(self: Arc<Self>) {
        let mut handles = vec![];
        for i in &self.inner {
            if let Some(receiver) = self.receivers.get(i) {
                let d = self.clone();
                handles.push(task::spawn(async move {
                    d.run(receiver).await;
                }))
            }
        }
        for h in handles {
            h.await;
        }
    }

    async fn run(&self, receiver: &Mutex<Receiver<String>>) {
        let mut rec = receiver.lock().await;
        loop {
            select! {
                msg = rec.recv() => {
                    if let Some(msg) = msg {
                        println!("{}", msg);
                        if msg == "stop".to_string() {
                            break
                        }
                    }
                }
            }
        }
    }
}


#[tokio::main]
async fn main() {}

Here is the error.

error[E0597]: `self` does not live long enough
   --> src/node/node.rs:96:37
    |
96  |             if let Some(receiver) = self.receivers.get(&operator_addr) {
    |                                     ^^^^------------------------------
    |                                     |
    |                                     borrowed value does not live long enough
    |                                     argument requires that `self` is borrowed for `'static`
...
107 |     }
    |     - `self` dropped here while still borrowed

get gives you a temporary loan of Reveiver that is not allowed to leave the current function, so it can't be used with a "global" spawn. That async move doesn't do anything for temporary references - moving them doesn't untangle them from their temporary scope.

You need to have each receiver in Arc and clone them before spawn.

Alternatively, don't use spawn, and instead await them in the same scope, e.g. using join_all.

It's working, tks :grinning: