Skip to content

kv: support transactional delete mutations#239

Open
lance6716 wants to merge 2 commits into
tikv:masterfrom
lance6716:lance/txn-delete-support
Open

kv: support transactional delete mutations#239
lance6716 wants to merge 2 commits into
tikv:masterfrom
lance6716:lance/txn-delete-support

Conversation

@lance6716

@lance6716 lance6716 commented May 28, 2026

Copy link
Copy Markdown

Summary

  • add a mutation-aware transaction buffer
  • add Txn::del and prewrite Del mutations without values
  • preserve last-mutation-wins behavior for repeated same-key mutations in one Txn
  • add mock TiKV transaction delete and same-transaction mutation-order tests
  • wait for mock-tikv to listen before CI tests start

Testing

  • git diff --check
  • GitHub Actions build-test runs on this PR

Authorship

This PR was implemented by Codex, an AI coding agent, under user direction.

Summary by CodeRabbit

  • New Features

    • Transactions now support deleting keys within a transaction, including correct read-back behavior before commit.
  • Bug Fixes

    • Buffered transaction reads now distinguish between set and delete operations, returning the expected result after mixed updates.
    • Transaction batching and commit processing now handle mutation types more accurately.
  • Tests

    • Added coverage for transaction delete, delete-then-set, and post-commit verification scenarios.
  • Chores

    • Improved test startup reliability by waiting for the local service to become ready before running checks.

Copilot AI review requested due to automatic review settings May 28, 2026 14:51
@ti-chi-bot ti-chi-bot Bot added the dco-signoff: yes Indicates the PR's author has signed the dco. label May 28, 2026
@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds transaction mutation objects that represent Put and Delete operations, threads them through the transaction buffer and 2PC commit path, adds delete coverage in tests, and makes the CI test script wait for mock-tikv readiness before running tests.

Changes

Transaction delete semantics

Layer / File(s) Summary
TxnMutation type and sizing
include/pingcap/kv/2pc.h
TxnMutation stores an op and optional value, provides Put/Delete constructors, and exposes value-size accounting used by 2PC batching.
Transaction buffer delete support
include/pingcap/kv/Txn.h
Txn now buffers TxnMutation objects, records deletes with del(), returns not-found for buffered deletes in get(), and passes mutations through walkBuffer().
2PC mutation propagation
src/kv/2pc.cc, include/pingcap/kv/2pc.h
TwoPhaseCommitter copies buffered mutations from Txn, preserves each mutation op in prewrite requests, and continues iterating secondary keys from the mutation map.
Delete behavior test
src/test/region_split_test.cc
testTxnDelete covers set, delete, repeated delete, and delete-then-set cases using buffered get() results and snapshot verification.

CI test startup readiness

Layer / File(s) Summary
mock-tikv readiness check
ci/build-test.sh
ci/build-test.sh polls 127.0.0.1:2378, fails when the port never opens, and force-kills mock_tikv on failure or after make test finishes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through mutations, both put and delete,
Buffered and prewritten, neat on my feet.
The tests now wait for mock-tikv to rise,
Then hoppy green checks sparkle in my bunny eyes.
✨🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding transactional delete mutation support in kv.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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.

@ti-chi-bot ti-chi-bot Bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label May 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for delete operations in transactions by introducing a TxnMutation type that carries both the operation type (Put/Del) and value, replacing the previous string-only buffer.

Changes:

  • Introduced TxnMutation struct encapsulating op type and value
  • Added Txn::del() API and updated get()/2PC prewrite to handle deletes
  • Added a new test exercising txn delete

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
include/pingcap/kv/2pc.h Defines TxnMutation; changes mutations map value type; uses valueSize() for size calc
include/pingcap/kv/Txn.h Buffer now maps to TxnMutation; adds del(); updates get() and walkBuffer() signature
src/kv/2pc.cc Propagates op type into prewrite request; skips value for Del ops
src/test/region_split_test.cc Adds testTxnDelete covering set/get/del/get flow

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread include/pingcap/kv/Txn.h Outdated
Comment on lines +45 to +47
void set(const std::string & key, const std::string & value) { buffer.emplace(key, TxnMutation::Put(value)); }

void del(const std::string & key) { buffer.emplace(key, TxnMutation::Del()); }
Comment on lines +98 to +102
{
Snapshot snap(test_cluster.get(), test_cluster->pd_client->getTS());
ASSERT_EQ(snap.Get("delete_test_key"), "");
}
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/test/region_split_test.cc (1)

79-102: ⚡ Quick win

Add same-transaction mutation-order regression cases.

This test validates cross-transaction delete, but not set->del and del->set within a single txn, which are key buffer semantics for TxnMutation.

✅ Suggested test additions
 TEST_F(TestWithMockKVRegionSplit, testTxnDelete)
 {
@@
     {
         Snapshot snap(test_cluster.get(), test_cluster->pd_client->getTS());
         ASSERT_EQ(snap.Get("delete_test_key"), "");
     }
+
+    // set then delete in the same txn => key should not exist
+    {
+        Txn txn(test_cluster.get());
+        txn.set("delete_test_key_2", "v1");
+        txn.del("delete_test_key_2");
+        txn.commit();
+    }
+    {
+        Snapshot snap(test_cluster.get(), test_cluster->pd_client->getTS());
+        ASSERT_EQ(snap.Get("delete_test_key_2"), "");
+    }
+
+    // delete then set in the same txn => latest mutation should win
+    {
+        Txn txn(test_cluster.get());
+        txn.del("delete_test_key_3");
+        txn.set("delete_test_key_3", "v2");
+        txn.commit();
+    }
+    {
+        Snapshot snap(test_cluster.get(), test_cluster->pd_client->getTS());
+        ASSERT_EQ(snap.Get("delete_test_key_3"), "v2");
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/region_split_test.cc` around lines 79 - 102, Extend the
testTxnDelete in TestWithMockKVRegionSplit to cover same-transaction
mutation-order regressions: add one case that performs txn.set("key","val") then
txn.del("key") within the same Txn (followed by txn.commit()) and assert via
Snapshot.Get("key") that the key is absent, and add the complementary case that
does txn.del("key") then txn.set("key","val") in the same Txn (commit) and
assert Snapshot.Get("key") returns the new value; use the existing Txn,
Snapshot, txn.set, txn.del, txn.commit and snap.Get patterns to implement these
two blocks alongside the existing cross-transaction checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@include/pingcap/kv/Txn.h`:
- Around line 45-47: Txn::set and Txn::del currently use buffer.emplace(...)
which ignores subsequent mutations for the same key; change these to overwrite
semantics so later set/del replace prior entries by using map::insert_or_assign
(or operator[]) when writing into Txn::buffer, and similarly replace emplace
calls in TwoPhaseCommitter's walkBuffer-to-2PC-mutation logic with
insert_or_assign so the last mutation for a key wins; update references to
TxnMutation construction (TxnMutation::Put/Del) accordingly.

---

Nitpick comments:
In `@src/test/region_split_test.cc`:
- Around line 79-102: Extend the testTxnDelete in TestWithMockKVRegionSplit to
cover same-transaction mutation-order regressions: add one case that performs
txn.set("key","val") then txn.del("key") within the same Txn (followed by
txn.commit()) and assert via Snapshot.Get("key") that the key is absent, and add
the complementary case that does txn.del("key") then txn.set("key","val") in the
same Txn (commit) and assert Snapshot.Get("key") returns the new value; use the
existing Txn, Snapshot, txn.set, txn.del, txn.commit and snap.Get patterns to
implement these two blocks alongside the existing cross-transaction checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2f838173-5cb1-4ce5-9f59-90b5e3eb0f01

📥 Commits

Reviewing files that changed from the base of the PR and between 48009c6 and 06a5e0b.

📒 Files selected for processing (4)
  • include/pingcap/kv/2pc.h
  • include/pingcap/kv/Txn.h
  • src/kv/2pc.cc
  • src/test/region_split_test.cc

Comment thread include/pingcap/kv/Txn.h Outdated
@lance6716 lance6716 force-pushed the lance/txn-delete-support branch from 06a5e0b to 37b3a4f Compare May 28, 2026 15:05
@ti-chi-bot ti-chi-bot Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels May 28, 2026
Signed-off-by: lance6716 <lance6716@gmail.com>
@lance6716 lance6716 force-pushed the lance/txn-delete-support branch from 37b3a4f to 76845ad Compare May 28, 2026 15:16
@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Jun 30, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-06-30 13:42:49.569803364 +0000 UTC m=+133311.270182767: ☑️ agreed by gengliqi.

@ti-chi-bot

ti-chi-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gengliqi

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 Jun 30, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/test/region_split_test.cc (1)

106-129: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a direct deldel same-key case.

This test covers setdel and delset, but not two consecutive del() calls on the same key. Since delete mutations now carry no value, that exact overwrite path is worth pinning down in this suite.

Possible addition
     {
         Txn txn(test_cluster.get());
         txn.set("delete_test_key_2", "v1");
         txn.del("delete_test_key_2");
+        txn.del("delete_test_key_2");
         auto buffered_result = txn.get("delete_test_key_2");
         ASSERT_FALSE(buffered_result.second);
         ASSERT_EQ(buffered_result.first, "");
         txn.commit();
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/region_split_test.cc` around lines 106 - 129, Add a direct same-key
delete-over-delete case to the transaction test in region_split_test.cc,
alongside the existing buffered mutation checks in the Txn/Snapshot flow. Extend
the test around the current delete/set scenarios to create a Txn, call del()
twice on the same key, verify txn.get() reflects a pending delete after the
second call, and commit to confirm the overwrite path behaves correctly. Use the
existing Txn and Snapshot patterns in this test to keep the coverage consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ci/build-test.sh`:
- Around line 32-34: The mock-tikv shutdown in build-test.sh is conditional on
make test succeeding, so cleanup can be skipped when the script exits early
under set -e. Move the kill of $mock_kv_pid into an EXIT trap immediately after
the mock-tikv process is started, and keep the existing test run in the main
flow so the cleanup always runs regardless of success or failure.

---

Nitpick comments:
In `@src/test/region_split_test.cc`:
- Around line 106-129: Add a direct same-key delete-over-delete case to the
transaction test in region_split_test.cc, alongside the existing buffered
mutation checks in the Txn/Snapshot flow. Extend the test around the current
delete/set scenarios to create a Txn, call del() twice on the same key, verify
txn.get() reflects a pending delete after the second call, and commit to confirm
the overwrite path behaves correctly. Use the existing Txn and Snapshot patterns
in this test to keep the coverage consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f694a5be-bbd4-4791-988e-b1f6d4804685

📥 Commits

Reviewing files that changed from the base of the PR and between 06a5e0b and 2e801e2.

📒 Files selected for processing (5)
  • ci/build-test.sh
  • include/pingcap/kv/2pc.h
  • include/pingcap/kv/Txn.h
  • src/kv/2pc.cc
  • src/test/region_split_test.cc
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/kv/2pc.cc
  • include/pingcap/kv/2pc.h
  • include/pingcap/kv/Txn.h

Comment thread ci/build-test.sh
Comment on lines 32 to 34
cd "$build_dir" && make test

kill -9 $mock_kv_pid

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Inspect cleanup flow in ci/build-test.sh"
sed -n '1,80p' ci/build-test.sh

echo
echo "Search CI scripts for trap-based background-process cleanup patterns"
rg -n 'trap .*EXIT|kill -9 .*mock|nohup .*mock-tikv' ci

Repository: tikv/client-c

Length of output: 1085


Make mock-tikv cleanup unconditional.
kill -9 $mock_kv_pid only runs if make test succeeds; with set -e, a test failure exits before cleanup, leaving mock-tikv running. Move it into an EXIT trap right after startup.

Suggested fix
 nohup /mock-tikv/bin/mock-tikv &
 mock_kv_pid=$!
+trap 'kill -9 "$mock_kv_pid" >/dev/null 2>&1 || true' EXIT
@@
-cd "$build_dir" && make test
-
-kill -9 $mock_kv_pid
+cd "$build_dir" && make test
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/build-test.sh` around lines 32 - 34, The mock-tikv shutdown in
build-test.sh is conditional on make test succeeding, so cleanup can be skipped
when the script exits early under set -e. Move the kill of $mock_kv_pid into an
EXIT trap immediately after the mock-tikv process is started, and keep the
existing test run in the main flow so the cleanup always runs regardless of
success or failure.

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. needs-1-more-lgtm Indicates a PR needs 1 more 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