What is the idiomatic Rust way to solve my task
AS IS: i have multiple grpc servers, my rust app on start is connecting to them all via different clients and i wanna store that connection in some struct lets name it Holder, which is stored as Vec and then passed to my logic layer of the application
since my rpc method stream(request and response) my Holder is storing tx and rx, what i want is to run background task for each Holder listening on rx and send it via grpc client to server, so i need to pass tx or entire Holder struct to my logic layer and here's my question all begins, i used to Go/C pointers which for this tasks i could just use pefectly, but Rust want allow me this and i having multiple borrow checker errors, on this level i started thinking im not doing this in "Rust idiomatic way" if its possible ofc, so asking for some help and examples maybe, below some abstract code of wha i am trying to do:
let holders: Vec<Holder> = match HolderCollection::create(hosts).await {
Ok(holders ) => holders,
Err(err ) => {
panic!("error creating data holders: {}", err)
}
};
create looks like
let mut res = HolderCollection {
holders: Vec::with_capacity(storages.len())
};
for v in storages {
let mut client = TransferServiceClient::connect(v).await?;
let (tx, rx) = mpsc::unbounded_channel();
let rx_stream = UnboundedReceiverStream::new(rx);
res.holders.push(Holder {
tx,
rc: rx_stream,
client
// some filed which should be updated on every response after sending grpc message
stat: 0.0,
})
}
Ok(res)
}
background task:
pub fn run(&self) {
for mut h in self.holders {
tokio::spawn(async move {
// cause of the stream, i cant just pass channel as argument
match h.client.put_data(h.rc).await {
Ok(res) => {
if let Some(msg) = res.into_inner().message().await {
h.stat = msg.new_stat
}
}
}
Err(err) => {
eprintln!("{}", err)
}
}
});
}
}
after that im trying to use those structs in the other component which somehow(its not important) generates messages, e.g:
// also not important logic of retrieving one of the holders
let holder = self.holders.get_available()
/*
do some logic here
*/
holder.tx.send(some_data)
is my approach acceptable in Rust, cause number of borrow checker errors im receiving is huge and i am thinking im doing something wrong