Skip to content

eventservice: optimize changefeed low-latency scheduling - #5900

Merged
ti-chi-bot[bot] merged 32 commits into
pingcap:masterfrom
asddongmen:agent/changefeed-level-low-latency-eventservice
Aug 12, 2026
Merged

eventservice: optimize changefeed low-latency scheduling#5900
ti-chi-bot[bot] merged 32 commits into
pingcap:masterfrom
asddongmen:agent/changefeed-level-low-latency-eventservice

Conversation

@asddongmen

@asddongmen asddongmen commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

What problem does this PR solve?

Issue Number: close #5705

Latency-sensitive changefeeds need EventService to advance and deliver resolved
timestamps without periodic scheduling delays. This is Part 2 of the
changefeed-level low-latency feature; #5862 provides the persisted mode and
control-plane propagation consumed here.

What is changed and how it works?

  • Isolate EventStore subscription reuse by performance mode and use immediate
    LogPuller resolved-ts advancement for low-latency subscriptions.
  • Serialize dispatcher scan scheduling with explicit states, fast-path
    no-event resolved notifications, and coalesced continuation after active
    scans.
  • Retry SchemaStore-blocked scans for low-latency changefeeds while preserving
    bounded worker queues and eventual recovery.
  • Register active-scan lifecycle state only when a worker actually scans, and
    expose dropped scheduling attempts through an EventService metric.

Check List

Tests

  • Unit test
  • Manual test (combined Part 1 + Part 2: three captures, concurrent
    low-latency/throughput changefeeds with 100k tables each, 200k isolated
    subscriptions, about 20 MB/s shared traffic for 30 minutes; both feeds
    remained normal)

Questions

Will it cause performance regression or break compatibility?

Throughput behavior remains unchanged. Low-latency mode performs more eager
frontier and scan scheduling; opposite modes intentionally do not share
EventStore subscriptions.

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

Yes. The changefeed performance-mode option introduced by #5862 needs user
documentation. The dropped-task metric is diagnostic and does not change
existing metric names.

Release note

Add low-latency EventService scheduling and mode-isolated EventStore
subscriptions for changefeeds.

Summary by CodeRabbit

  • New Features

    • Added per-changefeed low-latency mode for faster event delivery and progress reporting.
    • Added automatic retries for scans blocked by schema changes.
    • Added resilient scan scheduling with coalescing, queue recovery, and lifecycle tracking.
    • Added monitoring for scan tasks dropped when capacity is full.
  • Bug Fixes

    • Improved scan cancellation, reset recovery, and dispatcher state handling.
    • Kept standard and low-latency subscriptions isolated.
  • Documentation

    • Added design documentation covering low-latency behavior, compatibility, and testing.

Keep the low-latency mode focused on setting the logpuller advance interval to zero. Remove the additional batched heap update path and its helper after the 10k-region E2E test showed comparable mean and p95 latency without it.
Replace the periodic schema-capped scan retry with applied SchemaStore notifications. Serialize dispatcher scan scheduling with a short-lock state machine and coalesce worker continuations without dropping queued work.
Keep no-DML/no-DDL resolved notifications out of the scan worker queue while preserving dispatcher scan ownership. Gate continuation and schema-blocked recovery on low-latency mode, and cover queue-full recovery with a dropped-task metric.
Publish LogCoordinator resolved lag only from complete node-report rounds and calculate it at each node's report time. Preserve Maintainer watermark ordering, expose checkpoint/resolved lag atomically, and update dashboards to use the paired metrics.
Restore the unrelated Maintainer metric collector, watermark state, and dashboard changes. Keep this follow-up scoped to LogCoordinator owner resolved-ts lag calculation and its tests.
Keep the first changefeed-level low-latency PR free of pkg/eventservice changes. Move the coupled EventStore subscription isolation and EventService dropped-task metric into the follow-up part as well so both trees compile independently.
Use changefeed mode to isolate EventStore subscriptions and select immediate resolved-ts advancement. Add the EventService scan state machine, resolved-notification fast path, low-latency continuation and schema-blocked retry, deferred active-scan lifecycle, and focused coverage.
@ti-chi-bot

ti-chi-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b7332870-87d6-4aba-a325-08e1314259b2

📥 Commits

Reviewing files that changed from the base of the PR and between 2474e1f and 8c0100f.

📒 Files selected for processing (2)
  • logservice/eventstore/event_store.go
  • logservice/eventstore/event_store_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • logservice/eventstore/event_store.go
  • logservice/eventstore/event_store_test.go

📝 Walkthrough

Walkthrough

The PR adds per-changefeed low-latency mode. It propagates the mode through EventService and EventStore, isolates subscriptions by mode, introduces dispatcher scan states, and adds schema-blocked retry and queue-recovery handling.

Changes

Low-latency changefeed processing

Layer / File(s) Summary
Mode propagation and subscription isolation
docs/design/..., logservice/eventstore/*, pkg/eventservice/event_service.go, pkg/eventservice/event_service_test.go, pkg/eventservice/event_broker.go
Low-latency mode is added to dispatcher registration and status. EventStore separates subscriptions by mode and uses a zero resolved-ts advance interval for low-latency subscriptions.
Dispatcher scan state machine
pkg/eventservice/dispatcher_stat.go, pkg/eventservice/metrics_collector.go
Dispatcher scans use explicit queued, running, pending, schema-blocked, and removed states. Busy-state reporting replaces the atomic scan flag.
Broker scheduling and recovery
pkg/eventservice/event_broker.go, pkg/eventservice/event_broker_test.go, pkg/metrics/event_service.go
EventBroker adds immediate and coalesced scan scheduling, schema-blocked retries, reset cleanup, queue-full recovery, and a dropped scan task metric. Tests cover the new scan lifecycles and recovery paths.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EventBroker
  participant Dispatcher
  participant EventStore
  participant SchemaStore
  EventBroker->>Dispatcher: request scan
  Dispatcher->>EventBroker: claim scan state
  EventBroker->>EventStore: scan event range
  EventStore-->>EventBroker: return progress
  EventBroker->>SchemaStore: check schema frontier
  SchemaStore-->>EventBroker: return schema state
  EventBroker->>Dispatcher: complete or schedule continuation
Loading

Possibly related PRs

  • pingcap/ticdc#5554: Both modify pkg/eventservice/event_broker.go dispatcher scan and reset behavior.

Poem

A rabbit tracks each scan in flight,
Low-latency paths advance just right.
Schema blocks, then retries start,
Queues recover and states stay smart.
Progress moves through day and night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.04% 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 clearly summarizes the main change: optimizing EventService scheduling for changefeed low-latency mode.
Description check ✅ Passed The description includes the issue, implementation details, tests, compatibility impact, documentation needs, and release note.
Linked Issues check ✅ Passed The changes address the linked issue objectives for low-latency propagation, bounded scan scheduling, schema-blocked recovery, compatibility, and validation [#5705].
Out of Scope Changes check ✅ Passed The code, tests, design documentation, and metric changes are related to the low-latency EventService objectives.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 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.

@asddongmen
asddongmen changed the base branch from agent/changefeed-level-low-latency-core to master August 7, 2026 05:57
@asddongmen
asddongmen marked this pull request as ready for review August 7, 2026 05:57
@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 Aug 7, 2026
@asddongmen

Copy link
Copy Markdown
Collaborator Author

/test

@ti-chi-bot

ti-chi-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

@asddongmen: The /test command needs one or more targets.
The following commands are available to trigger required jobs:

/test pull-build
/test pull-build-next-gen
/test pull-cdc-kafka-integration-heavy
/test pull-cdc-kafka-integration-heavy-next-gen
/test pull-cdc-kafka-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-kafka-integration-light
/test pull-cdc-kafka-integration-light-next-gen
/test pull-cdc-kafka-integration-light-next-gen-legacy-safepoint
/test pull-cdc-mysql-integration-heavy
/test pull-cdc-mysql-integration-heavy-next-gen
/test pull-cdc-mysql-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-mysql-integration-light
/test pull-cdc-mysql-integration-light-next-gen
/test pull-cdc-mysql-integration-light-next-gen-legacy-safepoint
/test pull-cdc-pulsar-integration-heavy-next-gen
/test pull-cdc-pulsar-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-pulsar-integration-light-next-gen-legacy-safepoint
/test pull-cdc-storage-integration-heavy
/test pull-cdc-storage-integration-heavy-next-gen
/test pull-cdc-storage-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-storage-integration-light
/test pull-cdc-storage-integration-light-next-gen
/test pull-cdc-storage-integration-light-next-gen-legacy-safepoint
/test pull-check
/test pull-error-log-review
/test pull-unit-test
/test pull-unit-test-next-gen

The following commands are available to trigger optional jobs:

/test pull-cdc-mysql-integration-heavy-v7-5
/test pull-cdc-mysql-integration-heavy-v8-1
/test pull-cdc-mysql-integration-light-v7-5
/test pull-cdc-mysql-integration-light-v8-1
/test pull-cdc-pulsar-integration-heavy
/test pull-cdc-pulsar-integration-light
/test pull-cdc-pulsar-integration-light-next-gen

Use /test all to run the following jobs that were automatically triggered:

pull-error-log-review
Details

In response to this:

/test

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 kubernetes-sigs/prow repository.

@asddongmen

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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
pkg/eventservice/event_broker.go (1)

774-790: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Clear interrupted when the scan returns an error.

scanner.scan can set interrupted and return a non-nil err in the same call. The function then returns at Line 789 with interrupted still true. The deferred finishScan treats that as an interrupted scan and calls tryEnqueueScanLocked, so the dispatcher is re-queued immediately.

If the error is persistent, for example a repeated SchemaStore or EventStore failure, this forms a tight loop with no backoff: enqueue, scan, error, enqueue. The loop occupies one scan worker continuously and repeats the error log at Line 784.

Set interrupted to false on the error path so the dispatcher returns to dispatcherScanIdle and waits for the next notification.

🐛 Proposed fix
 	if err != nil {
+		// A failed scan must not be treated as an interrupted scan. Otherwise
+		// finishScan re-queues the dispatcher immediately and a persistent
+		// error becomes a tight retry loop.
+		interrupted = false
 		releaseQuota(available, uint64(sl.maxDMLBytes))
 		if task.isRemoved.Load() {
 			return
 		}
🤖 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/eventservice/event_broker.go` around lines 774 - 790, In the error branch
after scanner.scan returns, explicitly set interrupted to false before returning
so deferred finishScan does not re-enqueue the dispatcher. Update the err
handling block in the surrounding scan flow while preserving the existing quota
release, removal check, and error logging behavior.
🧹 Nitpick comments (7)
pkg/eventservice/metrics_collector.go (1)

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

Rename the log key to match the reported state.

isScanBusy() returns true for dispatcherScanQueued, dispatcherScanRunning, and dispatcherScanRunningPending. The key isTaskScanning states that an EventStore scan is in progress. That is now inaccurate for a queued dispatcher.

Rename the key so the log matches the scheduler state it reports.

♻️ Proposed change
-			zap.Bool("isTaskScanning", dispatcher.isScanBusy()),
+			zap.Bool("isScanBusy", dispatcher.isScanBusy()),

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

🤖 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/eventservice/metrics_collector.go` at line 340, Rename the zap log key in
the metrics collection code from isTaskScanning to a name that accurately
represents dispatcher.isScanBusy(), including queued, running, and pending scan
states; keep the existing state value and logging behavior unchanged.

Source: Coding guidelines

pkg/eventservice/event_broker.go (1)

1230-1234: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Log the SchemaStore error in the retry loop.

The loop marks the bucket dirty and skips the keyspace when GetTableDDLEventState fails. It emits no signal. A persistent SchemaStore failure then parks every low-latency dispatcher in that keyspace silently, and the only visible symptom is rising resolved-ts lag.

The ticker fires every 50 ms, so log at a rate-limited or debug level rather than on every failure.

♻️ Proposed change
 		ddlState, err := c.schemaStore.GetTableDDLEventState(keyspaceMeta, d.info.GetTableSpan().TableID)
 		if err != nil {
+			log.Debug("get table ddl event state failed in schema-blocked retry",
+				zap.Uint32("keyspaceID", keyspaceMeta.ID),
+				zap.Int64("tableID", d.info.GetTableSpan().TableID),
+				zap.Error(err))
 			bucket.dirty.Store(true)
 			return true
 		}

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

🤖 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/eventservice/event_broker.go` around lines 1230 - 1234, In the retry loop
around GetTableDDLEventState, record the returned SchemaStore error before
marking bucket.dirty and returning, using the repository’s approved rate-limited
or debug logging mechanism so failures are observable without emitting a log on
every 50 ms retry.

Source: Coding guidelines

logservice/eventstore/event_store_test.go (1)

282-286: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Derive the throughput interval from the server config.

The test hardcodes 100 as the throughput advance interval. That value comes from the default KVClient.AdvanceIntervalInMs. If the default changes, this test fails with an unclear reason. Read the configured value instead.

♻️ Proposed change
 			intervals := make(map[int64]int)
 			for _, subscription := range mockSubClient.subscriptions {
 				intervals[subscription.advanceInterval]++
 			}
-			require.Equal(t, map[int64]int{0: 1, 100: 1}, intervals)
+			throughputInterval := int64(config.GetGlobalServerConfig().KVClient.AdvanceIntervalInMs)
+			require.Equal(t, map[int64]int{0: 1, throughputInterval: 1}, intervals)

As per path instructions for **/*_test.go: "Prefer focused deterministic tests".

🤖 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 `@logservice/eventstore/event_store_test.go` around lines 282 - 286, Replace
the hardcoded 100 in the intervals assertion with the configured throughput
advance interval from the server or KVClient configuration used by this test.
Keep the expected interval counts unchanged and reference the existing
configuration symbol so the test remains deterministic when the default changes.

Source: Path instructions

pkg/metrics/event_service.go (1)

159-165: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider a reason label for the dropped-scan counter.

tryEnqueueScanLocked is called from four distinct paths in pkg/eventservice/event_broker.go: the internal request path at Line 1124, the interrupted-scan path at Line 1161, the low-latency continuation path at Line 1174, and the schema-retry path at Line 1256. The counter aggregates all four into one number.

A reason label would show which scheduling path saturates the worker queue. That distinction matters during triage, because the schema-retry path self-recovers on the next tick while the continuation path waits for the next EventStore notification.

The metric name follows the existing _count convention used by the neighboring counters in this file, so no rename is needed.

🤖 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/metrics/event_service.go` around lines 159 - 165, Add a reason label to
EventServiceDroppedScanTaskCount and update tryEnqueueScanLocked call sites to
pass distinct labels for the internal request, interrupted-scan, low-latency
continuation, and schema-retry paths. Ensure each dropped-task increment uses
the corresponding reason while preserving the existing metric name and count
behavior.
pkg/eventservice/event_broker_test.go (2)

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

Set scanState under scanMu in tests.

These lines write disp.scanState directly without holding disp.scanMu. Production code always mutates scanState under that mutex. The writes are currently safe because no other goroutine touches the dispatcher at these points, so -race stays clean.

Adding the lock keeps the test setup consistent with the invariant and stays correct if a future test adds a concurrent goroutine. Alternatively, add a small test helper such as setScanStateForTest.

As per path instructions for **/*_test.go: "Prefer focused deterministic tests".

Also applies to: 680-680, 713-713, 1055-1055

🤖 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/eventservice/event_broker_test.go` at line 385, Protect every direct test
assignment to disp.scanState with disp.scanMu, including the occurrences near
lines 385, 680, 713, and 1055. Use the existing mutex consistently around each
setup mutation, or introduce and reuse a focused setScanStateForTest helper that
performs the locked update.

Source: Path instructions


469-501: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for a scan that fails with an error.

TestInterruptedScanQueueFullRecoversOnNextNotify covers the interrupted path. No test covers scanner.scan returning both interrupted == true and a non-nil err. That combination drives the re-queue loop described in the pkg/eventservice/event_broker.go comment on Lines 774-790.

Add a case that injects a scan error and asserts the dispatcher settles in dispatcherScanIdle instead of being re-queued. I can generate this test if you want.

As per path instructions for **/*_test.go: "Prefer focused deterministic tests; see docs/agents/testing.md before adding or changing tests."

🤖 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/eventservice/event_broker_test.go` around lines 469 - 501, Add a focused
deterministic test alongside TestInterruptedScanQueueFullRecoversOnNextNotify
that makes scanner.scan return interrupted == true with a non-nil error. Assert
the dispatcher’s scan state settles at dispatcherScanIdle and that the failed
task is not re-queued, covering the error-handling path in the broker scan flow.

Source: Path instructions

logservice/eventstore/event_store.go (1)

695-704: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add the mode to the new-subscription log.

A table can now hold one throughput subscription and one low-latency subscription at the same time. The new subscription created log does not show which mode created the subscription. Add the mode and the applied advance interval. This makes duplicate per-table subscriptions diagnosable from logs alone.

♻️ Proposed log fields
 	log.Info("new subscription created",
 		zap.Stringer("dispatcherID", dispatcherID),
 		zap.Uint64("startTs", startTs),
 		zap.Uint64("subscriptionID", uint64(subStat.subID)),
+		zap.Bool("lowLatencyMode", lowLatencyMode),
+		zap.Int64("resolvedTsAdvanceInterval", resolvedTsAdvanceInterval),
 		zap.String("subSpan", common.FormatTableSpan(subStat.tableSpan)))

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

🤖 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 `@logservice/eventstore/event_store.go` around lines 695 - 704, Update the “new
subscription created” log in the subscription setup flow to include the
subscription mode, distinguishing throughput from low-latency, and the applied
resolved timestamp advance interval from resolvedTsAdvanceInterval. Preserve the
existing fields and use the established mode symbol or representation already
available in this flow.

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.

Inline comments:
In `@pkg/eventservice/event_broker.go`:
- Around line 1106-1108: Update the enqueue in prepareScanFromNotify, used by
advanceResolvedTs, so advancing resolved timestamps never blocks on a saturated
scan worker taskChan. Use a non-blocking enqueue or an intermediate channel
while preserving delivery of resolved-ts work and the existing requestScan
behavior for scan workers.

---

Outside diff comments:
In `@pkg/eventservice/event_broker.go`:
- Around line 774-790: In the error branch after scanner.scan returns,
explicitly set interrupted to false before returning so deferred finishScan does
not re-enqueue the dispatcher. Update the err handling block in the surrounding
scan flow while preserving the existing quota release, removal check, and error
logging behavior.

---

Nitpick comments:
In `@logservice/eventstore/event_store_test.go`:
- Around line 282-286: Replace the hardcoded 100 in the intervals assertion with
the configured throughput advance interval from the server or KVClient
configuration used by this test. Keep the expected interval counts unchanged and
reference the existing configuration symbol so the test remains deterministic
when the default changes.

In `@logservice/eventstore/event_store.go`:
- Around line 695-704: Update the “new subscription created” log in the
subscription setup flow to include the subscription mode, distinguishing
throughput from low-latency, and the applied resolved timestamp advance interval
from resolvedTsAdvanceInterval. Preserve the existing fields and use the
established mode symbol or representation already available in this flow.

In `@pkg/eventservice/event_broker_test.go`:
- Line 385: Protect every direct test assignment to disp.scanState with
disp.scanMu, including the occurrences near lines 385, 680, 713, and 1055. Use
the existing mutex consistently around each setup mutation, or introduce and
reuse a focused setScanStateForTest helper that performs the locked update.
- Around line 469-501: Add a focused deterministic test alongside
TestInterruptedScanQueueFullRecoversOnNextNotify that makes scanner.scan return
interrupted == true with a non-nil error. Assert the dispatcher’s scan state
settles at dispatcherScanIdle and that the failed task is not re-queued,
covering the error-handling path in the broker scan flow.

In `@pkg/eventservice/event_broker.go`:
- Around line 1230-1234: In the retry loop around GetTableDDLEventState, record
the returned SchemaStore error before marking bucket.dirty and returning, using
the repository’s approved rate-limited or debug logging mechanism so failures
are observable without emitting a log on every 50 ms retry.

In `@pkg/eventservice/metrics_collector.go`:
- Line 340: Rename the zap log key in the metrics collection code from
isTaskScanning to a name that accurately represents dispatcher.isScanBusy(),
including queued, running, and pending scan states; keep the existing state
value and logging behavior unchanged.

In `@pkg/metrics/event_service.go`:
- Around line 159-165: Add a reason label to EventServiceDroppedScanTaskCount
and update tryEnqueueScanLocked call sites to pass distinct labels for the
internal request, interrupted-scan, low-latency continuation, and schema-retry
paths. Ensure each dropped-task increment uses the corresponding reason while
preserving the existing metric name and count behavior.
🪄 Autofix

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: 250f1807-45d5-4dbf-9032-394fe0f3a198

📥 Commits

Reviewing files that changed from the base of the PR and between 883ceb8 and dbdc891.

📒 Files selected for processing (10)
  • docs/design/2026-08-07-changefeed-low-latency-eventservice.md
  • logservice/eventstore/event_store.go
  • logservice/eventstore/event_store_test.go
  • pkg/eventservice/dispatcher_stat.go
  • pkg/eventservice/event_broker.go
  • pkg/eventservice/event_broker_test.go
  • pkg/eventservice/event_service.go
  • pkg/eventservice/event_service_test.go
  • pkg/eventservice/metrics_collector.go
  • pkg/metrics/event_service.go

Comment thread pkg/eventservice/event_broker.go
@ti-chi-bot ti-chi-bot Bot added needs-1-more-lgtm Indicates a PR needs 1 more LGTM. approved labels Aug 9, 2026
@lidezhu

lidezhu commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

/test nex-gen

@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown

@lidezhu: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test pull-build
/test pull-build-next-gen
/test pull-cdc-kafka-integration-heavy
/test pull-cdc-kafka-integration-heavy-next-gen
/test pull-cdc-kafka-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-kafka-integration-light
/test pull-cdc-kafka-integration-light-next-gen
/test pull-cdc-kafka-integration-light-next-gen-legacy-safepoint
/test pull-cdc-mysql-integration-heavy
/test pull-cdc-mysql-integration-heavy-next-gen
/test pull-cdc-mysql-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-mysql-integration-light
/test pull-cdc-mysql-integration-light-next-gen
/test pull-cdc-mysql-integration-light-next-gen-legacy-safepoint
/test pull-cdc-pulsar-integration-heavy-next-gen
/test pull-cdc-pulsar-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-pulsar-integration-light-next-gen-legacy-safepoint
/test pull-cdc-storage-integration-heavy
/test pull-cdc-storage-integration-heavy-next-gen
/test pull-cdc-storage-integration-heavy-next-gen-legacy-safepoint
/test pull-cdc-storage-integration-light
/test pull-cdc-storage-integration-light-next-gen
/test pull-cdc-storage-integration-light-next-gen-legacy-safepoint
/test pull-check
/test pull-error-log-review
/test pull-unit-test
/test pull-unit-test-next-gen

The following commands are available to trigger optional jobs:

/test pull-cdc-mysql-integration-heavy-v7-5
/test pull-cdc-mysql-integration-heavy-v8-1
/test pull-cdc-mysql-integration-light-v7-5
/test pull-cdc-mysql-integration-light-v8-1
/test pull-cdc-pulsar-integration-heavy
/test pull-cdc-pulsar-integration-light
/test pull-cdc-pulsar-integration-light-next-gen

Use /test all to run the following jobs that were automatically triggered:

pull-error-log-review
Details

In response to this:

/test nex-gen

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 kubernetes-sigs/prow repository.

Comment thread pkg/eventservice/event_broker.go
Comment thread pkg/eventservice/event_broker.go Outdated
@ti-chi-bot

ti-chi-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: lidezhu, 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:

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 lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Aug 12, 2026
@ti-chi-bot

ti-chi-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-08-09 14:39:51.070941734 +0000 UTC m=+2970977.107036800: ☑️ agreed by lidezhu.
  • 2026-08-12 02:22:47.072063945 +0000 UTC m=+3185953.108158991: ☑️ agreed by wk989898.

@asddongmen

Copy link
Copy Markdown
Collaborator Author

/test all

@asddongmen

Copy link
Copy Markdown
Collaborator Author

/retest

@ti-chi-bot
ti-chi-bot Bot merged commit 825a0b3 into pingcap:master Aug 12, 2026
43 of 45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note Denotes a PR that will be considered when it comes time to generate release notes. 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.

*: optimize resolved-ts and checkpoint propagation latency

3 participants