From 7e74ea25cade31634b320a0cece22d1d7081004b Mon Sep 17 00:00:00 2001 From: Mikhail Nazarov Date: Mon, 30 Sep 2024 14:54:26 +0300 Subject: [PATCH 1/8] Fixed data representation for Uint8 and Uint16 --- ydb/src/grpc_wrapper/raw_table_service/value/value_ydb.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ydb/src/grpc_wrapper/raw_table_service/value/value_ydb.rs b/ydb/src/grpc_wrapper/raw_table_service/value/value_ydb.rs index 7749ad33..5fe90954 100644 --- a/ydb/src/grpc_wrapper/raw_table_service/value/value_ydb.rs +++ b/ydb/src/grpc_wrapper/raw_table_service/value/value_ydb.rs @@ -35,7 +35,7 @@ impl TryFrom for RawTypedValue { }, Value::Uint8(v) => RawTypedValue { r#type: RawType::Uint8, - value: RawValue::Int32(v as i32), + value: RawValue::UInt32(v as u32), }, Value::Int16(v) => RawTypedValue { r#type: RawType::Int16, @@ -43,7 +43,7 @@ impl TryFrom for RawTypedValue { }, Value::Uint16(v) => RawTypedValue { r#type: RawType::Uint16, - value: RawValue::Int32(v as i32), + value: RawValue::UInt32(v as u32), }, Value::Int32(v) => RawTypedValue { r#type: RawType::Int32, @@ -201,11 +201,11 @@ impl TryFrom for Value { (t @ RawType::Bool, v) => return types_mismatch(t, v), (RawType::Int8, RawValue::Int32(v)) => Value::Int8(v.try_into()?), (t @ RawType::Int8, v) => return types_mismatch(t, v), - (RawType::Uint8, RawValue::Int32(v)) => Value::Uint8(v.try_into()?), + (RawType::Uint8, RawValue::UInt32(v)) => Value::Uint8(v.try_into()?), (t @ RawType::Uint8, v) => return types_mismatch(t, v), (RawType::Int16, RawValue::Int32(v)) => Value::Int16(v.try_into()?), (t @ RawType::Int16, v) => return types_mismatch(t, v), - (RawType::Uint16, RawValue::Int32(v)) => Value::Uint16(v.try_into()?), + (RawType::Uint16, RawValue::UInt32(v)) => Value::Uint16(v.try_into()?), (t @ RawType::Uint16, v) => return types_mismatch(t, v), (RawType::Int32, RawValue::Int32(v)) => Value::Int32(v), (t @ RawType::Int32, v) => return types_mismatch(t, v), From 6578db74dc8e54922de91d3caff583291043a852 Mon Sep 17 00:00:00 2001 From: Mikhail Nazarov Date: Mon, 30 Sep 2024 17:25:04 +0300 Subject: [PATCH 2/8] integration tests --- ydb/src/client_table_test_integration.rs | 60 ++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/ydb/src/client_table_test_integration.rs b/ydb/src/client_table_test_integration.rs index 7ba4bdce..1395768c 100644 --- a/ydb/src/client_table_test_integration.rs +++ b/ydb/src/client_table_test_integration.rs @@ -653,6 +653,66 @@ SELECT CAST(NULL AS Optional) Ok(()) } +#[tokio::test] +#[traced_test] +#[ignore] // need YDB access +async fn select_with_u8_param() -> YdbResult<()> { + let client = create_client().await?; + let mut transaction = client + .table_client() + .create_autocommit_transaction(Mode::OnlineReadonly); + let res = transaction.query( + Query::from(r#" + DECLARE $val AS Uint8; + SELECT $val as s + "#).with_params(ydb_params!( + "$val" => 99u8 + ))) + .await?; + trace!("result: {:?}", &res); + assert_eq!( + Value::Uint8(99u8), + res.into_only_result() + .unwrap() + .rows() + .next() + .unwrap() + .remove_field_by_name("s") + .unwrap() + ); + Ok(()) +} + +#[tokio::test] +#[traced_test] +#[ignore] // need YDB access +async fn select_with_u16_param() -> YdbResult<()> { + let client = create_client().await?; + let mut transaction = client + .table_client() + .create_autocommit_transaction(Mode::OnlineReadonly); + let res = transaction.query( + Query::from(r#" + DECLARE $val AS Uint16; + SELECT $val as s + "#).with_params(ydb_params!( + "$val" => 34111u16 + ))) + .await?; + trace!("result: {:?}", &res); + assert_eq!( + Value::Uint16(34111u16), + res.into_only_result() + .unwrap() + .rows() + .next() + .unwrap() + .remove_field_by_name("s") + .unwrap() + ); + Ok(()) +} + #[tokio::test] #[traced_test] #[ignore] // need YDB access From d2c05e4a0f9693daec5064f64fbc4247fee45dd9 Mon Sep 17 00:00:00 2001 From: Timofey Koolin Date: Wed, 9 Oct 2024 11:41:29 +0300 Subject: [PATCH 3/8] update rust version --- .github/workflows/publish-crate.yml | 2 +- .github/workflows/rust-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-crate.yml b/.github/workflows/publish-crate.yml index 0309a38e..9c13c1e1 100644 --- a/.github/workflows/publish-crate.yml +++ b/.github/workflows/publish-crate.yml @@ -1,7 +1,7 @@ name: Publish rust crate to crates.io env: CARGO_TERM_COLOR: always - RUST_VERSION: 1.79.0 + RUST_VERSION: 1.81.0 CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse on: diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index 9db5c54e..e2641aa5 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -12,7 +12,7 @@ env: CARGO_TERM_COLOR: always CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse RUST_VERSION_OLD: "1.60.0" - RUST_VERSION_NEW: "1.79.0" + RUST_VERSION_NEW: "1.81.0" jobs: tests: From 9df3756e700ba4b9c3e6e4a35b2d62aa8627dc8d Mon Sep 17 00:00:00 2001 From: robot Date: Wed, 9 Oct 2024 08:41:36 +0000 Subject: [PATCH 4/8] bump version for ydb, patch --- ydb-example-urlshortener/Cargo.toml | 2 +- ydb/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ydb-example-urlshortener/Cargo.toml b/ydb-example-urlshortener/Cargo.toml index 5916429a..aa726aad 100644 --- a/ydb-example-urlshortener/Cargo.toml +++ b/ydb-example-urlshortener/Cargo.toml @@ -16,4 +16,4 @@ tokio = { version = "1.18", features = ["macros", "rt-multi-thread", "net"] } tracing = "0.1" tracing-subscriber = "0.3" warp = "0.3.2" -ydb = { version = "0.9.2", path="../ydb"} +ydb = { version = "0.9.3", path="../ydb"} diff --git a/ydb/Cargo.toml b/ydb/Cargo.toml index 70d52d0e..2fae9de5 100644 --- a/ydb/Cargo.toml +++ b/ydb/Cargo.toml @@ -1,7 +1,7 @@ [package] publish = true name = "ydb" -version = "0.9.2" +version = "0.9.3" authors = ["rekby "] edition = "2021" license = "Apache-2.0" From 1baa63e5307c0342b0974d75cad2c32e509b8234 Mon Sep 17 00:00:00 2001 From: Timofey Koolin Date: Wed, 9 Oct 2024 11:51:07 +0300 Subject: [PATCH 5/8] fix run linter --- .github/workflows/rust-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index e2641aa5..fe08948d 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -65,6 +65,6 @@ jobs: run: cargo test --verbose --workspace -- --include-ignored - name: Linter - if: matrix.rust_version == 'NEW' + if: matrix.rust_version == 'RUST_VERSION_NEW' run: | cargo clippy --workspace --all-targets -- -D warnings From 77196f217cc11189a82f234d02ce9ac5ee87822d Mon Sep 17 00:00:00 2001 From: Timofey Koolin Date: Wed, 9 Oct 2024 12:03:16 +0300 Subject: [PATCH 6/8] no check dependencies and code-generation by linter --- .github/workflows/rust-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-tests.yml b/.github/workflows/rust-tests.yml index fe08948d..a3b75e13 100644 --- a/.github/workflows/rust-tests.yml +++ b/.github/workflows/rust-tests.yml @@ -67,4 +67,4 @@ jobs: - name: Linter if: matrix.rust_version == 'RUST_VERSION_NEW' run: | - cargo clippy --workspace --all-targets -- -D warnings + cargo clippy --workspace --all-targets --no-deps --exclude=ydb-grpc -- -D warnings From 464aa29491c1bb6e5e1b8f382701a0d29357fd75 Mon Sep 17 00:00:00 2001 From: Timofey Koolin Date: Wed, 9 Oct 2024 12:28:39 +0300 Subject: [PATCH 7/8] updated protobufs --- Cargo.lock | 2 +- ydb-grpc/src/descriptors.bin | Bin 262737 -> 306408 bytes ydb-grpc/src/generated/google.protobuf.rs | 151 +++-- ydb-grpc/src/generated/ydb.discovery.rs | 29 + ydb-grpc/src/generated/ydb.rs | 38 +- ydb-grpc/src/generated/ydb.scheme.rs | 24 + ydb-grpc/src/generated/ydb.table.rs | 237 ++++++- ydb-grpc/src/generated/ydb.table.v1.rs | 20 + ydb-grpc/src/generated/ydb.topic.rs | 601 +++++++++++++++++- ydb-grpc/src/generated/ydb.topic.v1.rs | 68 ++ ydb-grpc/ydb-api-protos | 2 +- ydb/src/client_scheme/list_types.rs | 5 + .../topicwriter/message_write_status.rs | 7 + ydb/src/client_topic/topicwriter/writer.rs | 2 + .../raw_scheme_client/list_directory_types.rs | 5 + .../raw_table_service/value/type.rs | 3 + .../raw_topic_service/common/consumer.rs | 1 + 17 files changed, 1142 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60f6665e..992b87bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2550,7 +2550,7 @@ dependencies = [ [[package]] name = "ydb" -version = "0.9.2" +version = "0.9.3" dependencies = [ "async-trait", "async_once", diff --git a/ydb-grpc/src/descriptors.bin b/ydb-grpc/src/descriptors.bin index daad359eb5c0e32b931733f8e0479030d0599bc2..1334e116f6492e37a609363f94d6102ad790d880 100644 GIT binary patch delta 109623 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%0DipZR6&1Adf)YDP0 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 delta 71672 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 UskORCN>aQsqN#lj4ORVr0oPJpBLDyZ diff --git a/ydb-grpc/src/generated/google.protobuf.rs b/ydb-grpc/src/generated/google.protobuf.rs index f1bd03f6..82e92b65 100644 --- a/ydb-grpc/src/generated/google.protobuf.rs +++ b/ydb-grpc/src/generated/google.protobuf.rs @@ -211,9 +211,9 @@ pub struct FileDescriptorProto { /// If `edition` is present, this value must be "editions". #[prost(string, optional, tag = "12")] pub syntax: ::core::option::Option<::prost::alloc::string::String>, - /// The edition of the proto file, which is an opaque string. - #[prost(string, optional, tag = "13")] - pub edition: ::core::option::Option<::prost::alloc::string::String>, + /// The edition of the proto file. + #[prost(enumeration = "Edition", optional, tag = "14")] + pub edition: ::core::option::Option, } /// Describes a message type. #[derive(Clone, PartialEq, ::prost::Message)] @@ -281,7 +281,7 @@ pub struct ExtensionRangeOptions { #[prost(message, optional, tag = "50")] pub features: ::core::option::Option, /// The verification state of the range. - /// TODO(b/278783756): flip the default to DECLARATION once all empty ranges + /// TODO: flip the default to DECLARATION once all empty ranges /// are marked as UNVERIFIED. #[prost( enumeration = "extension_range_options::VerificationState", @@ -441,9 +441,10 @@ pub mod field_descriptor_proto { Bool = 8, String = 9, /// Tag-delimited aggregate. - /// Group type is deprecated and not supported in proto3. However, Proto3 + /// Group type is deprecated and not supported after google.protobuf. However, Proto3 /// implementations should still be able to parse the group wire format and - /// treat group fields as unknown fields. + /// treat group fields as unknown fields. In Editions, the group wire format + /// can be enabled via the `message_encoding` feature. Group = 10, /// Length-delimited aggregate. Message = 11, @@ -500,8 +501,11 @@ pub mod field_descriptor_proto { pub enum Label { /// 0 is reserved for errors Optional = 1, - Required = 2, Repeated = 3, + /// The required label is only allowed in google.protobuf. In proto3 and Editions + /// it's explicitly prohibited. In Editions, the `field_presence` feature + /// can be used to get this behavior. + Required = 2, } impl Label { /// String value of the enum field names used in the ProtoBuf definition. @@ -510,8 +514,8 @@ pub mod field_descriptor_proto { pub fn as_str_name(&self) -> &'static str { match self { Label::Optional => "LABEL_OPTIONAL", - Label::Required => "LABEL_REQUIRED", Label::Repeated => "LABEL_REPEATED", + Label::Required => "LABEL_REQUIRED", } } } @@ -811,7 +815,7 @@ pub struct MessageOptions { /// well. /// This should only be used as a temporary measure against broken builds due /// to the change in behavior for JSON field name conflicts. - /// TODO(b/261750190) This is legacy behavior we plan to remove once downstream + /// TODO This is legacy behavior we plan to remove once downstream /// teams have had time to migrate. #[deprecated] #[prost(bool, optional, tag = "11")] @@ -842,7 +846,9 @@ pub struct FieldOptions { /// a more efficient representation on the wire. Rather than repeatedly /// writing the tag and type for each element, the entire array is encoded as /// a single length-delimited blob. In proto3, only explicit setting it to - /// false will avoid using packed encoding. + /// false will avoid using packed encoding. This option is prohibited in + /// Editions, but the `repeated_field_encoding` feature can be used to control + /// the behavior. #[prost(bool, optional, tag = "2")] pub packed: ::core::option::Option, /// The jstype option determines the JavaScript type used for values of the @@ -930,8 +936,8 @@ pub struct FieldOptions { pub mod field_options { #[derive(Clone, PartialEq, ::prost::Message)] pub struct EditionDefault { - #[prost(string, optional, tag = "1")] - pub edition: ::core::option::Option<::prost::alloc::string::String>, + #[prost(enumeration = "super::Edition", optional, tag = "3")] + pub edition: ::core::option::Option, /// Textproto value. #[prost(string, optional, tag = "2")] pub value: ::core::option::Option<::prost::alloc::string::String>, @@ -1111,7 +1117,7 @@ pub struct EnumOptions { /// and strips underscored from the fields before comparison in proto3 only. /// The new behavior takes `json_name` into account and applies to proto2 as /// well. - /// TODO(b/261750190) Remove this legacy behavior once downstream teams have + /// TODO Remove this legacy behavior once downstream teams have /// had time to migrate. #[deprecated] #[prost(bool, optional, tag = "6")] @@ -1257,7 +1263,7 @@ pub mod uninterpreted_option { pub is_extension: bool, } } -/// TODO(b/274655146) Enums in C++ gencode (and potentially other languages) are +/// TODO Enums in C++ gencode (and potentially other languages) are /// not well scoped. This means that each of the feature enums below can clash /// with each other. The short names we've chosen maximize call-site /// readability, but leave us very open to this scenario. A future feature will @@ -1271,14 +1277,12 @@ pub struct FeatureSet { pub enum_type: ::core::option::Option, #[prost(enumeration = "feature_set::RepeatedFieldEncoding", optional, tag = "3")] pub repeated_field_encoding: ::core::option::Option, - #[prost(enumeration = "feature_set::StringFieldValidation", optional, tag = "4")] - pub string_field_validation: ::core::option::Option, + #[prost(enumeration = "feature_set::Utf8Validation", optional, tag = "4")] + pub utf8_validation: ::core::option::Option, #[prost(enumeration = "feature_set::MessageEncoding", optional, tag = "5")] pub message_encoding: ::core::option::Option, #[prost(enumeration = "feature_set::JsonFormat", optional, tag = "6")] pub json_format: ::core::option::Option, - #[prost(message, optional, boxed, tag = "999")] - pub raw_features: ::core::option::Option<::prost::alloc::boxed::Box>, } /// Nested message and enum types in `FeatureSet`. pub mod feature_set { @@ -1383,22 +1387,20 @@ pub mod feature_set { ::prost::Enumeration )] #[repr(i32)] - pub enum StringFieldValidation { + pub enum Utf8Validation { Unknown = 0, - Mandatory = 1, - Hint = 2, - None = 3, + None = 1, + Verify = 2, } - impl StringFieldValidation { + impl Utf8Validation { /// String value of the enum field names used in the ProtoBuf definition. /// The values are not transformed in any way and thus are considered stable /// (if the ProtoBuf definition does not change) and safe for programmatic use. pub fn as_str_name(&self) -> &'static str { match self { - StringFieldValidation::Unknown => "STRING_FIELD_VALIDATION_UNKNOWN", - StringFieldValidation::Mandatory => "MANDATORY", - StringFieldValidation::Hint => "HINT", - StringFieldValidation::None => "NONE", + Utf8Validation::Unknown => "UTF8_VALIDATION_UNKNOWN", + Utf8Validation::None => "NONE", + Utf8Validation::Verify => "VERIFY", } } } @@ -1461,6 +1463,39 @@ pub mod feature_set { } } } +/// A compiled specification for the defaults of a set of features. These +/// messages are generated from FeatureSet extensions and can be used to seed +/// feature resolution. The resolution with this object becomes a simple search +/// for the closest matching edition, followed by proto merges. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FeatureSetDefaults { + #[prost(message, repeated, tag = "1")] + pub defaults: ::prost::alloc::vec::Vec< + feature_set_defaults::FeatureSetEditionDefault, + >, + /// The minimum supported edition (inclusive) when this was constructed. + /// Editions before this will not have defaults. + #[prost(enumeration = "Edition", optional, tag = "4")] + pub minimum_edition: ::core::option::Option, + /// The maximum known edition (inclusive) when this was constructed. Editions + /// after this will not have reliable defaults. + #[prost(enumeration = "Edition", optional, tag = "5")] + pub maximum_edition: ::core::option::Option, +} +/// Nested message and enum types in `FeatureSetDefaults`. +pub mod feature_set_defaults { + /// A map from every known edition with a unique set of defaults to its + /// defaults. Not all editions may be contained here. For a given edition, + /// the defaults at the closest matching edition ordered at or before it should + /// be used. This field must be in strict ascending order by edition. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct FeatureSetEditionDefault { + #[prost(enumeration = "super::Edition", optional, tag = "3")] + pub edition: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub features: ::core::option::Option, + } +} /// Encapsulates information about the original source file from which a /// FileDescriptorProto was generated. #[derive(Clone, PartialEq, ::prost::Message)] @@ -1660,6 +1695,48 @@ pub mod generated_code_info { } } } +/// The full set of known editions. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum Edition { + /// A placeholder for an unknown edition value. + Unknown = 0, + /// Legacy syntax "editions". These pre-date editions, but behave much like + /// distinct editions. These can't be used to specify the edition of proto + /// files, but feature definitions must supply proto2/proto3 defaults for + /// backwards compatibility. + Proto2 = 998, + Proto3 = 999, + /// Editions that have been released. The specific values are arbitrary and + /// should not be depended on, but they will always be time-ordered for easy + /// comparison. + Edition2023 = 1000, + /// Placeholder editions for testing feature resolution. These should not be + /// used or relyed on outside of tests. + Edition1TestOnly = 1, + Edition2TestOnly = 2, + Edition99997TestOnly = 99997, + Edition99998TestOnly = 99998, + Edition99999TestOnly = 99999, +} +impl Edition { + /// String value of the enum field names used in the ProtoBuf definition. + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Edition::Unknown => "EDITION_UNKNOWN", + Edition::Proto2 => "EDITION_PROTO2", + Edition::Proto3 => "EDITION_PROTO3", + Edition::Edition2023 => "EDITION_2023", + Edition::Edition1TestOnly => "EDITION_1_TEST_ONLY", + Edition::Edition2TestOnly => "EDITION_2_TEST_ONLY", + Edition::Edition99997TestOnly => "EDITION_99997_TEST_ONLY", + Edition::Edition99998TestOnly => "EDITION_99998_TEST_ONLY", + Edition::Edition99999TestOnly => "EDITION_99999_TEST_ONLY", + } + } +} /// `Struct` represents a structured data value, consisting of fields /// which map to dynamically typed values. In some languages, `Struct` /// might be supported by a native representation. For example, in @@ -1736,15 +1813,6 @@ impl NullValue { } } } -/// A generic empty message that you can re-use to avoid defining duplicated -/// empty messages in your APIs. A typical example is to use it as the request -/// or the response type of an API method. For instance: -/// service Foo { -/// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); -/// } -#[derive(serde::Serialize, serde::Deserialize)] -#[derive(Clone, PartialEq, ::prost::Message)] -pub struct Empty {} /// A Timestamp represents a point in time independent of any time zone or local /// calendar, encoded as a count of seconds and fractions of seconds at /// nanosecond resolution. The count is relative to an epoch at UTC midnight on @@ -1825,4 +1893,13 @@ pub struct Timestamp { /// inclusive. #[prost(int32, tag = "2")] pub nanos: i32, -} \ No newline at end of file +} +/// A generic empty message that you can re-use to avoid defining duplicated +/// empty messages in your APIs. A typical example is to use it as the request +/// or the response type of an API method. For instance: +/// service Foo { +/// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +/// } +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Empty {} \ No newline at end of file diff --git a/ydb-grpc/src/generated/ydb.discovery.rs b/ydb-grpc/src/generated/ydb.discovery.rs index 5b0d0332..221d34af 100644 --- a/ydb-grpc/src/generated/ydb.discovery.rs +++ b/ydb-grpc/src/generated/ydb.discovery.rs @@ -73,4 +73,33 @@ pub struct WhoAmIResult { pub struct WhoAmIResponse { #[prost(message, optional, tag = "1")] pub operation: ::core::option::Option, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NodeLocation { + /// compatibility section -- will be removed in future versions + #[deprecated] + #[prost(uint32, optional, tag = "1")] + pub data_center_num: ::core::option::Option, + #[deprecated] + #[prost(uint32, optional, tag = "2")] + pub room_num: ::core::option::Option, + #[deprecated] + #[prost(uint32, optional, tag = "3")] + pub rack_num: ::core::option::Option, + #[deprecated] + #[prost(uint32, optional, tag = "4")] + pub body_num: ::core::option::Option, + /// for compatibility with WalleLocation + #[deprecated] + #[prost(uint32, optional, tag = "100500")] + pub body: ::core::option::Option, + #[prost(string, optional, tag = "10")] + pub data_center: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "20")] + pub module: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "30")] + pub rack: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "40")] + pub unit: ::core::option::Option<::prost::alloc::string::String>, } \ No newline at end of file diff --git a/ydb-grpc/src/generated/ydb.rs b/ydb-grpc/src/generated/ydb.rs index 8a4121c1..6252b630 100644 --- a/ydb-grpc/src/generated/ydb.rs +++ b/ydb-grpc/src/generated/ydb.rs @@ -84,6 +84,21 @@ pub struct CostInfo { } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct QuotaExceeded { + #[prost(bool, tag = "1")] + pub disk: bool, +} +/// Specifies a point in database time +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VirtualTimestamp { + #[prost(uint64, tag = "1")] + pub plan_step: u64, + #[prost(uint64, tag = "2")] + pub tx_id: u64, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct StatusIds {} /// Nested message and enum types in `StatusIds`. pub mod status_ids { @@ -122,6 +137,7 @@ pub mod status_ids { Undetermined = 400170, Unsupported = 400180, SessionBusy = 400190, + ExternalError = 400200, } impl StatusCode { /// String value of the enum field names used in the ProtoBuf definition. @@ -149,6 +165,7 @@ pub mod status_ids { StatusCode::Undetermined => "UNDETERMINED", StatusCode::Unsupported => "UNSUPPORTED", StatusCode::SessionBusy => "SESSION_BUSY", + StatusCode::ExternalError => "EXTERNAL_ERROR", } } } @@ -228,10 +245,27 @@ pub struct TaggedType { } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct PgType { + #[prost(string, tag = "10")] + pub type_name: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub type_modifier: ::prost::alloc::string::String, + /// pg object id of the type + /// full registry could be found here: + #[prost(uint32, tag = "1")] + pub oid: u32, + /// advanced type details useful for pg wire format proxying + #[prost(int32, tag = "2")] + pub typlen: i32, + #[prost(int32, tag = "3")] + pub typmod: i32, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct Type { #[prost( oneof = "r#type::Type", - tags = "1, 2, 101, 102, 103, 104, 105, 106, 107, 201, 202, 203, 204" + tags = "1, 2, 101, 102, 103, 104, 105, 106, 107, 201, 202, 203, 204, 205" )] pub r#type: ::core::option::Option, } @@ -345,6 +379,8 @@ pub mod r#type { EmptyListType(i32), #[prost(enumeration = "super::super::google::protobuf::NullValue", tag = "204")] EmptyDictType(i32), + #[prost(message, tag = "205")] + PgType(super::PgType), } } #[derive(serde::Serialize, serde::Deserialize)] diff --git a/ydb-grpc/src/generated/ydb.scheme.rs b/ydb-grpc/src/generated/ydb.scheme.rs index 0a5afa1b..f22eaa6a 100644 --- a/ydb-grpc/src/generated/ydb.scheme.rs +++ b/ydb-grpc/src/generated/ydb.scheme.rs @@ -75,6 +75,9 @@ pub struct Entry { /// Empty (zero) in other cases. #[prost(uint64, tag = "8")] pub size_bytes: u64, + /// Virtual timestamp when the object was created + #[prost(message, optional, tag = "9")] + pub created_at: ::core::option::Option, } /// Nested message and enum types in `Entry`. pub mod entry { @@ -100,9 +103,14 @@ pub mod entry { RtmrVolume = 5, BlockStoreVolume = 6, CoordinationNode = 7, + ColumnStore = 12, + ColumnTable = 13, Sequence = 15, Replication = 16, Topic = 17, + ExternalTable = 18, + ExternalDataSource = 19, + View = 20, } impl Type { /// String value of the enum field names used in the ProtoBuf definition. @@ -118,9 +126,14 @@ pub mod entry { Type::RtmrVolume => "RTMR_VOLUME", Type::BlockStoreVolume => "BLOCK_STORE_VOLUME", Type::CoordinationNode => "COORDINATION_NODE", + Type::ColumnStore => "COLUMN_STORE", + Type::ColumnTable => "COLUMN_TABLE", Type::Sequence => "SEQUENCE", Type::Replication => "REPLICATION", Type::Topic => "TOPIC", + Type::ExternalTable => "EXTERNAL_TABLE", + Type::ExternalDataSource => "EXTERNAL_DATA_SOURCE", + Type::View => "VIEW", } } } @@ -193,6 +206,17 @@ pub struct ModifyPermissionsRequest { /// Clear all permissions on the object for all subjects #[prost(bool, tag = "4")] pub clear_permissions: bool, + #[prost(oneof = "modify_permissions_request::Inheritance", tags = "5")] + pub inheritance: ::core::option::Option, +} +/// Nested message and enum types in `ModifyPermissionsRequest`. +pub mod modify_permissions_request { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Inheritance { + #[prost(bool, tag = "5")] + InterruptInheritance(bool), + } } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/ydb-grpc/src/generated/ydb.table.rs b/ydb-grpc/src/generated/ydb.table.rs index a3a97ee4..ae936ba4 100644 --- a/ydb-grpc/src/generated/ydb.table.rs +++ b/ydb-grpc/src/generated/ydb.table.rs @@ -42,6 +42,9 @@ pub struct GlobalIndex {} #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct GlobalAsyncIndex {} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GlobalUniqueIndex {} /// Represent secondary index #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -56,7 +59,7 @@ pub struct TableIndex { #[prost(string, repeated, tag = "5")] pub data_columns: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, /// Type of index - #[prost(oneof = "table_index::Type", tags = "3, 4")] + #[prost(oneof = "table_index::Type", tags = "3, 4, 6")] pub r#type: ::core::option::Option, } /// Nested message and enum types in `TableIndex`. @@ -69,6 +72,8 @@ pub mod table_index { GlobalIndex(super::GlobalIndex), #[prost(message, tag = "4")] GlobalAsyncIndex(super::GlobalAsyncIndex), + #[prost(message, tag = "6")] + GlobalUniqueIndex(super::GlobalUniqueIndex), } } /// Represent secondary index with index state @@ -90,7 +95,7 @@ pub struct TableIndexDescription { #[prost(uint64, tag = "7")] pub size_bytes: u64, /// Type of index - #[prost(oneof = "table_index_description::Type", tags = "3, 5")] + #[prost(oneof = "table_index_description::Type", tags = "3, 5, 8")] pub r#type: ::core::option::Option, } /// Nested message and enum types in `TableIndexDescription`. @@ -135,6 +140,8 @@ pub mod table_index_description { GlobalIndex(super::GlobalIndex), #[prost(message, tag = "5")] GlobalAsyncIndex(super::GlobalAsyncIndex), + #[prost(message, tag = "8")] + GlobalUniqueIndex(super::GlobalUniqueIndex), } } /// State of index building operation @@ -272,7 +279,12 @@ pub mod changefeed_format { #[repr(i32)] pub enum Format { Unspecified = 0, + /// Change record in JSON format for common (row oriented) tables Json = 1, + /// Change record in JSON format for document (DynamoDB-compatible) tables + DynamodbStreamsJson = 2, + /// Debezium-like change record JSON format for common (row oriented) tables + DebeziumJson = 3, } impl Format { /// String value of the enum field names used in the ProtoBuf definition. @@ -282,6 +294,8 @@ pub mod changefeed_format { match self { Format::Unspecified => "FORMAT_UNSPECIFIED", Format::Json => "FORMAT_JSON", + Format::DynamodbStreamsJson => "FORMAT_DYNAMODB_STREAMS_JSON", + Format::DebeziumJson => "FORMAT_DEBEZIUM_JSON", } } } @@ -298,6 +312,36 @@ pub struct Changefeed { /// Format of the data #[prost(enumeration = "changefeed_format::Format", tag = "3")] pub format: i32, + /// How long data in changefeed's underlying topic should be stored + #[prost(message, optional, tag = "4")] + pub retention_period: ::core::option::Option< + super::super::google::protobuf::Duration, + >, + /// Emit virtual timestamps of changes along with data or not + #[prost(bool, tag = "5")] + pub virtual_timestamps: bool, + /// Initial scan will output the current state of the table first + #[prost(bool, tag = "6")] + pub initial_scan: bool, + /// Attributes. Total size is limited to 10 KB. + #[prost(map = "string, string", tag = "7")] + pub attributes: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, + /// Value that will be emitted in the `awsRegion` field of the record in DYNAMODB_STREAMS_JSON format + #[prost(string, tag = "8")] + pub aws_region: ::prost::alloc::string::String, + /// Periodically emit resolved timestamps. If unspecified, resolved timestamps are not emitted. + #[prost(message, optional, tag = "9")] + pub resolved_timestamps_interval: ::core::option::Option< + super::super::google::protobuf::Duration, + >, + /// Partitioning settings of underlying topic. + #[prost(message, optional, tag = "10")] + pub topic_partitioning_settings: ::core::option::Option< + super::topic::PartitioningSettings, + >, } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -314,6 +358,23 @@ pub struct ChangefeedDescription { /// State of the feed #[prost(enumeration = "changefeed_description::State", tag = "4")] pub state: i32, + /// State of emitting of virtual timestamps along with data + #[prost(bool, tag = "5")] + pub virtual_timestamps: bool, + /// Attributes + #[prost(map = "string, string", tag = "6")] + pub attributes: ::std::collections::HashMap< + ::prost::alloc::string::String, + ::prost::alloc::string::String, + >, + /// Value that will be emitted in the `awsRegion` field of the record in DYNAMODB_STREAMS_JSON format + #[prost(string, tag = "7")] + pub aws_region: ::prost::alloc::string::String, + /// Interval of emitting of resolved timestamps. If unspecified, resolved timestamps are not emitted. + #[prost(message, optional, tag = "8")] + pub resolved_timestamps_interval: ::core::option::Option< + super::super::google::protobuf::Duration, + >, } /// Nested message and enum types in `ChangefeedDescription`. pub mod changefeed_description { @@ -332,8 +393,14 @@ pub mod changefeed_description { #[repr(i32)] pub enum State { Unspecified = 0, + /// Normal state, from this state changefeed can be disabled Enabled = 1, + /// No new change records are generated, but the old ones remain available + /// From this state changefeed cannot be switched to any other state Disabled = 2, + /// An initial scan is being performed. + /// After its completion changefeed will switch to the normal state + InitialScan = 3, } impl State { /// String value of the enum field names used in the ProtoBuf definition. @@ -344,6 +411,7 @@ pub mod changefeed_description { State::Unspecified => "STATE_UNSPECIFIED", State::Enabled => "STATE_ENABLED", State::Disabled => "STATE_DISABLED", + State::InitialScan => "STATE_INITIAL_SCAN", } } } @@ -586,6 +654,45 @@ pub struct TableProfile { } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct SequenceDescription { + /// mandatorys + #[prost(string, optional, tag = "1")] + pub name: ::core::option::Option<::prost::alloc::string::String>, + /// minimum value, defaults to 1 or Min + #[prost(sint64, optional, tag = "2")] + pub min_value: ::core::option::Option, + /// maximum value, defaults to Max or -1 + #[prost(sint64, optional, tag = "3")] + pub max_value: ::core::option::Option, + /// start value, defaults to min_value + #[prost(sint64, optional, tag = "4")] + pub start_value: ::core::option::Option, + /// number of items to cache, defaults to 1 + #[prost(uint64, optional, tag = "5")] + pub cache: ::core::option::Option, + /// increment at each call, defaults to 1 + #[prost(sint64, optional, tag = "6")] + pub increment: ::core::option::Option, + /// true when cycle on overflow is allowed + #[prost(bool, optional, tag = "7")] + pub cycle: ::core::option::Option, + /// set_val(next_value, next_used) is executed atomically when creating + #[prost(message, optional, tag = "8")] + pub set_val: ::core::option::Option, +} +/// Nested message and enum types in `SequenceDescription`. +pub mod sequence_description { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct SetVal { + #[prost(sint64, optional, tag = "1")] + pub next_value: ::core::option::Option, + #[prost(bool, optional, tag = "2")] + pub next_used: ::core::option::Option, + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ColumnMeta { /// Name of column #[prost(string, tag = "1")] @@ -596,6 +703,24 @@ pub struct ColumnMeta { /// Column family name of the column #[prost(string, tag = "3")] pub family: ::prost::alloc::string::String, + /// Column nullability + #[prost(bool, optional, tag = "4")] + pub not_null: ::core::option::Option, + /// Column default value option + #[prost(oneof = "column_meta::DefaultValue", tags = "5, 6")] + pub default_value: ::core::option::Option, +} +/// Nested message and enum types in `ColumnMeta`. +pub mod column_meta { + /// Column default value option + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum DefaultValue { + #[prost(message, tag = "5")] + FromLiteral(super::super::TypedValue), + #[prost(message, tag = "6")] + FromSequence(super::SequenceDescription), + } } /// The row will be considered as expired at the moment of time, when the value /// stored in is less than or equal to the current time (in epoch @@ -764,6 +889,9 @@ pub mod column_family { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct PartitioningSettings { + /// List of columns to partition by + #[prost(string, repeated, tag = "1")] + pub partition_by: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, /// Enable auto partitioning on reaching upper or lower partition size bound #[prost(enumeration = "super::feature_flag::Status", tag = "2")] pub partitioning_by_size: i32, @@ -866,6 +994,15 @@ pub struct CreateTableRequest { /// Read replicas settings for table #[prost(message, optional, tag = "17")] pub read_replicas_settings: ::core::option::Option, + /// Tiering rules name. It specifies how data migrates from one tier (logical storage) to another. + #[prost(string, tag = "18")] + pub tiering: ::prost::alloc::string::String, + /// Is temporary table + #[prost(bool, tag = "19")] + pub temporary: bool, + /// Is table column or row oriented + #[prost(enumeration = "StoreType", tag = "20")] + pub store_type: i32, /// Either one of the following partitions options can be specified #[prost(oneof = "create_table_request::Partitions", tags = "13, 14")] pub partitions: ::core::option::Option, @@ -990,6 +1127,9 @@ pub struct AlterTableRequest { /// Setup or remove time to live settings #[prost(oneof = "alter_table_request::TtlAction", tags = "7, 8")] pub ttl_action: ::core::option::Option, + /// Setup or remove tiering + #[prost(oneof = "alter_table_request::TieringAction", tags = "22, 23")] + pub tiering_action: ::core::option::Option, } /// Nested message and enum types in `AlterTableRequest`. pub mod alter_table_request { @@ -1002,6 +1142,15 @@ pub mod alter_table_request { #[prost(message, tag = "8")] DropTtlSettings(super::super::super::google::protobuf::Empty), } + /// Setup or remove tiering + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum TieringAction { + #[prost(string, tag = "22")] + SetTiering(::prost::alloc::string::String), + #[prost(message, tag = "23")] + DropTiering(super::super::super::google::protobuf::Empty), + } } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -1172,6 +1321,15 @@ pub struct DescribeTableResult { /// List of changefeeds #[prost(message, repeated, tag = "15")] pub changefeeds: ::prost::alloc::vec::Vec, + /// Tiering rules name + #[prost(string, tag = "16")] + pub tiering: ::prost::alloc::string::String, + /// Is temporary table + #[prost(bool, tag = "17")] + pub temporary: bool, + /// Is table column or row oriented + #[prost(enumeration = "StoreType", tag = "18")] + pub store_type: i32, } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -1398,6 +1556,8 @@ pub struct ExplainDataQueryRequest { pub yql_text: ::prost::alloc::string::String, #[prost(message, optional, tag = "3")] pub operation_params: ::core::option::Option, + #[prost(bool, tag = "4")] + pub collect_full_diagnostics: bool, } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -1413,6 +1573,8 @@ pub struct ExplainQueryResult { pub query_ast: ::prost::alloc::string::String, #[prost(string, tag = "2")] pub query_plan: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub query_full_diagnostics: ::prost::alloc::string::String, } /// Prepare given program to execute #[derive(serde::Serialize, serde::Deserialize)] @@ -1781,6 +1943,16 @@ pub struct ReadTableRequest { /// Use a server-side snapshot #[prost(enumeration = "super::feature_flag::Status", tag = "7")] pub use_snapshot: i32, + /// Server-side best-effort policy. Can be used as a hint to limit the size + /// of batches sent from a server. If both are specified, the server chooses + /// the smaller one. The limits are not strict, so batch size can be slightly + /// greater than any of the limits + #[prost(uint64, tag = "8")] + pub batch_limit_bytes: u64, + #[prost(uint64, tag = "9")] + pub batch_limit_rows: u64, + #[prost(enumeration = "super::feature_flag::Status", tag = "10")] + pub return_not_null_data_as_optional: i32, } /// ReadTable doesn't use Operation, returns result directly #[derive(serde::Serialize, serde::Deserialize)] @@ -1792,6 +1964,9 @@ pub struct ReadTableResponse { /// Issues #[prost(message, repeated, tag = "2")] pub issues: ::prost::alloc::vec::Vec, + /// Optional snapshot that corresponds to the returned data + #[prost(message, optional, tag = "4")] + pub snapshot: ::core::option::Option, /// Read table result #[prost(message, optional, tag = "3")] pub result: ::core::option::Option, @@ -1806,6 +1981,36 @@ pub struct ReadTableResult { } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReadRowsRequest { + /// Session identifier + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, + /// Path to table to read + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, + /// Keys to read. Must be a list of structs where each stuct is a key + /// for one requested row and should contain all key columns + #[prost(message, optional, tag = "3")] + pub keys: ::core::option::Option, + /// Output columns. If empty all columns will be requested + #[prost(string, repeated, tag = "4")] + pub columns: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ReadRowsResponse { + /// Status of request (same as other statuses) + #[prost(enumeration = "super::status_ids::StatusCode", tag = "1")] + pub status: i32, + /// Issues + #[prost(message, repeated, tag = "2")] + pub issues: ::prost::alloc::vec::Vec, + /// Result set (same as result of sql request) + #[prost(message, optional, tag = "3")] + pub result_set: ::core::option::Option, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct BulkUpsertRequest { #[prost(string, tag = "1")] pub table: ::prost::alloc::string::String, @@ -1858,6 +2063,10 @@ pub struct ExecuteScanQueryRequest { pub mode: i32, #[prost(enumeration = "query_stats_collection::Mode", tag = "8")] pub collect_stats: i32, + /// works only in mode: MODE_EXPLAIN, + /// collects additional diagnostics about query compilation, including query plan and scheme + #[prost(bool, tag = "9")] + pub collect_full_diagnostics: bool, } /// Nested message and enum types in `ExecuteScanQueryRequest`. pub mod execute_scan_query_request { @@ -1910,4 +2119,28 @@ pub struct ExecuteScanQueryPartialResult { pub result_set: ::core::option::Option, #[prost(message, optional, tag = "6")] pub query_stats: ::core::option::Option, + /// works only in mode: MODE_EXPLAIN, + /// collects additional diagnostics about query compilation, including query plan and scheme + #[prost(string, tag = "7")] + pub query_full_diagnostics: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum StoreType { + Unspecified = 0, + Row = 1, + Column = 2, +} +impl StoreType { + /// String value of the enum field names used in the ProtoBuf definition. + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + StoreType::Unspecified => "STORE_TYPE_UNSPECIFIED", + StoreType::Row => "STORE_TYPE_ROW", + StoreType::Column => "STORE_TYPE_COLUMN", + } + } } \ No newline at end of file diff --git a/ydb-grpc/src/generated/ydb.table.v1.rs b/ydb-grpc/src/generated/ydb.table.v1.rs index 81222f02..2c9f0cda 100644 --- a/ydb-grpc/src/generated/ydb.table.v1.rs +++ b/ydb-grpc/src/generated/ydb.table.v1.rs @@ -494,6 +494,26 @@ pub mod table_service_client { ); self.inner.server_streaming(request.into_request(), path, codec).await } + /// Reads specified keys non-transactionally from a single table + pub async fn read_rows( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/Ydb.Table.V1.TableService/ReadRows", + ); + self.inner.unary(request.into_request(), path, codec).await + } /// Upserts a batch of rows non-transactionally. /// Returns success only when all rows were successfully upserted. In case of an error some rows might /// be upserted and some might not. diff --git a/ydb-grpc/src/generated/ydb.topic.rs b/ydb-grpc/src/generated/ydb.topic.rs index c1ce28fd..630e58a3 100644 --- a/ydb-grpc/src/generated/ydb.topic.rs +++ b/ydb-grpc/src/generated/ydb.topic.rs @@ -28,6 +28,24 @@ pub struct UpdateTokenRequest { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpdateTokenResponse {} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PartitionWithGeneration { + /// Partition identifier. + #[prost(int64, tag = "1")] + pub partition_id: i64, + /// Partition generation. + #[prost(int64, tag = "2")] + pub generation: i64, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MetadataItem { + #[prost(string, tag = "1")] + pub key: ::prost::alloc::string::String, + #[prost(bytes = "vec", tag = "2")] + pub value: ::prost::alloc::vec::Vec, +} /// Messages for bidirectional streaming rpc StreamWrite #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -110,7 +128,7 @@ pub mod stream_write_message { pub get_last_seq_no: bool, /// Option for setting order on messages. /// If neither is set, no guarantees on ordering or partitions to write to. - #[prost(oneof = "init_request::Partitioning", tags = "4, 5")] + #[prost(oneof = "init_request::Partitioning", tags = "4, 5, 7")] pub partitioning: ::core::option::Option, } /// Nested message and enum types in `InitRequest`. @@ -126,9 +144,12 @@ pub mod stream_write_message { /// Explicit partition id to write to. #[prost(int64, tag = "5")] PartitionId(i64), + /// Explicit partition location to write to. + #[prost(message, tag = "7")] + PartitionWithGeneration(super::super::PartitionWithGeneration), } } - /// Response for handshake. + /// Response to the handshake. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct InitResponse { @@ -157,6 +178,8 @@ pub mod stream_write_message { /// See enum Codec above for values. #[prost(int32, tag = "2")] pub codec: i32, + #[prost(message, optional, tag = "3")] + pub tx: ::core::option::Option, } /// Nested message and enum types in `WriteRequest`. pub mod write_request { @@ -178,8 +201,11 @@ pub mod stream_write_message { /// Uncompressed size of client message body. #[prost(int64, tag = "4")] pub uncompressed_size: i64, + /// Message metadata. Overall size is limited to 4096 symbols (all keys and values combined). + #[prost(message, repeated, tag = "7")] + pub metadata_items: ::prost::alloc::vec::Vec, /// Per-message override for respective write session settings. - #[prost(oneof = "message_data::Partitioning", tags = "5, 6")] + #[prost(oneof = "message_data::Partitioning", tags = "5, 6, 8")] pub partitioning: ::core::option::Option, } /// Nested message and enum types in `MessageData`. @@ -194,6 +220,9 @@ pub mod stream_write_message { /// Explicit partition id to write to. #[prost(int64, tag = "6")] PartitionId(i64), + /// Explicit partition location to write to. + #[prost(message, tag = "8")] + PartitionWithGeneration(super::super::super::PartitionWithGeneration), } } } @@ -224,7 +253,7 @@ pub mod stream_write_message { #[prost(int64, tag = "1")] pub seq_no: i64, /// Either message is written for the first time or duplicate. - #[prost(oneof = "write_ack::MessageWriteStatus", tags = "2, 3")] + #[prost(oneof = "write_ack::MessageWriteStatus", tags = "2, 3, 4")] pub message_write_status: ::core::option::Option< write_ack::MessageWriteStatus, >, @@ -275,6 +304,9 @@ pub mod stream_write_message { } } } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct WrittenInTx {} /// Either message is written for the first time or duplicate. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Oneof)] @@ -283,6 +315,8 @@ pub mod stream_write_message { Written(Written), #[prost(message, tag = "3")] Skipped(Skipped), + #[prost(message, tag = "4")] + WrittenInTx(WrittenInTx), } } /// Message with write statistics. @@ -328,7 +362,7 @@ pub mod stream_read_message { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct PartitionSession { - /// Identitifier of partition session. Unique inside one RPC call. + /// Identifier of partition session. Unique inside one RPC call. #[prost(int64, tag = "1")] pub partition_session_id: i64, /// Topic path of partition. @@ -344,6 +378,7 @@ pub mod stream_read_message { /// CommitOffsetRequest - request for commit of some read data. /// PartitionSessionStatusRequest - request for session status /// UpdateTokenRequest - request to update auth token + /// DirectReadAck - client signals it has finished direct reading from the partition node. /// StartPartitionSessionResponse - Response to StreamReadServerMessage.StartPartitionSessionRequest. /// Client signals it is ready to get data from partition. /// StopPartitionSessionResponse - Response to StreamReadServerMessage.StopPartitionSessionRequest. @@ -351,7 +386,7 @@ pub mod stream_read_message { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct FromClient { - #[prost(oneof = "from_client::ClientMessage", tags = "1, 2, 3, 4, 5, 6, 7")] + #[prost(oneof = "from_client::ClientMessage", tags = "1, 2, 3, 4, 5, 8, 6, 7")] pub client_message: ::core::option::Option, } /// Nested message and enum types in `FromClient`. @@ -370,6 +405,8 @@ pub mod stream_read_message { PartitionSessionStatusRequest(super::PartitionSessionStatusRequest), #[prost(message, tag = "5")] UpdateTokenRequest(super::super::UpdateTokenRequest), + #[prost(message, tag = "8")] + DirectReadAck(super::DirectReadAck), /// Responses to respective server commands. #[prost(message, tag = "6")] StartPartitionSessionResponse(super::StartPartitionSessionResponse), @@ -385,6 +422,7 @@ pub mod stream_read_message { /// UpdateTokenResponse - acknowledgment of token update. /// StartPartitionSessionRequest - command from server to create a partition session. /// StopPartitionSessionRequest - command from server to destroy a partition session. + /// UpdatePartitionSession - command from server to update a partition session. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct FromServer { @@ -394,7 +432,7 @@ pub mod stream_read_message { /// Issues if any. #[prost(message, repeated, tag = "2")] pub issues: ::prost::alloc::vec::Vec, - #[prost(oneof = "from_server::ServerMessage", tags = "3, 4, 5, 6, 7, 8, 9")] + #[prost(oneof = "from_server::ServerMessage", tags = "3, 4, 5, 6, 7, 8, 9, 10")] pub server_message: ::core::option::Option, } /// Nested message and enum types in `FromServer`. @@ -418,6 +456,8 @@ pub mod stream_read_message { StartPartitionSessionRequest(super::StartPartitionSessionRequest), #[prost(message, tag = "9")] StopPartitionSessionRequest(super::StopPartitionSessionRequest), + #[prost(message, tag = "10")] + UpdatePartitionSession(super::UpdatePartitionSession), } } /// Handshake request. @@ -433,6 +473,12 @@ pub mod stream_read_message { /// Path of consumer that is used for reading by this session. #[prost(string, tag = "2")] pub consumer: ::prost::alloc::string::String, + /// Optional name. Will be shown in debug stat. + #[prost(string, tag = "3")] + pub reader_name: ::prost::alloc::string::String, + /// Direct reading from a partition node. + #[prost(bool, tag = "4")] + pub direct_read: bool, } /// Nested message and enum types in `InitRequest`. pub mod init_request { @@ -464,7 +510,7 @@ pub mod stream_read_message { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct InitResponse { - /// Read session identifier for debug purposes. + /// Read session identifier. #[prost(string, tag = "1")] pub session_id: ::prost::alloc::string::String, } @@ -489,7 +535,7 @@ pub mod stream_read_message { /// 4) Server is free to send up to 50 + 100 = 150 bytes. But the next read message is too big, /// and it sends 160 bytes ReadResponse. /// 5) Let's assume client somehow processes it, and its 200 bytes buffer is free again. - /// It shoud account for excess 10 bytes and send ReadRequest with bytes_size = 210. + /// It should account for excess 10 bytes and send ReadRequest with bytes_size = 210. #[prost(int64, tag = "1")] pub bytes_size: i64, } @@ -512,7 +558,7 @@ pub mod stream_read_message { #[derive(Clone, PartialEq, ::prost::Message)] pub struct MessageData { /// Partition offset in partition that assigned for message. - /// unique value for clientside deduplication - Topic:Partition:Offset + /// unique value for client side deduplication - Topic:Partition:Offset #[prost(int64, tag = "1")] pub offset: i64, /// Sequence number that provided with message on write from client. @@ -534,6 +580,8 @@ pub mod stream_read_message { /// Filled if message_group_id was set on message write. #[prost(string, tag = "7")] pub message_group_id: ::prost::alloc::string::String, + #[prost(message, repeated, tag = "8")] + pub metadata_items: ::prost::alloc::vec::Vec, } /// Representation of sequence of client messages from one write session. #[derive(serde::Serialize, serde::Deserialize)] @@ -626,7 +674,7 @@ pub mod stream_read_message { #[prost(int64, tag = "1")] pub partition_session_id: i64, } - /// Response for status request. + /// Response to status request. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct PartitionSessionStatusResponse { @@ -659,6 +707,9 @@ pub mod stream_read_message { /// Partition contains messages with offsets in range [start, end). #[prost(message, optional, tag = "3")] pub partition_offsets: ::core::option::Option, + /// Partition location, filled only when InitRequest.direct_read is true. + #[prost(message, optional, tag = "4")] + pub partition_location: ::core::option::Option, } /// Signal for server that cient is ready to recive data for partition. #[derive(serde::Serialize, serde::Deserialize)] @@ -699,6 +750,9 @@ pub mod stream_read_message { /// Upper bound for committed offsets. #[prost(int64, tag = "3")] pub committed_offset: i64, + /// Upper bound for read request identifiers, filled only when InitRequest.direct_read is true and graceful is true. + #[prost(int64, tag = "4")] + pub last_direct_read_id: i64, } /// Signal for server that client finished working with this partition. /// Must be sent only after corresponding StopPartitionSessionRequest from server. @@ -709,8 +763,276 @@ pub mod stream_read_message { /// Partition session identifier of partition session that is released by client. #[prost(int64, tag = "1")] pub partition_session_id: i64, + /// Flag of graceful stop, used only when InitRequest.direct_read is true + /// Client must pass this value unchanged from the StopPartitionSessionRequest. + /// Server can sent two StopPartitionSessionRequests, the first with graceful=true, the second with graceful=false. The client must answer both of them. + #[prost(bool, tag = "2")] + pub graceful: bool, + } + /// Command from server to notify about a partition session update. + /// Client should not send a response to the command. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct UpdatePartitionSession { + /// Partition session identifier. + #[prost(int64, tag = "1")] + pub partition_session_id: i64, + /// Partition location, filled only when InitRequest.direct_read is true. + #[prost(message, optional, tag = "2")] + pub partition_location: ::core::option::Option, + } + /// Signal for server that client has finished direct reading. + /// Server should not send a response to the command. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct DirectReadAck { + /// Partition session identifier. + #[prost(int64, tag = "1")] + pub partition_session_id: i64, + /// Identifier of the successfully completed read request. + #[prost(int64, tag = "2")] + pub direct_read_id: i64, + } +} +/// Messages for bidirectional streaming rpc StreamDirectRead +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StreamDirectReadMessage {} +/// Nested message and enum types in `StreamDirectReadMessage`. +pub mod stream_direct_read_message { + /// Client-server message for direct read session. + /// InitDirectRead - command from client to create and start a direct read session. + /// StartDirectReadPartitionSession - command from client to create and start a direct read partition session. + /// UpdateTokenRequest - request to update auth token + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct FromClient { + #[prost(oneof = "from_client::ClientMessage", tags = "1, 2, 3")] + pub client_message: ::core::option::Option, + } + /// Nested message and enum types in `FromClient`. + pub mod from_client { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum ClientMessage { + #[prost(message, tag = "1")] + InitDirectRead(super::InitDirectRead), + #[prost(message, tag = "2")] + StartDirectReadPartitionSession(super::StartDirectReadPartitionSession), + #[prost(message, tag = "3")] + UpdateTokenRequest(super::super::UpdateTokenRequest), + } + } + /// Server-client message for direct read session. + /// DirectReadResponse - portion of message data. + /// StopDirectReadPartitionSession - command from server to stop a direct read partition session. + /// UpdateTokenResponse - acknowledgment of token update. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct FromServer { + /// Server status of response. + #[prost(enumeration = "super::super::status_ids::StatusCode", tag = "1")] + pub status: i32, + /// Issues if any. + #[prost(message, repeated, tag = "2")] + pub issues: ::prost::alloc::vec::Vec, + #[prost(oneof = "from_server::ServerMessage", tags = "3, 4, 5")] + pub server_message: ::core::option::Option, + } + /// Nested message and enum types in `FromServer`. + pub mod from_server { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum ServerMessage { + #[prost(message, tag = "3")] + StopDirectReadPartitionSession(super::StopDirectReadPartitionSession), + #[prost(message, tag = "4")] + DirectReadResponse(super::DirectReadResponse), + #[prost(message, tag = "5")] + UpdateTokenResponse(super::super::UpdateTokenResponse), + } + } + /// Command from client to create and start a direct read session. + /// Server should not send a response to the command. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct InitDirectRead { + /// Read session identifier. + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, + /// Topics that will be read by this session. + #[prost(message, repeated, tag = "2")] + pub topics_read_settings: ::prost::alloc::vec::Vec< + init_direct_read::TopicReadSettings, + >, + /// Path of consumer that is used for reading by this session. + #[prost(string, tag = "3")] + pub consumer: ::prost::alloc::string::String, + } + /// Nested message and enum types in `InitDirectRead`. + pub mod init_direct_read { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct TopicReadSettings { + /// Topic path. + #[prost(string, tag = "1")] + pub path: ::prost::alloc::string::String, + } + } + /// Command from client to create and start a direct read partition session. + /// Server should not send a response to the command. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct StartDirectReadPartitionSession { + /// Partition session identifier. + #[prost(int64, tag = "1")] + pub partition_session_id: i64, + /// Upper bound for read request identifiers. + #[prost(int64, tag = "2")] + pub last_direct_read_id: i64, + /// Partition generation. + #[prost(int64, tag = "3")] + pub generation: i64, + } + /// Command from server to stop a direct read partition session. + /// Client should not send a response to the command. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct StopDirectReadPartitionSession { + /// The reason for the stop. + #[prost(enumeration = "super::super::status_ids::StatusCode", tag = "1")] + pub status: i32, + /// Issues if any. + #[prost(message, repeated, tag = "2")] + pub issues: ::prost::alloc::vec::Vec, + /// Partition session identifier. + #[prost(int64, tag = "3")] + pub partition_session_id: i64, + } + /// Messages that have been read directly from the partition node. + /// It's a response to StreamRead.ReadRequest + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct DirectReadResponse { + /// Partition session identifier. + #[prost(int64, tag = "1")] + pub partition_session_id: i64, + /// Read request identifier. + #[prost(int64, tag = "2")] + pub direct_read_id: i64, + /// Messages data + #[prost(message, optional, tag = "3")] + pub partition_data: ::core::option::Option< + super::stream_read_message::read_response::PartitionData, + >, + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransactionIdentity { + /// Transaction identifier from TableService. + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, + /// Session identifier from TableService. + #[prost(string, tag = "2")] + pub session: ::prost::alloc::string::String, +} +/// Add offsets to transaction request sent from client to server. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateOffsetsInTransactionRequest { + #[prost(message, optional, tag = "1")] + pub operation_params: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub tx: ::core::option::Option, + /// Ranges of offsets by topics. + #[prost(message, repeated, tag = "3")] + pub topics: ::prost::alloc::vec::Vec< + update_offsets_in_transaction_request::TopicOffsets, + >, + #[prost(string, tag = "4")] + pub consumer: ::prost::alloc::string::String, +} +/// Nested message and enum types in `UpdateOffsetsInTransactionRequest`. +pub mod update_offsets_in_transaction_request { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct TopicOffsets { + /// Topic path. + #[prost(string, tag = "1")] + pub path: ::prost::alloc::string::String, + /// Ranges of offsets by partitions. + #[prost(message, repeated, tag = "2")] + pub partitions: ::prost::alloc::vec::Vec, + } + /// Nested message and enum types in `TopicOffsets`. + pub mod topic_offsets { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct PartitionOffsets { + /// Partition identifier. + #[prost(int64, tag = "1")] + pub partition_id: i64, + /// List of offset ranges. + #[prost(message, repeated, tag = "2")] + pub partition_offsets: ::prost::alloc::vec::Vec, + } } } +/// Add offsets to transaction response sent from server to client. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateOffsetsInTransactionResponse { + /// Result of request will be inside operation. + #[prost(message, optional, tag = "1")] + pub operation: ::core::option::Option, +} +/// Add offsets to transaction result message that will be inside UpdateOffsetsInTransactionResponse.operation. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateOffsetsInTransactionResult {} +/// Commit offset request sent from client to server. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitOffsetRequest { + #[prost(message, optional, tag = "1")] + pub operation_params: ::core::option::Option, + /// Topic path of partition. + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, + /// Partition identifier. + #[prost(int64, tag = "3")] + pub partition_id: i64, + /// Path of consumer. + #[prost(string, tag = "4")] + pub consumer: ::prost::alloc::string::String, + /// Processed offset. + #[prost(int64, tag = "5")] + pub offset: i64, +} +/// Commit offset response sent from server to client. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitOffsetResponse { + /// Result of request will be inside operation. + #[prost(message, optional, tag = "1")] + pub operation: ::core::option::Option, +} +/// Commit offset result message inside CommitOffsetResponse.operation. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitOffsetResult {} +/// message representing statistics by several windows +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct MultipleWindowsStat { + #[prost(int64, tag = "1")] + pub per_minute: i64, + #[prost(int64, tag = "2")] + pub per_hour: i64, + #[prost(int64, tag = "3")] + pub per_day: i64, +} /// Consumer description. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -728,6 +1050,7 @@ pub struct Consumer { pub read_from: ::core::option::Option, /// List of supported codecs by this consumer. /// supported_codecs on topic must be contained inside this list. + /// If empty, codec compatibility check for the consumer is disabled. #[prost(message, optional, tag = "5")] pub supported_codecs: ::core::option::Option, /// Attributes of consumer @@ -736,6 +1059,34 @@ pub struct Consumer { ::prost::alloc::string::String, ::prost::alloc::string::String, >, + /// Filled only when requested statistics in Describe*Request. + #[prost(message, optional, tag = "7")] + pub consumer_stats: ::core::option::Option, +} +/// Nested message and enum types in `Consumer`. +pub mod consumer { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct ConsumerStats { + /// Minimal timestamp of last read from partitions. + #[prost(message, optional, tag = "1")] + pub min_partitions_last_read_time: ::core::option::Option< + super::super::super::google::protobuf::Timestamp, + >, + /// Maximum of differences between timestamp of read and write timestamp for all messages, read during last minute. + #[prost(message, optional, tag = "2")] + pub max_read_time_lag: ::core::option::Option< + super::super::super::google::protobuf::Duration, + >, + /// Maximum of differences between write timestamp and create timestamp for all messages, read during last minute. + #[prost(message, optional, tag = "3")] + pub max_write_time_lag: ::core::option::Option< + super::super::super::google::protobuf::Duration, + >, + /// Bytes read statistics. + #[prost(message, optional, tag = "4")] + pub bytes_read: ::core::option::Option, + } } /// Consumer alter description. #[derive(serde::Serialize, serde::Deserialize)] @@ -754,6 +1105,7 @@ pub struct AlterConsumer { pub set_read_from: ::core::option::Option, /// List of supported codecs by this consumer. /// supported_codecs on topic must be contained inside this list. + /// If empty, codec compatibility check for the consumer is disabled. #[prost(message, optional, tag = "5")] pub set_supported_codecs: ::core::option::Option, /// User and server attributes of consumer. Server attributes starts from "_" and will be validated by server. @@ -816,6 +1168,7 @@ pub struct CreateTopicRequest { pub retention_storage_mb: i64, /// List of allowed codecs for writers. /// Writes with codec not from this list are forbidden. + /// If empty, codec compatibility check for the topic is disabled. #[prost(message, optional, tag = "7")] pub supported_codecs: ::core::option::Option, /// Partition write speed in bytes per second. Must be less than database limit. @@ -852,6 +1205,17 @@ pub struct CreateTopicResponse { #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct CreateTopicResult {} +/// Topic partition location +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PartitionLocation { + /// Node identificator. + #[prost(int32, tag = "1")] + pub node_id: i32, + /// Partition generation. + #[prost(int64, tag = "2")] + pub generation: i64, +} /// Describe topic request sent from client to server. #[derive(serde::Serialize, serde::Deserialize)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -861,6 +1225,12 @@ pub struct DescribeTopicRequest { /// Topic path. #[prost(string, tag = "2")] pub path: ::prost::alloc::string::String, + /// Include topic statistics. + #[prost(bool, tag = "3")] + pub include_stats: bool, + /// Include partition location. + #[prost(bool, tag = "4")] + pub include_location: bool, } /// Describe topic response sent from server to client. /// If topic is not existed then response status will be "SCHEME_ERROR". @@ -897,12 +1267,17 @@ pub struct DescribeTopicResult { pub retention_storage_mb: i64, /// List of allowed codecs for writers. /// Writes with codec not from this list are forbidden. + /// If empty, codec compatibility check for the topic is disabled. #[prost(message, optional, tag = "7")] pub supported_codecs: ::core::option::Option, /// Partition write speed in bytes per second. /// Zero value means default limit: 1 MB per second. #[prost(int64, tag = "8")] pub partition_write_speed_bytes_per_second: i64, + #[prost(int64, tag = "14")] + pub partition_total_read_speed_bytes_per_second: i64, + #[prost(int64, tag = "15")] + pub partition_consumer_read_speed_bytes_per_second: i64, /// Burst size for write in partition, in bytes. /// Zero value means default limit: 1 MB. #[prost(int64, tag = "9")] @@ -919,6 +1294,9 @@ pub struct DescribeTopicResult { /// Metering settings. #[prost(enumeration = "MeteringMode", tag = "12")] pub metering_mode: i32, + /// Statistics of topic. + #[prost(message, optional, tag = "13")] + pub topic_stats: ::core::option::Option, } /// Nested message and enum types in `DescribeTopicResult`. pub mod describe_topic_result { @@ -937,7 +1315,207 @@ pub mod describe_topic_result { /// Ids of partitions from which this partition was formed by split or merge. #[prost(int64, repeated, tag = "4")] pub parent_partition_ids: ::prost::alloc::vec::Vec, + /// Stats for partition, filled only when include_stats in request is true. + #[prost(message, optional, tag = "5")] + pub partition_stats: ::core::option::Option, + /// Partition location, filled only when include_location in request is true. + #[prost(message, optional, tag = "6")] + pub partition_location: ::core::option::Option, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct TopicStats { + /// Approximate size of topic. + #[prost(int64, tag = "1")] + pub store_size_bytes: i64, + /// Minimum of timestamps of last write among all partitions. + #[prost(message, optional, tag = "2")] + pub min_last_write_time: ::core::option::Option< + super::super::super::google::protobuf::Timestamp, + >, + /// Maximum of differences between write timestamp and create timestamp for all messages, written during last minute. + #[prost(message, optional, tag = "3")] + pub max_write_time_lag: ::core::option::Option< + super::super::super::google::protobuf::Duration, + >, + /// How much bytes were written statistics. + #[prost(message, optional, tag = "4")] + pub bytes_written: ::core::option::Option, + } +} +/// Describe partition request sent from client to server. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribePartitionRequest { + #[prost(message, optional, tag = "1")] + pub operation_params: ::core::option::Option, + /// Topic path. + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, + /// Partition identifier. + #[prost(int64, tag = "3")] + pub partition_id: i64, + /// Include partition statistics. + #[prost(bool, tag = "4")] + pub include_stats: bool, + /// Include partition location. + #[prost(bool, tag = "5")] + pub include_location: bool, +} +/// Describe partition response sent from server to client. +/// If topic is not existed then response status will be "SCHEME_ERROR". +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribePartitionResponse { + /// Result of request will be inside operation. + #[prost(message, optional, tag = "1")] + pub operation: ::core::option::Option, +} +/// Describe partition result message that will be inside DescribeTopicResponse.operation. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribePartitionResult { + /// Partitions description. + #[prost(message, optional, tag = "1")] + pub partition: ::core::option::Option, +} +/// Describe topic's consumer request sent from client to server. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribeConsumerRequest { + #[prost(message, optional, tag = "1")] + pub operation_params: ::core::option::Option, + /// Topic path. + #[prost(string, tag = "2")] + pub path: ::prost::alloc::string::String, + /// Consumer name; + #[prost(string, tag = "3")] + pub consumer: ::prost::alloc::string::String, + /// Include consumer statistics. + #[prost(bool, tag = "4")] + pub include_stats: bool, + /// Include partition location. + #[prost(bool, tag = "5")] + pub include_location: bool, +} +/// Describe topic's consumer response sent from server to client. +/// If topic is not existed then response status will be "SCHEME_ERROR". +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribeConsumerResponse { + /// Result of request will be inside operation. + #[prost(message, optional, tag = "1")] + pub operation: ::core::option::Option, +} +/// Describe topic's consumer result message that will be inside DescribeConsumerResponse.operation. +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DescribeConsumerResult { + /// Description of scheme object. + #[prost(message, optional, tag = "1")] + pub self_: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub consumer: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub partitions: ::prost::alloc::vec::Vec, +} +/// Nested message and enum types in `DescribeConsumerResult`. +pub mod describe_consumer_result { + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct PartitionInfo { + /// Partition identifier. + #[prost(int64, tag = "1")] + pub partition_id: i64, + /// Is partition open for write. + #[prost(bool, tag = "2")] + pub active: bool, + /// Ids of partitions which was formed when this partition was split or merged. + #[prost(int64, repeated, tag = "3")] + pub child_partition_ids: ::prost::alloc::vec::Vec, + /// Ids of partitions from which this partition was formed by split or merge. + #[prost(int64, repeated, tag = "4")] + pub parent_partition_ids: ::prost::alloc::vec::Vec, + /// Stats for partition, filled only when include_stats in request is true. + #[prost(message, optional, tag = "5")] + pub partition_stats: ::core::option::Option, + /// Stats for consumer of this partition, filled only when include_stats in request is true. + #[prost(message, optional, tag = "6")] + pub partition_consumer_stats: ::core::option::Option, + /// Partition location, filled only when include_location in request is true. + #[prost(message, optional, tag = "7")] + pub partition_location: ::core::option::Option, } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct PartitionConsumerStats { + /// Last read offset from this partition. + #[prost(int64, tag = "1")] + pub last_read_offset: i64, + /// Committed offset for this partition. + #[prost(int64, tag = "2")] + pub committed_offset: i64, + /// Reading this partition read session identifier. + #[prost(string, tag = "3")] + pub read_session_id: ::prost::alloc::string::String, + /// Timestamp of providing this partition to this session by server. + #[prost(message, optional, tag = "4")] + pub partition_read_session_create_time: ::core::option::Option< + super::super::super::google::protobuf::Timestamp, + >, + /// Timestamp of last read from this partition. + #[prost(message, optional, tag = "5")] + pub last_read_time: ::core::option::Option< + super::super::super::google::protobuf::Timestamp, + >, + /// Maximum of differences between timestamp of read and write timestamp for all messages, read during last minute. + #[prost(message, optional, tag = "6")] + pub max_read_time_lag: ::core::option::Option< + super::super::super::google::protobuf::Duration, + >, + /// Maximum of differences between write timestamp and create timestamp for all messages, read during last minute. + #[prost(message, optional, tag = "7")] + pub max_write_time_lag: ::core::option::Option< + super::super::super::google::protobuf::Duration, + >, + /// How much bytes were read during several windows statistics from this partition. + #[prost(message, optional, tag = "8")] + pub bytes_read: ::core::option::Option, + /// Read session name, provided by client. + #[prost(string, tag = "11")] + pub reader_name: ::prost::alloc::string::String, + /// Host where read session connected. + #[prost(int32, tag = "12")] + pub connection_node_id: i32, + } +} +#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PartitionStats { + /// Partition contains messages with offsets in range [start, end). + #[prost(message, optional, tag = "1")] + pub partition_offsets: ::core::option::Option, + /// Approximate size of partition. + #[prost(int64, tag = "2")] + pub store_size_bytes: i64, + /// Timestamp of last write. + #[prost(message, optional, tag = "3")] + pub last_write_time: ::core::option::Option< + super::super::google::protobuf::Timestamp, + >, + /// Maximum of differences between write timestamp and create timestamp for all messages, written during last minute. + #[prost(message, optional, tag = "4")] + pub max_write_time_lag: ::core::option::Option< + super::super::google::protobuf::Duration, + >, + /// How much bytes were written during several windows in this partition. + #[prost(message, optional, tag = "5")] + pub bytes_written: ::core::option::Option, + /// Partition host. Useful for debugging purposes. + /// Use PartitionLocation + #[deprecated] + #[prost(int32, tag = "8")] + pub partition_node_id: i32, } /// Update existing topic request sent from client to server. #[derive(serde::Serialize, serde::Deserialize)] @@ -964,6 +1542,7 @@ pub struct AlterTopicRequest { pub set_retention_storage_mb: ::core::option::Option, /// List of allowed codecs for writers. /// Writes with codec not from this list are forbidden. + /// If empty, codec compatibility check for the topic is disabled. #[prost(message, optional, tag = "7")] pub set_supported_codecs: ::core::option::Option, /// Partition write speed in bytes per second. Must be less than database limit. Default limit - 1 MB/s. diff --git a/ydb-grpc/src/generated/ydb.topic.v1.rs b/ydb-grpc/src/generated/ydb.topic.v1.rs index dcb14499..ebfa6805 100644 --- a/ydb-grpc/src/generated/ydb.topic.v1.rs +++ b/ydb-grpc/src/generated/ydb.topic.v1.rs @@ -174,6 +174,51 @@ pub mod topic_service_client { ); self.inner.streaming(request.into_streaming_request(), path, codec).await } + /// Single commit offset request. + pub async fn commit_offset( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/Ydb.Topic.V1.TopicService/CommitOffset", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// Add information about offset ranges to the transaction. + pub async fn update_offsets_in_transaction( + &mut self, + request: impl tonic::IntoRequest< + super::super::UpdateOffsetsInTransactionRequest, + >, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/Ydb.Topic.V1.TopicService/UpdateOffsetsInTransaction", + ); + self.inner.unary(request.into_request(), path, codec).await + } /// Create topic command. pub async fn create_topic( &mut self, @@ -217,6 +262,29 @@ pub mod topic_service_client { ); self.inner.unary(request.into_request(), path, codec).await } + /// Describe topic's consumer command. + pub async fn describe_consumer( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/Ydb.Topic.V1.TopicService/DescribeConsumer", + ); + self.inner.unary(request.into_request(), path, codec).await + } /// Alter topic command. pub async fn alter_topic( &mut self, diff --git a/ydb-grpc/ydb-api-protos b/ydb-grpc/ydb-api-protos index 07b827b8..3490f62e 160000 --- a/ydb-grpc/ydb-api-protos +++ b/ydb-grpc/ydb-api-protos @@ -1 +1 @@ -Subproject commit 07b827b89f426c8b8ec0d14ede78db1cb1c540a6 +Subproject commit 3490f62eb05039bc1f881bfda62030edc17784d7 diff --git a/ydb/src/client_scheme/list_types.rs b/ydb/src/client_scheme/list_types.rs index def3679a..226eea5d 100644 --- a/ydb/src/client_scheme/list_types.rs +++ b/ydb/src/client_scheme/list_types.rs @@ -15,6 +15,8 @@ pub enum SchemeEntryType { Unspecified, Directory, Table, + ColumnStrore, + ColumnTable, PersQueueGroup, Database, RtmrVolume, @@ -23,6 +25,9 @@ pub enum SchemeEntryType { Sequence, Replication, Topic, + ExternalDataSource, + ExternalTable, + View, Unknown(i32), } diff --git a/ydb/src/client_topic/topicwriter/message_write_status.rs b/ydb/src/client_topic/topicwriter/message_write_status.rs index 71523b51..e6f6046d 100644 --- a/ydb/src/client_topic/topicwriter/message_write_status.rs +++ b/ydb/src/client_topic/topicwriter/message_write_status.rs @@ -12,10 +12,14 @@ pub enum MessageSkipReason { UnknownReasonCode(i32), } +#[cfg_attr(not(feature = "force-exhaustive-all"), non_exhaustive)] +pub struct MessageWriteInTxInfo {} + #[cfg_attr(not(feature = "force-exhaustive-all"), non_exhaustive)] pub enum MessageWriteStatus { Written(MessageWriteInfo), Skipped(MessageSkipReason), + WrittenInTx(MessageWriteInTxInfo), Unknown, } @@ -48,6 +52,9 @@ impl From> for MessageWrit Some(write_response::write_ack::MessageWriteStatus::Skipped(skip_info)) => { MessageWriteStatus::Skipped(MessageSkipReason::from(skip_info.reason)) } + Some(write_response::write_ack::MessageWriteStatus::WrittenInTx(_write_info)) => { + MessageWriteStatus::WrittenInTx(MessageWriteInTxInfo{}) + } } } } diff --git a/ydb/src/client_topic/topicwriter/writer.rs b/ydb/src/client_topic/topicwriter/writer.rs index 676a7883..fcf7e341 100644 --- a/ydb/src/client_topic/topicwriter/writer.rs +++ b/ydb/src/client_topic/topicwriter/writer.rs @@ -245,6 +245,7 @@ impl TopicWriter { as i64, nanos: message.created_at.duration_since(UNIX_EPOCH)?.as_nanos() as i32, }), + metadata_items: vec![], data: message.data, uncompressed_size: data_size, partitioning: Some(message_data::Partitioning::MessageGroupId( @@ -270,6 +271,7 @@ impl TopicWriter { client_message: Some(ClientMessage::WriteRequest(WriteRequest { messages, codec: 1, + tx: None, })), }) .unwrap(); // TODO: HANDLE ERROR diff --git a/ydb/src/grpc_wrapper/raw_scheme_client/list_directory_types.rs b/ydb/src/grpc_wrapper/raw_scheme_client/list_directory_types.rs index 03b784e6..f7f66750 100644 --- a/ydb/src/grpc_wrapper/raw_scheme_client/list_directory_types.rs +++ b/ydb/src/grpc_wrapper/raw_scheme_client/list_directory_types.rs @@ -73,6 +73,8 @@ fn from_grpc_code_to_scheme_entry_type(value: i32) -> SchemeEntryType { Some(grpcT::Unspecified) => SchemeEntryType::Unspecified, Some(grpcT::Directory) => SchemeEntryType::Directory, Some(grpcT::Table) => SchemeEntryType::Table, + Some(grpcT::ColumnStore) => SchemeEntryType::ColumnStrore, + Some(grpcT::ColumnTable) => SchemeEntryType::ColumnTable, Some(grpcT::PersQueueGroup) => SchemeEntryType::PersQueueGroup, Some(grpcT::Database) => SchemeEntryType::Database, Some(grpcT::RtmrVolume) => SchemeEntryType::RtmrVolume, @@ -81,6 +83,9 @@ fn from_grpc_code_to_scheme_entry_type(value: i32) -> SchemeEntryType { Some(grpcT::Sequence) => SchemeEntryType::Sequence, Some(grpcT::Replication) => SchemeEntryType::Replication, Some(grpcT::Topic) => SchemeEntryType::Topic, + Some(grpcT::ExternalDataSource) => SchemeEntryType::ExternalDataSource, + Some(grpcT::ExternalTable) => SchemeEntryType::ExternalTable, + Some(grpcT::View) => SchemeEntryType::View, None => SchemeEntryType::Unknown(value), } } diff --git a/ydb/src/grpc_wrapper/raw_table_service/value/type.rs b/ydb/src/grpc_wrapper/raw_table_service/value/type.rs index aa8711b0..ef10c2bd 100644 --- a/ydb/src/grpc_wrapper/raw_table_service/value/type.rs +++ b/ydb/src/grpc_wrapper/raw_table_service/value/type.rs @@ -280,6 +280,9 @@ impl TryFrom for RawType { item_type: RawType::try_from(*t)?, })) } + ProtoType::PgType(_pg_type) => { + return decode_err("pg type unimplemented yet"); + } ProtoType::VoidType(_) => RawType::Void, ProtoType::NullType(_) => RawType::Null, ProtoType::EmptyListType(_) => RawType::EmptyList, diff --git a/ydb/src/grpc_wrapper/raw_topic_service/common/consumer.rs b/ydb/src/grpc_wrapper/raw_topic_service/common/consumer.rs index 88afd9ed..a6c7180f 100644 --- a/ydb/src/grpc_wrapper/raw_topic_service/common/consumer.rs +++ b/ydb/src/grpc_wrapper/raw_topic_service/common/consumer.rs @@ -35,6 +35,7 @@ impl From for Consumer { read_from, supported_codecs: Some(SupportedCodecs::from(value.supported_codecs)), attributes: value.attributes, + consumer_stats: None, } } } From 1c32018effdd7775fd8ce80976b17d06cdf2eeb5 Mon Sep 17 00:00:00 2001 From: robot Date: Wed, 9 Oct 2024 12:14:19 +0000 Subject: [PATCH 8/8] bump version for ydb-grpc, minor --- ydb-grpc/Cargo.toml | 2 +- ydb/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ydb-grpc/Cargo.toml b/ydb-grpc/Cargo.toml index 8a521908..37536371 100644 --- a/ydb-grpc/Cargo.toml +++ b/ydb-grpc/Cargo.toml @@ -1,7 +1,7 @@ [package] publish = true name = "ydb-grpc" -version = "0.0.14" +version = "0.1.0" authors = ["rekby "] edition = "2021" license = "Apache-2.0" diff --git a/ydb/Cargo.toml b/ydb/Cargo.toml index 2fae9de5..0a863819 100644 --- a/ydb/Cargo.toml +++ b/ydb/Cargo.toml @@ -53,7 +53,7 @@ tonic = { version = "0.8.1", features = ["tls"] } tower = "0.4" url = "2.2" uuid = { version = "1", features = ["v4"] } -ydb-grpc = { version = "0.0.14", path = "../ydb-grpc" } +ydb-grpc = { version = "0.1.0", path="../ydb-grpc"} [dev-dependencies] async_once = "0.2"