[fix][test] Bound record reads in Debezium MySQL and Postgres tests#71
Merged
david-streamlio merged 2 commits intoJul 9, 2026
Merged
Conversation
AbstractKafkaConnectSource.read() loops until a record is available and never returns null. Calling it on the test thread inside an Awaitility untilAsserted block means a connector that produces fewer records than expected blocks forever: Awaitility cannot interrupt a blocked assertion, so its atMost(60s) never fires. Neither test declared a timeOut, so the CI job ran to its own 45-minute limit and reported a cancellation rather than a failure. Read each record on a bounded worker thread and add a test-level timeOut as a backstop, so under-delivery fails promptly with a message naming the connector.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the Debezium MySQL and Postgres integration tests so they fail promptly (instead of hanging the entire CI job) when the connector under-delivers CDC records during the initial snapshot.
Changes:
- Replace the unbounded
while (source.read() != null)pattern with a fixedEXPECTED_RECORDSloop. - Add a per-record read deadline by running
source.read()on a separate executor thread and failing on timeout. - Add a TestNG
@Test(timeOut = 600_000)backstop and ensure the executor is shut down during cleanup.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| debezium/mysql/src/test/java/org/apache/pulsar/io/debezium/mysql/DebeziumMysqlSourceTest.java | Adds bounded, per-record reads + test timeout to prevent indefinite CI hangs on under-delivery. |
| debezium/postgres/src/test/java/org/apache/pulsar/io/debezium/postgres/DebeziumPostgresSourceTest.java | Applies the same bounded read harness + test timeout to Postgres CDC snapshot assertions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| @BeforeMethod | ||
| public void setup() throws Exception { | ||
| readerExecutor = Executors.newSingleThreadExecutor(); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This was referenced Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #70
Motivation
DebeziumMysqlSourceTestandDebeziumPostgresSourceTestcan hang CI for 45 minutes instead of failing, if their connector delivers fewer CDC records than expected.AbstractKafkaConnectSource.read()is awhile (true)loop whose onlyreturnyields a record — an empty poll hitscontinue. It never returnsnull. Both tests drive it withwhile ((record = source.read()) != null), escaping only viabreakafter 2 records, all inside an AwaitilityuntilAssertedblock. If fewer than 2 records arrive,read()spins forever, and Awaitility'satMost(60s)never fires becauseuntilAssertedcannot interrupt a blocked assertion. Neither test declares atimeOut, so nothing bounds them.They pass today only because MySQL and Postgres reliably emit their snapshot records. This was observed for real on #58, where the
Tests - Connectorsjob ran 45m15s and was cancelled — no diagnostics, 45 minutes of runner time gone.Modifications
For both tests:
READ_TIMEOUT_SECONDS = 120), cancelling the blocked read and failing with a message that names the connector and points at the Debezium logs.@Test(timeOut = 600_000)as a backstop.shutdownNow()the executor in cleanup, since a reader may still be blocked inread().while (read() != null)idiom with an explicitEXPECTED_RECORDSloop, so the expectation is stated rather than implied by abreak.This is the same harness applied in #58.
Verifying this change
Both tests pass locally against real containers:
The guard itself was verified by forcing under-delivery (expecting 3 records against 2 seeded rows): the fixed harness fails in ~37s with a
TimeoutException, where the old one hangs indefinitely.Related
timeOuttimeOutbackstop but still read on the test threadOnce those land, a follow-up can lift
readOne()into a shared test base class rather than repeating it per module.