// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; package google.bigtable.v2; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/api/resource.proto"; import "google/api/routing.proto"; import "google/bigtable/v2/data.proto"; import "google/bigtable/v2/request_stats.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; import "google/rpc/status.proto"; option csharp_namespace = "Google.Cloud.Bigtable.V2"; option go_package = "google.golang.org/genproto/googleapis/bigtable/v2;bigtable"; option java_multiple_files = true; option java_outer_classname = "BigtableProto"; option java_package = "com.google.bigtable.v2"; option php_namespace = "Google\\Cloud\\Bigtable\\V2"; option ruby_package = "Google::Cloud::Bigtable::V2"; option (google.api.resource_definition) = { type: "bigtableadmin.googleapis.com/Instance" pattern: "projects/{project}/instances/{instance}" }; option (google.api.resource_definition) = { type: "bigtableadmin.googleapis.com/Table" pattern: "projects/{project}/instances/{instance}/tables/{table}" }; // Service for reading from and writing to existing Bigtable tables. service Bigtable { option (google.api.default_host) = "bigtable.googleapis.com"; option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/bigtable.data," "https://www.googleapis.com/auth/bigtable.data.readonly," "https://www.googleapis.com/auth/cloud-bigtable.data," "https://www.googleapis.com/auth/cloud-bigtable.data.readonly," "https://www.googleapis.com/auth/cloud-platform," "https://www.googleapis.com/auth/cloud-platform.read-only"; // Streams back the contents of all requested rows in key order, optionally // applying the same Reader filter to each. Depending on their size, // rows and cells may be broken up across multiple responses, but // atomicity of each row will still be preserved. See the // ReadRowsResponse documentation for details. rpc ReadRows(ReadRowsRequest) returns (stream ReadRowsResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:readRows" body: "*" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name"; option (google.api.method_signature) = "table_name,app_profile_id"; } // Returns a sample of row keys in the table. The returned row keys will // delimit contiguous sections of the table of approximately equal size, // which can be used to break up the data for distributed tasks like // mapreduces. rpc SampleRowKeys(SampleRowKeysRequest) returns (stream SampleRowKeysResponse) { option (google.api.http) = { get: "/v2/{table_name=projects/*/instances/*/tables/*}:sampleRowKeys" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name"; option (google.api.method_signature) = "table_name,app_profile_id"; } // Mutates a row atomically. Cells already present in the row are left // unchanged unless explicitly changed by `mutation`. rpc MutateRow(MutateRowRequest) returns (MutateRowResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:mutateRow" body: "*" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name,row_key,mutations"; option (google.api.method_signature) = "table_name,row_key,mutations,app_profile_id"; } // Mutates multiple rows in a batch. Each individual row is mutated // atomically as in MutateRow, but the entire batch is not executed // atomically. rpc MutateRows(MutateRowsRequest) returns (stream MutateRowsResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:mutateRows" body: "*" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name,entries"; option (google.api.method_signature) = "table_name,entries,app_profile_id"; } // Mutates a row atomically based on the output of a predicate Reader filter. rpc CheckAndMutateRow(CheckAndMutateRowRequest) returns (CheckAndMutateRowResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:checkAndMutateRow" body: "*" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name,row_key,predicate_filter,true_mutations,false_mutations"; option (google.api.method_signature) = "table_name,row_key,predicate_filter,true_mutations,false_mutations,app_profile_id"; } // Warm up associated instance metadata for this connection. // This call is not required but may be useful for connection keep-alive. rpc PingAndWarm(PingAndWarmRequest) returns (PingAndWarmResponse) { option (google.api.http) = { post: "/v2/{name=projects/*/instances/*}:ping" body: "*" }; option (google.api.routing) = { routing_parameters { field: "name" path_template: "{name=projects/*/instances/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "name"; option (google.api.method_signature) = "name,app_profile_id"; } // Modifies a row atomically on the server. The method reads the latest // existing timestamp and value from the specified columns and writes a new // entry based on pre-defined read/modify/write rules. The new value for the // timestamp is the greater of the existing timestamp or the current server // time. The method returns the new contents of all modified cells. rpc ReadModifyWriteRow(ReadModifyWriteRowRequest) returns (ReadModifyWriteRowResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:readModifyWriteRow" body: "*" }; option (google.api.routing) = { routing_parameters { field: "table_name" path_template: "{table_name=projects/*/instances/*/tables/*}" } routing_parameters { field: "app_profile_id" } }; option (google.api.method_signature) = "table_name,row_key,rules"; option (google.api.method_signature) = "table_name,row_key,rules,app_profile_id"; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Returns the current list of partitions that make up the table's // change stream. The union of partitions will cover the entire keyspace. // Partitions can be read with `ReadChangeStream`. rpc GenerateInitialChangeStreamPartitions( GenerateInitialChangeStreamPartitionsRequest) returns (stream GenerateInitialChangeStreamPartitionsResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:generateInitialChangeStreamPartitions" body: "*" }; option (google.api.method_signature) = "table_name"; option (google.api.method_signature) = "table_name,app_profile_id"; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Reads changes from a table's change stream. Changes will // reflect both user-initiated mutations and mutations that are caused by // garbage collection. rpc ReadChangeStream(ReadChangeStreamRequest) returns (stream ReadChangeStreamResponse) { option (google.api.http) = { post: "/v2/{table_name=projects/*/instances/*/tables/*}:readChangeStream" body: "*" }; option (google.api.method_signature) = "table_name"; option (google.api.method_signature) = "table_name,app_profile_id"; } } // Request message for Bigtable.ReadRows. message ReadRowsRequest { // The desired view into RequestStats that should be returned in the response. // // See also: RequestStats message. enum RequestStatsView { // The default / unset value. The API will default to the NONE option below. REQUEST_STATS_VIEW_UNSPECIFIED = 0; // Do not include any RequestStats in the response. This will leave the // RequestStats embedded message unset in the response. REQUEST_STATS_NONE = 1; // Include the full set of available RequestStats in the response, // applicable to this read. REQUEST_STATS_FULL = 2; } // Required. The unique name of the table from which to read. // Values are of the form // `projects//instances//tables/`. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 5; // The row keys and/or ranges to read sequentially. If not specified, reads // from all rows. RowSet rows = 2; // The filter to apply to the contents of the specified row(s). If unset, // reads the entirety of each row. RowFilter filter = 3; // The read will stop after committing to N rows' worth of results. The // default (zero) is to return all results. int64 rows_limit = 4; // The view into RequestStats, as described above. RequestStatsView request_stats_view = 6; } // Response message for Bigtable.ReadRows. message ReadRowsResponse { // Specifies a piece of a row's contents returned as part of the read // response stream. message CellChunk { // The row key for this chunk of data. If the row key is empty, // this CellChunk is a continuation of the same row as the previous // CellChunk in the response stream, even if that CellChunk was in a // previous ReadRowsResponse message. bytes row_key = 1; // The column family name for this chunk of data. If this message // is not present this CellChunk is a continuation of the same column // family as the previous CellChunk. The empty string can occur as a // column family name in a response so clients must check // explicitly for the presence of this message, not just for // `family_name.value` being non-empty. google.protobuf.StringValue family_name = 2; // The column qualifier for this chunk of data. If this message // is not present, this CellChunk is a continuation of the same column // as the previous CellChunk. Column qualifiers may be empty so // clients must check for the presence of this message, not just // for `qualifier.value` being non-empty. google.protobuf.BytesValue qualifier = 3; // The cell's stored timestamp, which also uniquely identifies it // within its column. Values are always expressed in // microseconds, but individual tables may set a coarser // granularity to further restrict the allowed values. For // example, a table which specifies millisecond granularity will // only allow values of `timestamp_micros` which are multiples of // 1000. Timestamps are only set in the first CellChunk per cell // (for cells split into multiple chunks). int64 timestamp_micros = 4; // Labels applied to the cell by a // [RowFilter][google.bigtable.v2.RowFilter]. Labels are only set // on the first CellChunk per cell. repeated string labels = 5; // The value stored in the cell. Cell values can be split across // multiple CellChunks. In that case only the value field will be // set in CellChunks after the first: the timestamp and labels // will only be present in the first CellChunk, even if the first // CellChunk came in a previous ReadRowsResponse. bytes value = 6; // If this CellChunk is part of a chunked cell value and this is // not the final chunk of that cell, value_size will be set to the // total length of the cell value. The client can use this size // to pre-allocate memory to hold the full cell value. int32 value_size = 7; // Signals to the client concerning previous CellChunks received. oneof row_status { // Indicates that the client should drop all previous chunks for // `row_key`, as it will be re-read from the beginning. bool reset_row = 8; // Indicates that the client can safely process all previous chunks for // `row_key`, as its data has been fully read. bool commit_row = 9; } } // A collection of a row's contents as part of the read request. repeated CellChunk chunks = 1; // Optionally the server might return the row key of the last row it // has scanned. The client can use this to construct a more // efficient retry request if needed: any row keys or portions of // ranges less than this row key can be dropped from the request. // This is primarily useful for cases where the server has read a // lot of data that was filtered out since the last committed row // key, allowing the client to skip that work on a retry. bytes last_scanned_row_key = 2; // // If requested, provide enhanced query performance statistics. The semantics // dictate: // * request_stats is empty on every (streamed) response, except // * request_stats has non-empty information after all chunks have been // streamed, where the ReadRowsResponse message only contains // request_stats. // * For example, if a read request would have returned an empty // response instead a single ReadRowsResponse is streamed with empty // chunks and request_stats filled. // // Visually, response messages will stream as follows: // ... -> {chunks: [...]} -> {chunks: [], request_stats: {...}} // \______________________/ \________________________________/ // Primary response Trailer of RequestStats info // // Or if the read did not return any values: // {chunks: [], request_stats: {...}} // \________________________________/ // Trailer of RequestStats info RequestStats request_stats = 3; } // Request message for Bigtable.SampleRowKeys. message SampleRowKeysRequest { // Required. The unique name of the table from which to sample row keys. // Values are of the form // `projects//instances//tables/
`. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 2; } // Response message for Bigtable.SampleRowKeys. message SampleRowKeysResponse { // Sorted streamed sequence of sample row keys in the table. The table might // have contents before the first row key in the list and after the last one, // but a key containing the empty string indicates "end of table" and will be // the last response given, if present. // Note that row keys in this list may not have ever been written to or read // from, and users should therefore not make any assumptions about the row key // structure that are specific to their use case. bytes row_key = 1; // Approximate total storage space used by all rows in the table which precede // `row_key`. Buffering the contents of all rows between two subsequent // samples would require space roughly equal to the difference in their // `offset_bytes` fields. int64 offset_bytes = 2; } // Request message for Bigtable.MutateRow. message MutateRowRequest { // Required. The unique name of the table to which the mutation should be // applied. Values are of the form // `projects//instances//tables/
`. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 4; // Required. The key of the row to which the mutation should be applied. bytes row_key = 2 [(google.api.field_behavior) = REQUIRED]; // Required. Changes to be atomically applied to the specified row. Entries // are applied in order, meaning that earlier mutations can be masked by later // ones. Must contain at least one entry and at most 100000. repeated Mutation mutations = 3 [(google.api.field_behavior) = REQUIRED]; } // Response message for Bigtable.MutateRow. message MutateRowResponse {} // Request message for BigtableService.MutateRows. message MutateRowsRequest { // A mutation for a given row. message Entry { // The key of the row to which the `mutations` should be applied. bytes row_key = 1; // Required. Changes to be atomically applied to the specified row. // Mutations are applied in order, meaning that earlier mutations can be // masked by later ones. You must specify at least one mutation. repeated Mutation mutations = 2 [(google.api.field_behavior) = REQUIRED]; } // Required. The unique name of the table to which the mutations should be // applied. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 3; // Required. The row keys and corresponding mutations to be applied in bulk. // Each entry is applied as an atomic mutation, but the entries may be // applied in arbitrary order (even between entries for the same row). // At least one entry must be specified, and in total the entries can // contain at most 100000 mutations. repeated Entry entries = 2 [(google.api.field_behavior) = REQUIRED]; } // Response message for BigtableService.MutateRows. message MutateRowsResponse { // The result of applying a passed mutation in the original request. message Entry { // The index into the original request's `entries` list of the Entry // for which a result is being reported. int64 index = 1; // The result of the request Entry identified by `index`. // Depending on how requests are batched during execution, it is possible // for one Entry to fail due to an error with another Entry. In the event // that this occurs, the same error will be reported for both entries. google.rpc.Status status = 2; } // One or more results for Entries from the batch request. repeated Entry entries = 1; // Information about how client should limit the rate (QPS). Primirily used by // supported official Cloud Bigtable clients. If unset, the rate limit info is // not provided by the server. optional RateLimitInfo rate_limit_info = 3; } // Information about how client should adjust the load to Bigtable. message RateLimitInfo { // Time that clients should wait before adjusting the target rate again. // If clients adjust rate too frequently, the impact of the previous // adjustment may not have been taken into account and may // over-throttle or under-throttle. If clients adjust rate too slowly, they // will not be responsive to load changes on server side, and may // over-throttle or under-throttle. google.protobuf.Duration period = 1; // If it has been at least one `period` since the last load adjustment, the // client should multiply the current load by this value to get the new target // load. For example, if the current load is 100 and `factor` is 0.8, the new // target load should be 80. After adjusting, the client should ignore // `factor` until another `period` has passed. // // The client can measure its load using any unit that's comparable over time // For example, QPS can be used as long as each request involves a similar // amount of work. double factor = 2; } // Request message for Bigtable.CheckAndMutateRow. message CheckAndMutateRowRequest { // Required. The unique name of the table to which the conditional mutation // should be applied. Values are of the form // `projects//instances//tables/
`. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 7; // Required. The key of the row to which the conditional mutation should be // applied. bytes row_key = 2 [(google.api.field_behavior) = REQUIRED]; // The filter to be applied to the contents of the specified row. Depending // on whether or not any results are yielded, either `true_mutations` or // `false_mutations` will be executed. If unset, checks that the row contains // any values at all. RowFilter predicate_filter = 6; // Changes to be atomically applied to the specified row if `predicate_filter` // yields at least one cell when applied to `row_key`. Entries are applied in // order, meaning that earlier mutations can be masked by later ones. // Must contain at least one entry if `false_mutations` is empty, and at most // 100000. repeated Mutation true_mutations = 4; // Changes to be atomically applied to the specified row if `predicate_filter` // does not yield any cells when applied to `row_key`. Entries are applied in // order, meaning that earlier mutations can be masked by later ones. // Must contain at least one entry if `true_mutations` is empty, and at most // 100000. repeated Mutation false_mutations = 5; } // Response message for Bigtable.CheckAndMutateRow. message CheckAndMutateRowResponse { // Whether or not the request's `predicate_filter` yielded any results for // the specified row. bool predicate_matched = 1; } // Request message for client connection keep-alive and warming. message PingAndWarmRequest { // Required. The unique name of the instance to check permissions for as well // as respond. Values are of the form // `projects//instances/`. string name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Instance" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 2; } // Response message for Bigtable.PingAndWarm connection keepalive and warming. message PingAndWarmResponse {} // Request message for Bigtable.ReadModifyWriteRow. message ReadModifyWriteRowRequest { // Required. The unique name of the table to which the read/modify/write rules // should be applied. Values are of the form // `projects//instances//tables/
`. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. string app_profile_id = 4; // Required. The key of the row to which the read/modify/write rules should be // applied. bytes row_key = 2 [(google.api.field_behavior) = REQUIRED]; // Required. Rules specifying how the specified row's contents are to be // transformed into writes. Entries are applied in order, meaning that earlier // rules will affect the results of later ones. repeated ReadModifyWriteRule rules = 3 [(google.api.field_behavior) = REQUIRED]; } // Response message for Bigtable.ReadModifyWriteRow. message ReadModifyWriteRowResponse { // A Row containing the new contents of all cells modified by the request. Row row = 1; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Request message for Bigtable.GenerateInitialChangeStreamPartitions. message GenerateInitialChangeStreamPartitionsRequest { // Required. The unique name of the table from which to get change stream // partitions. Values are of the form // `projects//instances//tables/
`. // Change streaming must be enabled on the table. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. // Single cluster routing must be configured on the profile. string app_profile_id = 2; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Response message for Bigtable.GenerateInitialChangeStreamPartitions. message GenerateInitialChangeStreamPartitionsResponse { // A partition of the change stream. StreamPartition partition = 1; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Request message for Bigtable.ReadChangeStream. message ReadChangeStreamRequest { // Required. The unique name of the table from which to read a change stream. // Values are of the form // `projects//instances//tables/
`. // Change streaming must be enabled on the table. string table_name = 1 [ (google.api.field_behavior) = REQUIRED, (google.api.resource_reference) = { type: "bigtableadmin.googleapis.com/Table" } ]; // This value specifies routing for replication. If not specified, the // "default" application profile will be used. // Single cluster routing must be configured on the profile. string app_profile_id = 2; // The partition to read changes from. StreamPartition partition = 3; // Options for describing where we want to start reading from the stream. oneof start_from { // Start reading the stream at the specified timestamp. This timestamp must // be within the change stream retention period, less than or equal to the // current time, and after change stream creation, whichever is greater. // This value is inclusive and will be truncated to microsecond granularity. google.protobuf.Timestamp start_time = 4; // Tokens that describe how to resume reading a stream where reading // previously left off. If specified, changes will be read starting at the // the position. Tokens are delivered on the stream as part of `Heartbeat` // and `CloseStream` messages. // // If a single token is provided, the token’s partition must exactly match // the request’s partition. If multiple tokens are provided, as in the case // of a partition merge, the union of the token partitions must exactly // cover the request’s partition. Otherwise, INVALID_ARGUMENT will be // returned. StreamContinuationTokens continuation_tokens = 6; } // If specified, OK will be returned when the stream advances beyond // this time. Otherwise, changes will be continuously delivered on the stream. // This value is inclusive and will be truncated to microsecond granularity. google.protobuf.Timestamp end_time = 5; // If specified, the duration between `Heartbeat` messages on the stream. // Otherwise, defaults to 5 seconds. google.protobuf.Duration heartbeat_duration = 7; } // NOTE: This API is intended to be used by Apache Beam BigtableIO. // Response message for Bigtable.ReadChangeStream. message ReadChangeStreamResponse { // A partial or complete mutation. message MutationChunk { // Information about the chunking of this mutation. // Only `SetCell` mutations can be chunked, and all chunks for a `SetCell` // will be delivered contiguously with no other mutation types interleaved. message ChunkInfo { // The total value size of all the chunks that make up the `SetCell`. int32 chunked_value_size = 1; // The byte offset of this chunk into the total value size of the // mutation. int32 chunked_value_offset = 2; // When true, this is the last chunk of a chunked `SetCell`. bool last_chunk = 3; } // If set, then the mutation is a `SetCell` with a chunked value across // multiple messages. ChunkInfo chunk_info = 1; // If this is a continuation of a chunked message (`chunked_value_offset` > // 0), ignore all fields except the `SetCell`'s value and merge it with // the previous message by concatenating the value fields. Mutation mutation = 2; } // A message corresponding to one or more mutations to the partition // being streamed. A single logical `DataChange` message may also be split // across a sequence of multiple individual messages. Messages other than // the first in a sequence will only have the `type` and `chunks` fields // populated, with the final message in the sequence also containing `done` // set to true. message DataChange { // The type of mutation. enum Type { // The type is unspecified. TYPE_UNSPECIFIED = 0; // A user-initiated mutation. USER = 1; // A system-initiated mutation as part of garbage collection. // https://cloud.google.com/bigtable/docs/garbage-collection GARBAGE_COLLECTION = 2; // This is a continuation of a multi-message change. CONTINUATION = 3; } // The type of the mutation. Type type = 1; // The cluster where the mutation was applied. // Not set when `type` is `GARBAGE_COLLECTION`. string source_cluster_id = 2; // The row key for all mutations that are part of this `DataChange`. // If the `DataChange` is chunked across multiple messages, then this field // will only be set for the first message. bytes row_key = 3; // The timestamp at which the mutation was applied on the Bigtable server. google.protobuf.Timestamp commit_timestamp = 4; // A value that lets stream consumers reconstruct Bigtable's // conflict resolution semantics. // https://cloud.google.com/bigtable/docs/writes#conflict-resolution // In the event that the same row key, column family, column qualifier, // timestamp are modified on different clusters at the same // `commit_timestamp`, the mutation with the larger `tiebreaker` will be the // one chosen for the eventually consistent state of the system. int32 tiebreaker = 5; // The mutations associated with this change to the partition. // May contain complete mutations or chunks of a multi-message chunked // `DataChange` record. repeated MutationChunk chunks = 6; // When true, indicates that the entire `DataChange` has been read // and the client can safely process the message. bool done = 8; // An encoded position for this stream's partition to restart reading from. // This token is for the StreamPartition from the request. string token = 9; // An estimate of the commit timestamp that is usually lower than or equal // to any timestamp for a record that will be delivered in the future on the // stream. It is possible that, under particular circumstances that a future // record has a timestamp is is lower than a previously seen timestamp. For // an example usage see // https://beam.apache.org/documentation/basics/#watermarks google.protobuf.Timestamp estimated_low_watermark = 10; } // A periodic message with information that can be used to checkpoint // the state of a stream. message Heartbeat { // A token that can be provided to a subsequent `ReadChangeStream` call // to pick up reading at the current stream position. StreamContinuationToken continuation_token = 1; // An estimate of the commit timestamp that is usually lower than or equal // to any timestamp for a record that will be delivered in the future on the // stream. It is possible that, under particular circumstances that a future // record has a timestamp is is lower than a previously seen timestamp. For // an example usage see // https://beam.apache.org/documentation/basics/#watermarks google.protobuf.Timestamp estimated_low_watermark = 2; } // A message indicating that the client should stop reading from the stream. // If status is OK and `continuation_tokens` & `new_partitions` are empty, the // stream has finished (for example if there was an `end_time` specified). // If `continuation_tokens` & `new_partitions` are present, then a change in // partitioning requires the client to open a new stream for each token to // resume reading. Example: // [B, D) ends // | // v // new_partitions: [A, C) [C, E) // continuation_tokens.partitions: [B,C) [C,D) // ^---^ ^---^ // ^ ^ // | | // | StreamContinuationToken 2 // | // StreamContinuationToken 1 // To read the new partition [A,C), supply the continuation tokens whose // ranges cover the new partition, for example ContinuationToken[A,B) & // ContinuationToken[B,C). message CloseStream { // The status of the stream. google.rpc.Status status = 1; // If non-empty, contains the information needed to resume reading their // associated partitions. repeated StreamContinuationToken continuation_tokens = 2; // If non-empty, contains the new partitions to start reading from, which // are related to but not necessarily identical to the partitions for the // above `continuation_tokens`. repeated StreamPartition new_partitions = 3; } // The data or control message on the stream. oneof stream_record { // A mutation to the partition. DataChange data_change = 1; // A periodic heartbeat message. Heartbeat heartbeat = 2; // An indication that the stream should be closed. CloseStream close_stream = 3; } }