无法获得存储库的正确所有权形式
Unable to acquire the right form of ownership to repository
我正在尝试通过 gRPC(使用 Tonic)编写一个与客户端(在此代码中称为 Slave)通信的小型 Web 应用程序,但我几乎在一开始就卡住了。我希望从站能够通过在 gRPC 上调用 register()
函数来自行注册。目前的请求仅包含 mac_address(由于缺少我所知道的任何更好的唯一设备标识符)。
代码的精华部分如下所示
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))
}
}
不幸的是,我似乎无法调用 add_server
。它目前给我以下错误:
trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<SlaveRepository>`
我猜想绕过它的一个简单方法是写 register(&mut self,...)
,但我什至不能尝试这样做,因为 SlaveManager
是从自动生成的一个原型文件,那个文件不使用 mut
.
我最初使用 Box<SlaveRepository>
,但似乎也没有用,而且我认为它不合适,因为 SlaveRepository
将在几个不同的地方使用。
Arc<T>
智能指针使您可以 read-only 访问其指针。所以你不能修改Arc
后面的东西,至少不能直接修改。
鉴于您正在使用 Arc
这是一个 thread-safe 引用计数指针,我假设这将跨线程使用。在这种情况下,您应该将 SlaveRepository
包装在一些同步原语中,例如 Mutex<T>
or RWLock<T>
(请注意,在 async
上下文中,您应该使用这些原语的 async
版本,而不是来自 std
的那些):
pub struct SlaveServer {
slave_repo: Arc<RWLock<SlaveRepository>>
}
// skipped for brevity
let mut lock_guard = self.slave_repo
.write()
.await;
lock_quard.add_slave(
Slave {
mac_address: req.mac_address.clone()
}
);
我正在尝试通过 gRPC(使用 Tonic)编写一个与客户端(在此代码中称为 Slave)通信的小型 Web 应用程序,但我几乎在一开始就卡住了。我希望从站能够通过在 gRPC 上调用 register()
函数来自行注册。目前的请求仅包含 mac_address(由于缺少我所知道的任何更好的唯一设备标识符)。
代码的精华部分如下所示
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))
}
}
不幸的是,我似乎无法调用 add_server
。它目前给我以下错误:
trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc<SlaveRepository>`
我猜想绕过它的一个简单方法是写 register(&mut self,...)
,但我什至不能尝试这样做,因为 SlaveManager
是从自动生成的一个原型文件,那个文件不使用 mut
.
我最初使用 Box<SlaveRepository>
,但似乎也没有用,而且我认为它不合适,因为 SlaveRepository
将在几个不同的地方使用。
Arc<T>
智能指针使您可以 read-only 访问其指针。所以你不能修改Arc
后面的东西,至少不能直接修改。
鉴于您正在使用 Arc
这是一个 thread-safe 引用计数指针,我假设这将跨线程使用。在这种情况下,您应该将 SlaveRepository
包装在一些同步原语中,例如 Mutex<T>
or RWLock<T>
(请注意,在 async
上下文中,您应该使用这些原语的 async
版本,而不是来自 std
的那些):
pub struct SlaveServer {
slave_repo: Arc<RWLock<SlaveRepository>>
}
// skipped for brevity
let mut lock_guard = self.slave_repo
.write()
.await;
lock_quard.add_slave(
Slave {
mac_address: req.mac_address.clone()
}
);