Skip to content

kafka: unify sink errors and replace failpoint tests - #5786

Merged
ti-chi-bot[bot] merged 7 commits into
pingcap:masterfrom
3AceShowHand:kafka-unify-error
Jul 28, 2026
Merged

kafka: unify sink errors and replace failpoint tests#5786
ti-chi-bot[bot] merged 7 commits into
pingcap:masterfrom
3AceShowHand:kafka-unify-error

Conversation

@3AceShowHand

@3AceShowHand 3AceShowHand commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

What problem does this PR solve?

Kafka sink errors are overly fine-grained and inconsistently wrapped. Some propagation paths add multiple TiCDC error codes, lose the original cause, or use an error category owned by another sink. This makes retry classification and troubleshooting harder.

Kafka producer failure tests also rely on failpoints even when the behavior can be covered by focused unit tests and real Kafka failures.

Issue Number: close #5790

What is changed and how it works?

  • Consolidate configuration errors into ErrKafkaInvalidConfig.
  • Consolidate Admin API errors into ErrKafkaAdminAPI.
  • Consolidate producer send errors into ErrKafkaSendMessage.
  • Add ErrNewKafkaSink and ErrKafkaSinkClosed, and delete superseded Kafka error definitions.
  • Wrap third-party errors once where their semantic category is first known; upper layers return them directly.
  • Preserve original causes and propagate context cancellation without extra wrapping.
  • Classify external storage and marshal failures at their owning boundaries.
  • Correct the Pulsar producer creation error category.

The Kafka failpoints are removed without dropping their behavioral coverage:

  • KafkaSinkAsyncSendError: replaced by a real broker-rejection scenario in kafka_big_messages. The producer starts with a large topic limit, the test lowers the broker-side topic limit, and Kafka rejects an already-enqueued message through Sarama Errors(). The test checks ErrKafkaSendMessage, warning-to-normal recovery, replay, and final data consistency.
  • Kafka sink unit coverage verifies that an AsyncRunCallback error makes sink.Run return the error and mark the sink abnormal without depending on Sarama.
  • KafkaSinkSyncSendMessageError: single-message failure, cause preservation, and single ErrKafkaSendMessage wrapping are covered by TestSyncProducerErrorWrappedOnce.
  • KafkaSinkSyncSendMessagesError: batch failure, cause preservation, and single ErrKafkaSendMessage wrapping are covered by TestSyncProducerErrorWrappedOnce.
  • DML, DDL, and checkpoint log context previously checked by the failpoint integration test is covered by focused BuildEventLogContext unit tests.

Check List

Tests

  • Unit test
  • Integration test

The Kafka integration scenario requires the repository Linux test environment and is left for CI; local unit tests, shell validation, and static checks pass on macOS/ARM.

Questions

Will it cause performance regression or break compatibility?

No performance regression is expected. This PR intentionally removes obsolete exported Kafka error variables and changes affected RFC codes and messages; compatibility aliases are not retained.

Do you need to update user documentation, design documentation or monitoring documentation?

No user-facing documentation or monitoring changes are required.

Release note

None

Summary by CodeRabbit

  • Bug Fixes

    • Improved Kafka and Pulsar sink error reporting for clearer configuration, connection, administration, and message-delivery failures.
    • Invalid Kafka settings and topic expressions now consistently report configuration errors.
    • Kafka topic and broker settings now distinguish missing configuration from administration failures and use safe fallback behavior.
    • Sending messages after a sink closes now returns a consistent closed-sink error.
    • External storage and Pulsar producer failures now use more accurate error classifications.
  • Tests

    • Expanded coverage for asynchronous delivery failures, closed sinks, configuration errors, and topic administration scenarios.
    • Updated integration coverage for asynchronous message-size failures and Pulsar sink recovery.

@ti-chi-bot ti-chi-bot Bot added do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@3AceShowHand, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7128e087-96fe-4262-aaec-098904982e34

📥 Commits

Reviewing files that changed from the base of the PR and between 4438456 and c9e57f1.

📒 Files selected for processing (2)
  • pkg/sink/kafka/sarama_config.go
  • pkg/sink/kafka/sarama_config_test.go
📝 Walkthrough

Walkthrough

Kafka sink errors are consolidated around configuration, admin, producer, and sink-level classifications. Admin configuration lookups now report presence explicitly, while producer, sink, topic-manager, claim-check, and integration tests follow the revised contracts.

Changes

Kafka error taxonomy and producer runtime

Layer / File(s) Summary
Error taxonomy and producer runtime
pkg/errors/*, pkg/sink/kafka/sarama_*.go, pkg/sink/kafka/logutil*, pkg/util/external_storage.go, downstreamadapter/sink/eventrouter/topic/*
Kafka error sentinels, configuration validation, producer close/send handling, cancellation propagation, codec types, external-storage errors, and topic-expression validation use the revised classifications.

Admin configuration contract and option resolution

Layer / File(s) Summary
Admin configuration contract and option resolution
pkg/sink/kafka/admin*, pkg/sink/kafka/cluster_admin_client*, pkg/sink/kafka/options*
Broker and topic configuration methods return (value, found, error), admin failures use ErrKafkaAdminAPI, missing settings fall back through option resolution, and validation errors use ErrKafkaInvalidConfig.

Sink and topic-manager propagation

Layer / File(s) Summary
Sink and topic-manager propagation
downstreamadapter/sink/kafka/*, downstreamadapter/sink/topicmanager/*, downstreamadapter/sink/pulsar/helper.go, pkg/sink/kafka/claimcheck/*
Sink verification, construction, topic creation, producer factories, claim-check storage, Pulsar producer creation, and related tests propagate the updated errors and type contracts.

Integration scenario updates

Layer / File(s) Summary
Integration scenario updates
tests/integration_tests/*
Kafka asynchronous-send coverage, Pulsar-only MQ error-resume coverage, HTTP error expectations, and CI test membership are updated.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

  • pingcap/ticdc#5715: Changes related topic validation, auto-creation, and encoder-initialization paths in the same sink verification flow.

Suggested labels: lgtm

Suggested reviewers: hongyunyan, wk989898, asddongmen

Poem

I’m a rabbit with errors neatly tied,
Kafka labels hop side by side.
Admin configs say “found” or “no,”
Sink paths tell the truth as they go.
Tests nibble bugs beneath the moon.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.15% 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
Title check ✅ Passed The title is concise and accurately summarizes the main changes: Kafka sink error unification and failpoint test replacement.
Description check ✅ Passed The description matches the template: problem, issue number, changes, tests, questions, and release note are all present.
Linked Issues check ✅ Passed The changes address #5790 by consolidating Kafka errors, adjusting wrapping/cancellation, and replacing failpoint coverage with focused tests.
Out of Scope Changes check ✅ Passed The non-Kafka edits are still tied to the same error-classification and test-migration work, with no clearly unrelated changes evident.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@pkg/sink/kafka/sarama_factory.go`:
- Around line 125-127: Close the previously created client before returning from
both producer-construction failure paths: the sarama.NewSyncProducerFromClient
call at pkg/sink/kafka/sarama_factory.go:125-127 and the
sarama.NewAsyncProducerFromClient call at
pkg/sink/kafka/sarama_factory.go:152-154. Preserve the existing wrapped error
returns after performing the cleanup.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0de4272f-86ca-4b46-9a28-e301df7632e1

📥 Commits

Reviewing files that changed from the base of the PR and between 0d49297 and e2d01a2.

📒 Files selected for processing (21)
  • downstreamadapter/sink/eventrouter/topic/expression.go
  • downstreamadapter/sink/eventrouter/topic/expression_test.go
  • downstreamadapter/sink/kafka/helper.go
  • downstreamadapter/sink/kafka/sink.go
  • downstreamadapter/sink/pulsar/helper.go
  • downstreamadapter/sink/topicmanager/kafka_topic_manager.go
  • downstreamadapter/sink/topicmanager/kafka_topic_manager_test.go
  • pkg/errors/error.go
  • pkg/errors/error_test.go
  • pkg/sink/kafka/admin.go
  • pkg/sink/kafka/admin_test.go
  • pkg/sink/kafka/cluster_admin_client.go
  • pkg/sink/kafka/cluster_admin_client_mock.go
  • pkg/sink/kafka/options.go
  • pkg/sink/kafka/options_test.go
  • pkg/sink/kafka/sarama_async_producer.go
  • pkg/sink/kafka/sarama_config.go
  • pkg/sink/kafka/sarama_factory.go
  • pkg/sink/kafka/sarama_sync_producer.go
  • pkg/sink/kafka/sarama_sync_producer_test.go
  • tests/integration_tests/http_api/util/test_case.py

Comment thread pkg/sink/kafka/sarama_factory.go
@3AceShowHand 3AceShowHand changed the title kafka: unify errors kafka: simplify and unify sink errors Jul 28, 2026
@ti-chi-bot ti-chi-bot Bot added release-note-none Denotes a PR that doesn't merit a release note. and removed do-not-merge/needs-linked-issue release-note Denotes a PR that will be considered when it comes time to generate release notes. labels Jul 28, 2026
@3AceShowHand 3AceShowHand changed the title kafka: simplify and unify sink errors kafka: unify sink errors and replace failpoint tests Jul 28, 2026
@ti-chi-bot ti-chi-bot Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 28, 2026
@3AceShowHand

Copy link
Copy Markdown
Collaborator Author

/test all

@3AceShowHand

Copy link
Copy Markdown
Collaborator Author

/test all

@ti-chi-bot ti-chi-bot Bot added needs-1-more-lgtm Indicates a PR needs 1 more LGTM. approved labels Jul 28, 2026
@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Jul 28, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-07-28 06:59:58.006194751 +0000 UTC m=+1906584.042289807: ☑️ agreed by asddongmen.
  • 2026-07-28 07:32:46.362876159 +0000 UTC m=+1908552.398971215: ☑️ agreed by hongyunyan.

@3AceShowHand

Copy link
Copy Markdown
Collaborator Author

/test all

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/integration_tests/mq_sink_error_resume/run.sh (1)

26-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Quote variable expansions flagged by shellcheck.

$WORK_DIR, $CDC_BINARY, $pd_addr, and $SINK_URI are unquoted on these lines, risking globbing/word-splitting.

🔧 Suggested fix
-	run_pulsar_cluster $WORK_DIR normal
+	run_pulsar_cluster "$WORK_DIR" normal
 	SINK_URI="pulsar://127.0.0.1:6650/$TOPIC_NAME?protocol=canal-json&enable-tidb-extension=true"
 	# Return one failpoint error to fail the changefeed.
 	# Note we return one error for the failpoint, if owner retry changefeed frequently, it may break the test.
 	export GO_FAILPOINTS='github.com/pingcap/ticdc/downstreamadapter/sink/pulsar/PulsarSinkAsyncSendError=1*return(true)'
-	run_cdc_server --workdir $WORK_DIR --binary $CDC_BINARY --addr "127.0.0.1:8300" --pd $pd_addr
+	run_cdc_server --workdir "$WORK_DIR" --binary "$CDC_BINARY" --addr "127.0.0.1:8300" --pd "$pd_addr"
-	changefeed_id=$(cdc_cli_changefeed create --pd=$pd_addr --sink-uri="$SINK_URI" | grep '^ID:' | head -n1 | awk '{print $2}')
+	changefeed_id=$(cdc_cli_changefeed create --pd="$pd_addr" --sink-uri="$SINK_URI" | grep '^ID:' | head -n1 | awk '{print $2}')
-	run_pulsar_consumer --upstream-uri $SINK_URI
+	run_pulsar_consumer --upstream-uri "$SINK_URI"
🤖 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 `@tests/integration_tests/mq_sink_error_resume/run.sh` around lines 26 - 33,
Quote the variable expansions in the integration test commands using WORK_DIR,
CDC_BINARY, pd_addr, and SINK_URI, including the run_cdc_server,
cdc_cli_changefeed, and run_pulsar_consumer invocations, to prevent shell
globbing and word splitting while preserving the existing command behavior.

Source: Linters/SAST tools

pkg/sink/kafka/sarama_sync_producer.go (1)

58-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate log+wrap logic; verify logging guideline compliance.

SendMessage and SendMessages repeat the same log.Error(...) block (keyspace/changefeed/eventContext fields) before wrapping with errors.ErrKafkaSendMessage. Consider extracting a small helper (e.g. p.logAndWrapSendError(err, message)) to avoid field drift between the two call sites.

Separately, this introduces a new structured log call and removes the prior failpoint-based error injection — worth double-checking against the repo's logging conventions (log level, field set, avoiding duplicate logging if the caller in downstreamadapter/sink/kafka/sink.go also logs on the same failure path).

♻️ Suggested helper extraction
+func (p *saramaSyncProducer) logAndWrapSendError(err error, message *codecCommon.Message) error {
+	log.Error("send message to kafka failed",
+		zap.String("keyspace", p.id.Keyspace()),
+		zap.String("changefeed", p.id.Name()),
+		zap.String("eventContext", BuildEventLogContext(p.id.Keyspace(), p.id.Name(), message.LogInfo)),
+		zap.Error(err))
+	return errors.WrapError(errors.ErrKafkaSendMessage, err)
+}
+
 func (p *saramaSyncProducer) SendMessage(topic string, partitionNum int32, message *codecCommon.Message) error {
 	...
 	_, _, err := p.producer.SendMessage(msg)
 	if err == nil {
 		return nil
 	}
-	log.Error("send message to kafka failed",
-		zap.String("keyspace", p.id.Keyspace()),
-		zap.String("changefeed", p.id.Name()),
-		zap.String("eventContext", BuildEventLogContext(p.id.Keyspace(), p.id.Name(), message.LogInfo)),
-		zap.Error(err))
-	return errors.WrapError(errors.ErrKafkaSendMessage, err)
+	return p.logAndWrapSendError(err, message)
 }

As per coding guidelines: "Logs are operational signals; see docs/agents/logging.md before adding, removing, or rewriting logs."

Also applies to: 84-92

🤖 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 `@pkg/sink/kafka/sarama_sync_producer.go` around lines 58 - 67, The SendMessage
and SendMessages paths duplicate Kafka send-error logging and wrapping, with
potential logging-convention or duplicate-log issues. Extract shared handling
into a helper such as logAndWrapSendError using the existing keyspace,
changefeed, eventContext, and ErrKafkaSendMessage behavior, then verify it
complies with the repository logging guidance and does not duplicate caller
logging.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@pkg/sink/kafka/sarama_sync_producer.go`:
- Around line 58-67: The SendMessage and SendMessages paths duplicate Kafka
send-error logging and wrapping, with potential logging-convention or
duplicate-log issues. Extract shared handling into a helper such as
logAndWrapSendError using the existing keyspace, changefeed, eventContext, and
ErrKafkaSendMessage behavior, then verify it complies with the repository
logging guidance and does not duplicate caller logging.

In `@tests/integration_tests/mq_sink_error_resume/run.sh`:
- Around line 26-33: Quote the variable expansions in the integration test
commands using WORK_DIR, CDC_BINARY, pd_addr, and SINK_URI, including the
run_cdc_server, cdc_cli_changefeed, and run_pulsar_consumer invocations, to
prevent shell globbing and word splitting while preserving the existing command
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ce5d84ab-2bf2-416c-9863-fe6442613c8d

📥 Commits

Reviewing files that changed from the base of the PR and between e2d01a2 and 4438456.

📒 Files selected for processing (23)
  • downstreamadapter/sink/kafka/helper.go
  • downstreamadapter/sink/kafka/sink.go
  • downstreamadapter/sink/kafka/sink_test.go
  • downstreamadapter/sink/pulsar/helper.go
  • pkg/sink/kafka/admin_test.go
  • pkg/sink/kafka/claimcheck/claim_check.go
  • pkg/sink/kafka/claimcheck/claim_check_test.go
  • pkg/sink/kafka/logutil.go
  • pkg/sink/kafka/logutil_test.go
  • pkg/sink/kafka/oauth2_token_provider.go
  • pkg/sink/kafka/oauth2_token_provider_test.go
  • pkg/sink/kafka/options_test.go
  • pkg/sink/kafka/sarama_async_producer.go
  • pkg/sink/kafka/sarama_factory.go
  • pkg/sink/kafka/sarama_sync_producer.go
  • pkg/sink/kafka/sarama_sync_producer_test.go
  • pkg/util/external_storage.go
  • tests/integration_tests/http_api/util/test_case.py
  • tests/integration_tests/kafka_big_messages/run.sh
  • tests/integration_tests/kafka_log_info/run.sh
  • tests/integration_tests/mq_sink_error_resume/run.sh
  • tests/integration_tests/run_heavy_it_in_ci.sh
  • tests/integration_tests/run_light_it_in_ci.sh
💤 Files with no reviewable changes (1)
  • tests/integration_tests/kafka_log_info/run.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/integration_tests/http_api/util/test_case.py
  • pkg/sink/kafka/sarama_factory.go
  • pkg/sink/kafka/options_test.go

@ti-chi-bot

ti-chi-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: asddongmen, hongyunyan, wk989898

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:
  • OWNERS [asddongmen,hongyunyan,wk989898]

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

@3AceShowHand

Copy link
Copy Markdown
Collaborator Author

/retest

@ti-chi-bot
ti-chi-bot Bot merged commit fa340f1 into pingcap:master Jul 28, 2026
25 checks passed
@3AceShowHand

Copy link
Copy Markdown
Collaborator Author

/cherry-pick release-8.5

@ti-chi-bot

Copy link
Copy Markdown
Member

@3AceShowHand: new pull request created to branch release-8.5: #5815.
But this PR has conflicts, please resolve them!

Details

In response to this:

/cherry-pick release-8.5

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note-none Denotes a PR that doesn't merit a release note. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

kafka: simplify and unify sink errors

5 participants