kvproto

repository·master·Indexed 41 days ago

https://github.com/pingcap/kvproto

A centralized repository for Protocol Buffer definitions used by TiKV, providing schema management and generated Go and Rust code bindings to ensure protocol consistency. It includes specifications for the DB9 Coprocessor Protocol, backup metadata compatibility, and helper methods for managing UploadRequest, WriteEngineRequest, and Error types via the prost-codec feature.

Tokens
2.2K
Snippets
7
Records
11
Agent score
51%

What's inside kvproto

  1. How the DB9 Coprocessor Protocol is transported

    master

    The DB9 protocol does not introduce a new gRPC service. Instead, it reuses the existing TiKV coprocessor.Request envelope to leverage existing routing, region clipping, and admission control.

    To transport a DB9 request, you must configure the outer coprocessor.Request as follows:

    • tp: Set to REQ_TYPE_DB9_DAG.
    • ranges: Provide concrete, region-clipped key ranges.
    • data: Provide the serialized Db9DagRequest payload.

    This separation allows the outer envelope to manage physical routing while the inner DB9 payload manages logical scan shapes and execution metadata.

    coprocessor.Request {
      tp: REQ_TYPE_DB9_DAG
      ranges: [region_clipped_ranges]
      data: serialized_Db9DagRequest
    }
  2. Maintain BackupMeta schema compatibility

    master

    When modifying the backup metadata wire schema in proto/brpb.proto (specifically for backup.BackupMeta or any messages reachable from it), you must increment the BackupSchemaVersion to ensure compatibility.

    The version constant is located in pkg/brpb/backup_schema_version.go.

  3. Compile protobufs using Docker

    master

    The simplest way to compile the protobufs without managing local dependencies is via Docker.

    1. Build the Docker image:
      ./scripts/docker-build.sh
    2. Run the compilation command (e.g., for Go):
      ./scripts/docker-run.sh make go
    ./scripts/docker-build.sh
    ./scripts/docker-run.sh make go
  4. How to use kvproto to manage TiKV protocol buffers

    master

    kvproto is a repository containing the Protocol Buffer files used by TiKV. Developers use it to manage the schema definitions for TiKV's communication protocols and to generate language-specific bindings for Go and Rust.

    Workflow for updating or adding protocols:

    1. Add/Modify Protos: Write new .proto files in the proto/ folder.
    2. Sync raft-rs (if needed): If you need to update raft-rs, download the corresponding .proto file from the raft-rs repository and overwrite the existing file in the include/ folder.
    3. Generate Code: Run make to generate the language bindings.
      • Go code is generated in the pkg/ folder.
      • Rust code is generated in the src/ folder.
    4. Update Dependencies: Update any dependent projects to use the newly generated code.
    make
  5. Format and check proto file formatting

    master

    To prevent IDE-induced diffs and maintain consistency, kvproto uses buf format. The formatter is automatically downloaded into the ./bin directory (which is gitignored) when required.

    • Check formatting: Run make proto-fmt-check. This is also executed automatically during make check.
    • Apply formatting in-place: Run make proto-fmt.

    If make check fails due to formatting issues, run make proto-fmt and then rerun make check.

    make proto-fmt
  6. Structure of a Db9SelectResponse

    master

    The Db9SelectResponse is the unary response payload returned by the coprocessor. It contains:

    • rows: The result rows. For aggregate pushdown, rows are laid out as [group_keys..., partial_states...].
    • stats: A Db9ExecStats object reporting:
      • scanned_keys
      • scanned_rows
      • decoded_rows
      • returned_rows
    • warnings: Any execution warnings.

    Note: The current implementation is unary only. Streaming responses are not yet supported and will be rejected by the executor.

  7. Structure of a Db9DagRequest

    master

    A Db9DagRequest is the unary request payload used for DB9 coprocessor execution. It contains the following core components:

    Core Identity

    • codec_version: The DB9-local wire contract version (starting from 1).
    • db_id: The tenant/database identity used for row and index key prefixes.

    Schema Metadata (Db9TableInfo)

    Carries a schema snapshot to avoid extra fetches during execution. Includes:

    • table_name, table_id, schema_version
    • columns, pk_indices, indexes

    Scan Specification (Db9ScanSpec)

    Defines the logical scan shape:

    • kind, index_id, index_name, desc
    • require_row_fetch: A boolean indicating if the executor must fetch base rows (required for non-covering index scans).

    Expressions and Projection

    Uses Db9Expr to represent DB9-native expression trees (constants, column references, binary/unary expressions, casts, function calls, and null checks). Db9NamedExpr is used to name projection outputs.

    Aggregation (Db9AggregatePlan)

    Optional metadata for partial aggregation:

    • mode: Currently supports DB9_AGGREGATE_MODE_PARTIAL_ONLY.
    • group_keys: The keys to group by.
    • aggregates: A list of Db9AggregateSpec containing function_name, optional arg, and partial_state_types (used to define the row contract for complex aggregates like AVG).

    Limit (Db9LimitSpec)

    Carries a pushed limit. If the field is absent, it signifies no pushed limit.

  8. DB9 Type System and Wire Values

    master

    The protocol uses Db9TypeKind to model the DB9 type namespace and Db9Value to carry actual data.

    Db9Value supports the following wire values:

    • null_value
    • bool_value
    • int32_value
    • int64_value
    • float64_value
    • text_value
    • bytes_value
    • timestamp_value (encoded as milliseconds since Unix epoch)
    • timestamptz_value (encoded as milliseconds since Unix epoch)
    enum Db9TypeKind { ... }
    
    message Db9Value {
      oneof value {
        bool bool_value = 1;
        int32 int32_value = 3;
        int64 int64_value = 4;
        float64 float64_value = 5;
        string text_value = 6;
        bytes bytes_value = 7;
        int64 timestamp_value = 8;    // ms since epoch
        int64 timestamptz_value = 9;  // ms since epoch
        ... 
      }
    }
  9. Manage UploadRequest data and metadata

    master

    When using the prost-codec feature, the UploadRequest type provides helper methods to manage its chunk field, which can contain either raw data or SST metadata.

    • set_data(v: Vec<u8>): Sets the chunk as upload_request::Chunk::Data.
    • get_data() -> &[u8]: Returns the data slice, or an empty slice if no data is present.
    • set_meta(v: SstMeta): Sets the chunk as upload_request::Chunk::Meta.
    • get_meta() -> &SstMeta: Returns a reference to the metadata, or a default reference if none is present.
    • has_meta() -> bool: Returns true if the chunk contains metadata.
    // Example usage of UploadRequest helpers
    let mut request = UploadRequest::default();
    request.set_data(vec![1, 2, 3]);
    assert_eq!(request.get_data(), &[1, 2, 3]);
    
    request.set_meta(some_sst_meta);
    assert!(request.has_meta());
  10. Manage WriteEngineRequest batches and heads

    master

    When using the prost-codec feature, WriteEngineRequest provides helpers to interact with its chunk field, which can hold either a WriteHead or a WriteBatch.

    • set_head(v: WriteHead): Sets the chunk as write_engine_request::Chunk::Head.
    • get_head() -> &WriteHead: Returns a reference to the head, or a default reference if none is present.
    • has_head() -> bool: Returns true if the chunk contains a head.
    • set_batch(v: WriteBatch): Sets the chunk as write_engine_request::Chunk::Batch.
    • get_batch() -> &WriteBatch: Returns a reference to the batch, or a default reference if none is present.
    • has_batch() -> bool: Returns true if the chunk contains a batch.
    • take_batch() -> WriteBatch: Consumes the chunk and returns the WriteBatch. Returns a default WriteBatch if no batch is present.
    // Example usage of WriteEngineRequest helpers
    let mut request = WriteEngineRequest::default();
    request.set_batch(my_batch);
    let batch = request.take_batch();
  11. Handle Error details in Error type

    master

    When using the prost-codec feature, the Error type provides a way to attach and retrieve specific error details including RegionError, KvError, and ClusterIdError.

    Setting Errors

    • set_region_error(v: errorpb::Error)
    • set_kv_error(v: kvrpcpb::KeyError)
    • set_cluster_id_error(v: ClusterIdError)

    Getting Errors

    • get_region_error() -> &errorpb::Error
    • get_kv_error() -> &kvrpcpb::KeyError
    • get_cluster_id_error() -> &ClusterIdError
    • has_region_error() -> bool
    • has_kv_error() -> bool
    • has_cluster_id_error() -> bool

    Mutable Access

    If the specific error type is not already present, these methods will initialize it with a default value before returning a mutable reference:

    • mut_region_error() -> &mut errorpb::Error
    • mut_kv_error() -> &mut kvrpcpb::KeyError
    • mut_cluster_id_error() -> &mut ClusterIdError