add API V3 keyspace identity protos - #1458
Conversation
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
# Conflicts: # pkg/kvrpcpb/kvrpcpb.pb.go # pkg/pdpb/pdpb.pb.go Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
# Conflicts: # pkg/keyspacepb/keyspacepb.pb.go # proto/keyspacepb.proto # scripts/proto.lock
| // The keyspace that the request is sent to. | ||
| // NOTE: This field is only meaningful while the api_version is V2. | ||
| uint32 keyspace_id = 32; | ||
| oneof keyspace { |
There was a problem hiding this comment.
Changing this existing scalar field into a oneof is source-incompatible for generated Go users even though the wire tag is preserved. Context.KeyspaceId disappears, and downstream PD/TiDB/client-go code constructs or reads this field directly, so upgrading kvproto would break V1/V2 callers that do not use V3. The legacy scalar should stay as a normal field and keyspace_identity should be added alongside it, as was done for AutoIDRequest and KeyspaceMeta.
There was a problem hiding this comment.
Thanks, fair point. I originally kept keyspace_id as a normal field and added keyspace_identity alongside it to minimize downstream Go source changes. Later I changed it to oneof based on review feedback, since semantically it is clearer that only one keyspace identifier should be set.
I think both directions are reasonable: parallel fields are more source-compatible, while oneof is clearer semantically. @sunxiaoguang what do you think? If we prefer minimizing downstream changes for kvrpcpb.Context, I can change this back to the parallel-field style.
There was a problem hiding this comment.
Thanks @rleungx @disksing for the insightful discussion.
I lean towards the oneof approach here. Here is my perspective:
Confined Blast Radius: While changing to oneof is indeed source-incompatible, the generated protobuf code is primarily encapsulated within our rich clients (client-go, client-rust, client-c). The blast radius of this incompatible change is limited and well-contained within these repositories, rather than leaking indefinitely downstream.
Compiler-Guaranteed Safety: For strongly-typed languages, breaking the source code during compilation is actually a major benefit in this context. It forces the compiler to help us pinpoint every single callsite that accesses the relevant fields. This completely eliminates the risk of missing any field migrations, which could otherwise lead to silent, hard-to-debug runtime issues.
Semantics vs. Refactoring Cost: Maintaining parallel fields compromises semantic clarity and risks inconsistent states (e.g., both fields being set). The value of absolute correctness and explicit semantics brought by oneof far outweighs the cost of limited code adjustments in the client libraries.
Therefore, I'd prefer to go with oneof to ensure long-term robustness.
Signed-off-by: disksing <i@disksing.com>
| // | ||
| // `V3` uses user-key wire semantics for normal KV RPCs. Servers encode an | ||
| // 8-byte physical prefix at the serving boundary: | ||
| // mode(1) + namespace_id(4 bytes, big endian) + keyspace_id(3 bytes, big endian). |
There was a problem hiding this comment.
What's the semantic difference between namespace id and keyspace id?
What are the considerations of encoding namespace id first? Can it be mode(1) + keyspace_id(3 bytes, big endian) + namespace_id(4 bytes, big endian)?
There was a problem hiding this comment.
namespace_id represents the higher-level namespace that groups multiple keyspaces. We intentionally encode it before keyspace_id because storage keys are ordered lexicographically. Using mode + namespace_id + keyspace_id ensures that all keyspaces belonging to the same namespace form one contiguous key range after sorting. If keyspace_id were encoded first, keyspaces from the same namespace would be scattered across different ranges. Therefore, we prefer to keep the namespace ID before the keyspace ID.
|
@disksing |
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bb7133, cfzjywxk, coocood, rleungx, windtalker, zhangjinpeng87 The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
| @@ -16,7 +17,12 @@ option (rustproto.lite_runtime_all) = true; | |||
|
|
|||
| // Keyspace provides services to manage keyspaces. | |||
| service Keyspace { | |||
There was a problem hiding this comment.
Namespace contains keyspace, but we put Namespace in the Keyspace service. Maybe adding a new Namespace service is better?
There was a problem hiding this comment.
Namespace and keyspace are tightly coupled in API V3, and namespace_id is part of KeyspaceIdentity. Therefore, keeping their management APIs in the same service seems reasonable. We can revisit a separate Namespace service if it gains a more independent lifecycle later.
|
Why didn't any reviewer point out the missing github related issue and design spec? |
Sync the final protocol changes from pingcap/kvproto#1458 at 7022f46937bc35125fb6d65aad5a0eedd59e7cfd onto release-8.5-keyspace. Preserve the downstream release schema and regenerate Go bindings and proto.lock with the downstream toolchain. Signed-off-by: disksing <i@disksing.com>
Issue: #1506
Summary
Validation