diff --git a/src/lib.rs b/src/lib.rs index 89b25f45..838eed11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,7 +105,7 @@ mod compat; mod config; mod kv; mod pd; -mod proto; +pub mod proto; mod region; mod region_cache; mod stats; diff --git a/src/proto.rs b/src/proto.rs index f0dee9af..fb959105 100644 --- a/src/proto.rs +++ b/src/proto.rs @@ -1,14 +1,52 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. +//! The protobuf messages and gRPC clients generated from [kvproto], the TiKV, PD and +//! TiCDC protocol definitions this crate is built on. +//! +//! They let applications call RPCs this crate does not wrap, over the same message types: +//! for example TiCDC's `cdcpb::change_data_client::ChangeDataClient` or PD's GC safe +//! point RPCs on `pdpb::pd_client::PdClient`. The clients are [tonic] clients; build +//! their channels with the [`tonic`] re-exported here, which is the version the clients +//! are generated for (and [`prost`] for the message traits). +//! +//! ```no_run +//! use tikv_client::proto::pdpb; +//! use tikv_client::proto::tonic::transport::Channel; +//! +//! # async fn f() -> Result<(), Box> { +//! let channel = Channel::from_static("http://127.0.0.1:2379").connect().await?; +//! let mut pd = pdpb::pd_client::PdClient::new(channel); +//! let members = pd.get_members(pdpb::GetMembersRequest::default()).await?; +//! let cluster_id = members.into_inner().header.unwrap().cluster_id; +//! let request = pdpb::GetGcSafePointRequest { +//! header: Some(pdpb::RequestHeader { +//! cluster_id, +//! ..Default::default() +//! }), +//! }; +//! let safe_point = pd.get_gc_safe_point(request).await?.into_inner().safe_point; +//! # let _ = safe_point; +//! # Ok(()) +//! # } +//! ``` +//! +//! These modules are generated code and follow kvproto: they change when the vendored +//! protos are updated, independently of the rest of the API. +//! +//! [kvproto]: https://github.com/pingcap/kvproto + #![allow(clippy::large_enum_variant)] #![allow(clippy::enum_variant_names)] +pub use prost; pub use protos::*; +pub use tonic; // Rust 1.93's clippy::all flags many protobuf-generated wire types as dead code. // Prior toolchain (1.84.1) did not fail on these generated definitions. #[allow(clippy::doc_lazy_continuation)] #[allow(dead_code)] +#[allow(rustdoc::all)] mod protos { include!("generated/mod.rs"); } diff --git a/tests/proto_tests.rs b/tests/proto_tests.rs new file mode 100644 index 00000000..84f9393c --- /dev/null +++ b/tests/proto_tests.rs @@ -0,0 +1,38 @@ +//! The generated kvproto modules are public: applications can name the messages and +//! build the gRPC clients this crate does not wrap. No cluster is needed. + +use tikv_client::proto::cdcpb; +use tikv_client::proto::kvrpcpb; +use tikv_client::proto::pdpb; +use tikv_client::proto::prost::Message; +use tikv_client::proto::tonic::transport::Channel; +use tikv_client::proto::tonic::transport::Endpoint; + +#[test] +fn generated_messages_are_public_and_encode_with_the_reexported_prost() { + let request = pdpb::UpdateServiceGcSafePointRequest { + header: Some(pdpb::RequestHeader { + cluster_id: 7, + ..Default::default() + }), + service_id: b"gc_worker".to_vec(), + ttl: i64::MAX, + safe_point: 42, + }; + let decoded = + pdpb::UpdateServiceGcSafePointRequest::decode(request.encode_to_vec().as_slice()).unwrap(); + assert_eq!(decoded, request); + + // The re-exported `ProtoLockInfo` is the same type as the generated one. + let lock: tikv_client::ProtoLockInfo = kvrpcpb::LockInfo::default(); + assert!(lock.secondaries.is_empty()); +} + +#[tokio::test] +async fn generated_clients_build_on_the_reexported_tonic() { + // A lazy channel never dials, so this needs no server. + let channel: Channel = Endpoint::from_static("http://127.0.0.1:1").connect_lazy(); + let _pd = pdpb::pd_client::PdClient::new(channel.clone()); + let _cdc = cdcpb::change_data_client::ChangeDataClient::new(channel) + .max_decoding_message_size(64 << 20); +}