Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Design Doc]: Refactor Xline protobuf #420

Closed
bsbds opened this issue Aug 22, 2023 · 0 comments
Closed

[Design Doc]: Refactor Xline protobuf #420

bsbds opened this issue Aug 22, 2023 · 0 comments

Comments

@bsbds
Copy link
Collaborator

bsbds commented Aug 22, 2023

Why

In current Xline design, we transparently use the curp crate through the Command trait.

More specifically, curp itself use bincode to serialize/deserialize the generics without knowing the specific type. For instance in handling ProposeRequest:

impl ProposeRequest {
    /// Create a new `Propose` request
    pub(crate) fn new<C: Command>(cmd: &C) -> bincode::Result<Self> {
        Ok(Self {
            command: bincode::serialize(cmd)?,
        })
    }

    /// Get command
    pub(crate) fn cmd<C: Command>(&self) -> bincode::Result<C> {
        bincode::deserialize(&self.command)
    }
}

Bincode can efficiently serialize native Rust types. However, we needed to implement the curp client in languages other than Rust, and the curp server should to be able to accept requests from client SDK written in these languages, it is necessary to employ an alternative approach for cross language serialization.

How

message ProposeRequest {
    // The serialized command
    // The original type is `Command`
    bytes command = 1;
}

Current implementation use bytes in proto types to store the serialized bincode values, as shown in above code snippets. Instead, we could use protobuf for serialization, and store the result into the bytes fields(can be viewed as nested protobufs).

Currently some of the types defined in the xline crate cannot be seen from other languages. We need to move these types from xline to proto files. For example the Command type:

pub struct Command {
    /// Keys of request
    keys: Vec<KeyRange>,
    /// Request data
    request: RequestWithToken,
    /// Propose id
    id: ProposeId,
}

will be converted to proto type definition:

message Command {
    repeated KeyRange keys = 1;
    RequestWithToken request = 2;
    string propose_id = 3;
}

...

When implementing a xline client, the developer just need to know the specific type defined in xline proto files, and manually serialize/deserialize the type into/from bytes.

Issues

In proto 3, the required keyword is removed, so for any non-scalar types field will be replaced as an Option<T> in prost, which is hard to use. I plan to keep the original types currently defined in xline and add a conversion between the original types and the generated proto types.

Implementing the client

When implementing a curp clients, developers needs to use the following types:

  • ProposeRequest
  • ProposeResponse
  • WaitSyncedRequest
  • WaitSyncedResponse

They can be found in curp/proto/command.proto, and relevant errors are in curp/proto/error.proto

For xline client, the types need to be serialized can be found in xlineapi/proto/command.proto and xlineapi/proto/error.proto.

When constructing a request, you need firstly serialize the command types defined in xlineapi protos into bytes, and then put them into the types defined in curp protos accordingly. Use the same approach for decoding a response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant