I'm trying to write a small webapp communicating with a client (aka Slave in this code) over gRPC (using Tonic) and I'm getting stuck almost at the very beginning. I want the slave to be able to self-register by invoking the register()
function over gRPC. The request at the moment contains only the mac_address (due to lack of any better unique device identifier I'm aware of).
The juicy part of the code looks as follows
pub struct SlaveServer {
slave_repo: Arc<SlaveRepository>
}
#[tonic::async_trait]
impl SlaveManager for SlaveServer {
async fn register(&self, request : Request<RegistrationRequest>) -> Result<Response<RegistrationResponse>, Status> {
let req: RegistrationRequest = request.into_inner();
(*self.slave_repo).add_slave(
Slave {
mac_address: req.mac_address.clone()
}
);
println!("New slave: {}", req.mac_address);
let response = RegistrationResponse { slave_id: "new_id".to_string() };
return Ok(Response::new(response))
}
}
unfortunately however it looks like I cannot invoke add_server
. It currently gives me the following error:
trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<SlaveRepository>`
It is my guess that an easy way to go around it would be to write register(&mut self,...)
, but that is not something I can even attempt, given that the SlaveManager
is auto-generated from a proto file and that one doesn't use the mut
.
I originally used Box<SlaveRepository>
, but that didn't seem to work either, plus I suppose it wasn't suitable since the SlaveRepository
will be used in several different places.
The
Arc<T>
smart pointer gives you read-only access to its pointee. So you cannot modify something which is behind anArc
, at least not directly.Given that you are using
Arc
which is a thread-safe reference counted pointer, I assume that this would be used across threads. In that case you should wrap yourSlaveRepository
in some synchronization primitive, such asMutex<T>
orRWLock<T>
(note that inasync
context you should use theasync
versions of those primitives, instead of the ones fromstd
):This is called the interior mutability pattern