Skip to content

ruv2: fill rpc counters in exec details#1933

Merged
ti-chi-bot[bot] merged 2 commits into
tikv:masterfrom
oh-my-tidb:disksing/rpc-interceptor
Apr 2, 2026
Merged

ruv2: fill rpc counters in exec details#1933
ti-chi-bot[bot] merged 2 commits into
tikv:masterfrom
oh-my-tidb:disksing/rpc-interceptor

Conversation

@disksing
Copy link
Copy Markdown
Collaborator

@disksing disksing commented Mar 31, 2026

What changed

This PR updates the statement RUv2 raw RPC counters to flow through ExecDetailsV2.RuV2 instead of extending RUDetails in client-go.

Specifically:

  • update github.com/pingcap/kvproto to the latest master that includes RUV2.read_rpc_count and RUV2.write_rpc_count
  • remove the temporary raw counter fields and helpers previously added to RUDetails
  • fill ExecDetailsV2.RuV2.ReadRpcCount and ExecDetailsV2.RuV2.WriteRpcCount in client-go when handling completed RPCs
  • keep TiKV RUv2 calculation reading from ExecDetailsV2.RuV2, with a fallback for responses that still do not carry ExecDetailsV2

Why

The previous approach stored extra raw counters in RUDetails only so TiDB could read them back later. Now that kvproto exposes these counters in ExecDetailsV2.RuV2, client-go can put them directly into the protocol detail object and avoid carrying an additional side channel in RUDetails.

This keeps the raw counter source aligned with other RUv2 fields and simplifies the client-go runtime detail structure.

Impact

  • keeps statement-level raw RPC counters available to TiDB through ExecDetailsV2.RuV2
  • removes the temporary RUDetails extension added only for this feature
  • preserves the existing fallback path for write RPC charging when a response does not include ExecDetailsV2

Tests

  • go test ./util ./config ./internal/client ./tikvrpc

Summary by CodeRabbit

  • Bug Fixes

    • More accurate RU v2 accounting: read and write RPCs are tracked separately and streaming responses correctly contribute to RU metrics.
  • Chores

    • Bumped several module dependency versions across examples and main modules.
  • Tests

    • Updated tests to validate the new read/write RPC tracking and streaming behavior.

@ti-chi-bot ti-chi-bot Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. dco-signoff: yes Indicates the PR's author has signed the dco. labels Mar 31, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

This PR separates TiKV read/write RPC counting (int64), updates RU v2 update API and its delta computation to use both counts and mutates ExecDetailsV2.RuV2, wires counting through client and streaming responses, and bumps several go.mod dependency versions.

Changes

Cohort / File(s) Summary
RU v2 config & tests
config/ruv2.go, config/ruv2_test.go
Changed UpdateTiKVRUV2FromExecDetailsV2 signature to accept readRPCCount, writeRPCCount int64; tightened nil checks; mutate details.RuV2 counts and recompute delta using updated RU fields. Test renamed/updated to set WriteRpcCount in ExecDetailsV2 and call new signature.
Client RPC logic & async path
internal/client/client.go, internal/client/client_async.go, internal/client/client_async_test.go
Replaced single-write-count helper with completedTiKVRUV2RPCCount returning (read, write) int64; pass both counts into RU v2 updater. Coprocessor stream setup now sets Ctx and CountRPC for streaming responses. Updated async test assertions for write RPCs.
TiKV streaming responses
tikvrpc/tikvrpc.go, tikvrpc/tikvrpc_test.go
Added exported Ctx and CountRPC fields to stream response types; Recv() now conditionally reports a read RPC (when CountRPC true) by calling RU v2 updater with read count. Tests extended to assert RU v2 read/write and storage counters.
Go module files
go.mod, integration_tests/go.mod, examples/*/go.mod
Bumped github.com/pingcap/kvproto pseudo-version and upgraded various golang.org/x/* indirect dependency versions across module files. No code API exports changed.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Req as Request
    participant TiKV as TiKV RPC
    participant Resp as CopStreamResponse
    participant Config as config.UpdateTiKVRUV2FromExecDetailsV2

    Client->>Req: prepare request (sets CountRPC/Ctx for cop streams)
    Client->>TiKV: send RPC
    TiKV-->>Resp: stream response (Resp.CountRPC may be true)
    Resp->>Resp: Recv() reads message
    alt Resp.CountRPC == true
      Resp->>Config: UpdateTiKVRUV2FromExecDetailsV2(Resp.Ctx, ExecDetailsV2, readRPCCount=1, writeRPCCount=0)
    else
      Resp->>Config: UpdateTiKVRUV2FromExecDetailsV2(Resp.Ctx, ExecDetailsV2, 0, 0)
    end
    Config->>Config: mutate ExecDetailsV2.RuV2, recompute delta, accumulate ruDetails
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • nolouch
  • ekexium
  • cfzjywxk

Poem

🐰 I counted hops — read and write, one by one,
I nudged ExecDetails till the sums were done.
Streams now carry context, counts set just right,
Modules updated, and the tests hum with light. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: filling RPC counters (read/write) in ExecDetailsV2.RuV2 as the core objective of the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ti-chi-bot ti-chi-bot Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Mar 31, 2026
@disksing disksing force-pushed the disksing/rpc-interceptor branch 2 times, most recently from b55278d to 8863bb9 Compare March 31, 2026 15:06
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 31, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@disksing disksing marked this pull request as ready for review March 31, 2026 15:22
@ti-chi-bot ti-chi-bot Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 31, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tikvrpc/tikvrpc.go (1)

1349-1359: ⚠️ Potential issue | 🟠 Major

Complete the BatchCop stream accounting path.

internal/client/client.go now sets CountRPC on BatchCopStreamResponse and skips RUv2 updates in sendRequest() because streams are expected to self-account in Recv(). This method only clears the flag, so batch-cop responses never propagate any RPC counters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tikvrpc/tikvrpc.go` around lines 1349 - 1359, BatchCopStreamResponse.Recv
currently only clears the deadline and CountRPC flag but does not perform the
RPC/accounting work streams are expected to do; copy the RPC accounting path
from sendRequest() into Recv(): when ret != nil (i.e., a real BatchResponse is
received) set resp.BatchResponse = ret, ensure resp.CountRPC is set so this
response is charged, and invoke the same RPC counter/RUv2 update logic used in
sendRequest() (the exact bookkeeping calls used there) so the stream propagates
RPC counters and updates RU metrics for BatchCopStreamResponse.
🧹 Nitpick comments (1)
config/ruv2_test.go (1)

26-55: Add a nil-ExecDetailsV2 fallback case.

This only exercises the path where ExecDetailsV2.RuV2 already exists. A case with details == nil or details.RuV2 == nil would lock down the compatibility fallback for older responses now that raw RPC counts are being threaded through ExecDetailsV2.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/ruv2_test.go` around lines 26 - 55, Add tests that exercise the
nil-branch in UpdateTiKVRUV2FromExecDetailsV2 by calling it with details == nil
and with &kvrpcpb.ExecDetailsV2{RuV2: nil} so the compatibility fallback path is
covered; create a similar test setup as TestUpdateTiKVRUV2FromExecDetailsV2 (use
DefaultConfig(), DefaultRUV2TiKVConfig(), StoreGlobalConfig, util.NewRUDetails()
and ctx with util.RUDetailsCtxKey) and assert ruDetails.TiKVRUV2() equals the
expected fallback value (or remains unchanged) after each call to
UpdateTiKVRUV2FromExecDetailsV2 to lock down behavior for nil ExecDetailsV2 and
nil RuV2 cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@tikvrpc/tikvrpc.go`:
- Around line 1349-1359: BatchCopStreamResponse.Recv currently only clears the
deadline and CountRPC flag but does not perform the RPC/accounting work streams
are expected to do; copy the RPC accounting path from sendRequest() into Recv():
when ret != nil (i.e., a real BatchResponse is received) set resp.BatchResponse
= ret, ensure resp.CountRPC is set so this response is charged, and invoke the
same RPC counter/RUv2 update logic used in sendRequest() (the exact bookkeeping
calls used there) so the stream propagates RPC counters and updates RU metrics
for BatchCopStreamResponse.

---

Nitpick comments:
In `@config/ruv2_test.go`:
- Around line 26-55: Add tests that exercise the nil-branch in
UpdateTiKVRUV2FromExecDetailsV2 by calling it with details == nil and with
&kvrpcpb.ExecDetailsV2{RuV2: nil} so the compatibility fallback path is covered;
create a similar test setup as TestUpdateTiKVRUV2FromExecDetailsV2 (use
DefaultConfig(), DefaultRUV2TiKVConfig(), StoreGlobalConfig, util.NewRUDetails()
and ctx with util.RUDetailsCtxKey) and assert ruDetails.TiKVRUV2() equals the
expected fallback value (or remains unchanged) after each call to
UpdateTiKVRUV2FromExecDetailsV2 to lock down behavior for nil ExecDetailsV2 and
nil RuV2 cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 234b9772-a19e-4397-9f7a-af4a313730a5

📥 Commits

Reviewing files that changed from the base of the PR and between 3805cb7 and 22624f0.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • integration_tests/go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • config/ruv2.go
  • config/ruv2_test.go
  • examples/gcworker/go.mod
  • examples/rawkv/go.mod
  • examples/txnkv/1pc_txn/go.mod
  • examples/txnkv/async_commit/go.mod
  • examples/txnkv/delete_range/go.mod
  • examples/txnkv/go.mod
  • examples/txnkv/pessimistic_txn/go.mod
  • examples/txnkv/unsafedestoryrange/go.mod
  • go.mod
  • integration_tests/go.mod
  • internal/client/client.go
  • internal/client/client_async.go
  • internal/client/client_async_test.go
  • tikvrpc/tikvrpc.go
  • tikvrpc/tikvrpc_test.go

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Apr 1, 2026
@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Apr 1, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Apr 1, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ekexium, nolouch

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added the approved label Apr 1, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Apr 1, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-04-01 07:50:15.421293561 +0000 UTC m=+337820.626653608: ☑️ agreed by nolouch.
  • 2026-04-01 09:55:46.381617649 +0000 UTC m=+345351.586977706: ☑️ agreed by ekexium.

disksing added 2 commits April 2, 2026 10:33
Signed-off-by: disksing <i@disksing.com>
Signed-off-by: disksing <i@disksing.com>
@disksing disksing force-pushed the disksing/rpc-interceptor branch from 22624f0 to ec6a7ae Compare April 2, 2026 02:39
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tikvrpc/tikvrpc.go (1)

1348-1361: ⚠️ Potential issue | 🔴 Critical

Missing UpdateTiKVRUV2FromExecDetailsV2 call causes BatchCop RU v2 accounting to be dropped.

BatchCopStreamResponse.Recv() resets CountRPC but never calls config.UpdateTiKVRUV2FromExecDetailsV2. In contrast, CopStreamResponse.Recv() (lines 1326-1332) correctly implements this.

The Ctx field is wired up in getBatchCopStreamResponse but is never used here. Since client.go excludes BatchCopStreamResponse from the default handler with the comment "Stream responses are handled in Recv()", BatchCop streams will have zero RU v2 accounting.

Proposed fix to add RU v2 accounting
 func (resp *BatchCopStreamResponse) Recv() (*coprocessor.BatchResponse, error) {
 	deadline := time.Now().Add(resp.Timeout).UnixNano()
 	atomic.StoreInt64(&resp.deadline, deadline)

 	ret, err := resp.Tikv_BatchCoprocessorClient.Recv()

 	atomic.StoreInt64(&resp.deadline, 0) // Stop the lease check.
 	if ret != nil {
 		resp.BatchResponse = ret
+		readRPCCount := int64(0)
+		if resp.CountRPC {
+			resp.CountRPC = false
+			readRPCCount = 1
+		}
+		config.UpdateTiKVRUV2FromExecDetailsV2(resp.Ctx, ret.GetExecDetailsV2(), readRPCCount, 0)
-		resp.CountRPC = false
 	}
 	return ret, errors.WithStack(err)
 }

Note: You may also want to add a Bypass field to BatchCopStreamResponse for consistency with CopStreamResponse, or verify that BatchCop requests should never bypass resource control.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tikvrpc/tikvrpc.go` around lines 1348 - 1361, BatchCopStreamResponse.Recv()
resets CountRPC and clears the deadline but never updates RU v2 accounting; add
a call to config.UpdateTiKVRUV2FromExecDetailsV2 using resp.Ctx and the exec
details from the received response (similar to CopStreamResponse.Recv()) before
clearing CountRPC so BatchCop RU v2 usage is recorded; ensure you read exec
details from ret (resp.BatchResponse) when ret != nil, call
UpdateTiKVRUV2FromExecDetailsV2(resp.Ctx, execDetails, resp.CountRPC, /*bypass*/
false or a new resp.Bypass field if you add it for parity with
CopStreamResponse), then reset resp.CountRPC and deadline as currently done.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@tikvrpc/tikvrpc.go`:
- Around line 1348-1361: BatchCopStreamResponse.Recv() resets CountRPC and
clears the deadline but never updates RU v2 accounting; add a call to
config.UpdateTiKVRUV2FromExecDetailsV2 using resp.Ctx and the exec details from
the received response (similar to CopStreamResponse.Recv()) before clearing
CountRPC so BatchCop RU v2 usage is recorded; ensure you read exec details from
ret (resp.BatchResponse) when ret != nil, call
UpdateTiKVRUV2FromExecDetailsV2(resp.Ctx, execDetails, resp.CountRPC, /*bypass*/
false or a new resp.Bypass field if you add it for parity with
CopStreamResponse), then reset resp.CountRPC and deadline as currently done.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ee210a7f-6d65-45dc-a8ca-6be2431c2868

📥 Commits

Reviewing files that changed from the base of the PR and between 22624f0 and ec6a7ae.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • integration_tests/go.sum is excluded by !**/*.sum
📒 Files selected for processing (17)
  • config/ruv2.go
  • config/ruv2_test.go
  • examples/gcworker/go.mod
  • examples/rawkv/go.mod
  • examples/txnkv/1pc_txn/go.mod
  • examples/txnkv/async_commit/go.mod
  • examples/txnkv/delete_range/go.mod
  • examples/txnkv/go.mod
  • examples/txnkv/pessimistic_txn/go.mod
  • examples/txnkv/unsafedestoryrange/go.mod
  • go.mod
  • integration_tests/go.mod
  • internal/client/client.go
  • internal/client/client_async.go
  • internal/client/client_async_test.go
  • tikvrpc/tikvrpc.go
  • tikvrpc/tikvrpc_test.go
✅ Files skipped from review due to trivial changes (8)
  • examples/txnkv/unsafedestoryrange/go.mod
  • integration_tests/go.mod
  • examples/txnkv/delete_range/go.mod
  • examples/rawkv/go.mod
  • examples/gcworker/go.mod
  • examples/txnkv/1pc_txn/go.mod
  • examples/txnkv/go.mod
  • examples/txnkv/async_commit/go.mod
🚧 Files skipped from review as they are similar to previous changes (7)
  • examples/txnkv/pessimistic_txn/go.mod
  • internal/client/client_async.go
  • internal/client/client_async_test.go
  • go.mod
  • tikvrpc/tikvrpc_test.go
  • config/ruv2_test.go
  • config/ruv2.go

@ti-chi-bot ti-chi-bot Bot merged commit 1b3c5b5 into tikv:master Apr 2, 2026
18 of 19 checks passed
@disksing disksing deleted the disksing/rpc-interceptor branch April 2, 2026 05:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved dco-signoff: yes Indicates the PR's author has signed the dco. lgtm size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants