无法获得存储库的正确所有权形式

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()
            }
        );

这叫做interior mutability pattern