Skip to content

[fix][test] Bound record reads in Debezium MySQL and Postgres tests#71

Merged
david-streamlio merged 2 commits into
apache:masterfrom
david-streamlio:fix/debezium-test-read-timeouts
Jul 9, 2026
Merged

[fix][test] Bound record reads in Debezium MySQL and Postgres tests#71
david-streamlio merged 2 commits into
apache:masterfrom
david-streamlio:fix/debezium-test-read-timeouts

Conversation

@david-streamlio

Copy link
Copy Markdown
Contributor

Fixes #70

Motivation

DebeziumMysqlSourceTest and DebeziumPostgresSourceTest can hang CI for 45 minutes instead of failing, if their connector delivers fewer CDC records than expected.

AbstractKafkaConnectSource.read() is a while (true) loop whose only return yields a record — an empty poll hits continue. It never returns null. Both tests drive it with while ((record = source.read()) != null), escaping only via break after 2 records, all inside an Awaitility untilAsserted block. If fewer than 2 records arrive, read() spins forever, and Awaitility's atMost(60s) never fires because untilAsserted cannot interrupt a blocked assertion. Neither test declares a timeOut, 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 - Connectors job ran 45m15s and was cancelled — no diagnostics, 45 minutes of runner time gone.

Modifications

For both tests:

  • Read each record on a single-threaded executor with a per-record deadline (READ_TIMEOUT_SECONDS = 120), cancelling the blocked read and failing with a message that names the connector and points at the Debezium logs.
  • Add @Test(timeOut = 600_000) as a backstop.
  • shutdownNow() the executor in cleanup, since a reader may still be blocked in read().
  • Replace the while (read() != null) idiom with an explicit EXPECTED_RECORDS loop, so the expectation is stated rather than implied by a break.

This is the same harness applied in #58.

Verifying this change

Both tests pass locally against real containers:

DebeziumMysqlSourceTest > testMysqlCdcEvents PASSED
DebeziumPostgresSourceTest > testPostgresCdcEvents PASSED
BUILD SUCCESSFUL in 26s

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

Once those land, a follow-up can lift readOne() into a shared test base class rather than repeating it per module.

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.

Copilot AI 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.

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 fixed EXPECTED_RECORDS loop.
  • 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Debezium integration tests can hang CI for 45 minutes instead of failing

2 participants