【问题标题】:How to abstract over serializable objects being either remote or local in Rust?如何在 Rust 中抽象出远程或本地的可序列化对象?
【发布时间】:2020-11-15 17:38:58
【问题描述】:

我有一个枚举来表示节点是本地的(指当前节点)还是远程的,在这种情况下,通信是通过 RPC 调用发生的:

pub enum Node {
    Local,
    Remote(SocketAddr),
}

我有一个结构DB,它代表一个本地数据库。我需要序列化这个Node 枚举,因为它被用作元数据来确定某些键值对的存储位置(本地或远程)。我将此元数据存储在与我的其余数据相同的数据库中,因此Node::Local 指的是存储它的数据库。

我希望反序列化的节点枚举包含对它被取出的数据库的引用,以便我可以将 Local 变体转换为 Local(DB)。然后我对Local 和Remote 变体具有相同的语义,因为它们都包含足够的信息来执行Node.get(key) 和Node.insert(key, value) 操作。

使用远程变体,我只需打开与SocketAddr 的连接,并发出 RPC 请求,但使用Local 变体,我必须在引用本地数据库的地方进行模式匹配, 并应用特殊逻辑而不是一般地说Node.get(key)。根本问题是Node::Local 不包含足够的信息来执行对本地数据库的请求,而Node::Remote 中的SocketAddr 足以执行RPC 调用。

我可以通过创建一个自定义反序列化方法来解决这个问题,其中我将当前的DB 作为对该反序列化方法的引用,但我想知道是否有其他好的方法可以解决这个问题。

【问题讨论】:

  • trait 怎么样?
  • 这仍然不能解决必须序列化它的问题。即使我没有使用枚举而是使用 trait 对象,这些 trait 对象仍然需要包含必要的信息,以便在反序列化时执行请求。对于 socketAddr 这不是问题,但我无法序列化整个数据库,因此本地 trait 对象在没有外部信息的情况下无法执行 db 操作。
  • 听起来你会明白为什么本地和远程不是抽象的东西。
  • 我只是在这里错过了一些信息。为什么 Node::Local 缺少信息?为什么不让它包含必要的信息?
  • @Netwave OP 不想提供一个最小的例子,所以我猜,但他们在 DB 结构内有 Node。问题是Node 需要的信息是包含DB 本身。这是一个经典的循环引用问题。它可以在 Rust 中解决,但循环引用在任何语言中都是一种痛苦。我鼓励避免它。我可能会让DB::get(key) 打电话给Node::get(key, local_db) 并避免整个混乱。

标签: serialization rust enums rpc abstraction


【解决方案1】:

我最终将这种区别表示为枚举。使用单独的枚举进行序列化和实际工作,因为我无法序列化对本地数据库的引用,如果您不需要序列化,当然可以避开 NodeRepr 枚举:

#[derive(Serialize, Deserialize)]
pub enum NodeRepr {
    Local,
    Remote(NodeRef),
}

pub enum Node<'a> {
    Local(&'a LocalDB),
    Remote(NodeRef),
}

节点枚举然后具有 impl 方法,通过 match 语句将必要的方法调用委托给 localdb 或 NodeRef 方法。

impl Node {
    pub async fn get(&self, key: String) -> Option<String> {
        match self {
            Node::Local(db) => db.get(key),
            Node::Remote(noderef) => noderef.get(key).await,
        }
    }
}

这种处理方式允许我们仍然保留节点是本地还是远程的信息,以便我们可以在必要时在代码中的任何地方使用这些信息。这很有用,因为您通常不希望总是隐藏某事物是本地还是远程的信息。

如果您总是想隐藏节点是远程节点还是本地节点以强制执行代码清洁,您可以使用 trait 对象,您可以让 LocalDB 和 NodeRef 都实现相同的 trait。

特征特别有用,因为它允许添加新的节点类型(本地和远程之外),而无需更改任何旧代码。使用枚举,期望只有两种不同枚举情况的代码将在添加新节点类型时中断。特征对象的限制也可以通过应用经典的 OOP 模式(如访问者模式)来克服。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2019-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多