david-streamlio opened a new pull request, #86:
URL: https://github.com/apache/pulsar-connectors/pull/86

   Fixes #85
   
   ### Motivation
   
   An audit for timing flakes found the same defect in four more modules. Each 
writes to a sink that flushes **asynchronously**, waits a **fixed** 
`Thread.sleep`, then asserts the flush happened. On a slow runner the flush has 
not run and the assertion fails — the sink is fine, the test raced it.
   
   This shape has already failed two unrelated PRs today:
   
   - `InfluxDBSinkTest.testOpenWriteCloseJson` (v2) broke #39 → fixed in #73
   - `PulsarSchemaHistoryTest.setup` broke #79 → fixed in #84
   
   ### Findings
   
   | Module | Test | Sleep | Then asserts | Async mechanism |
   |---|---|---|---|---|
   | `hdfs3` | `HdfsSequentialSinkTest.write5000Test` | 2000 ms | `verify(..., 
times(5000)).ack()` | `syncInterval` background sync |
   | `hdfs3` | `HdfsSequentialSinkTest`, `HdfsTextSinkTest` | 2000 ms | 
`verify(..., times(100)).ack()` | same |
   | `mongo` | `MongoSinkTest` × 5 sites | 1000 ms | `verify(..., 
times(n)).ack()/.fail()` | `flushExecutor.scheduleAtFixedRate` |
   | `influxdb` v1 | `InfluxDBGenericRecordSinkTest` | 1000 ms | 
`verify(influxDB, times(1)).write(...)` | `BatchSink` flush executor — the very 
class whose v2 sibling flaked |
   | `hbase` | `HbaseGenericRecordSinkTest` | 500 ms | reads the row back | 
`HbaseAbstractSink` batch flush |
   
   `write5000Test` is the sharpest: 5000 acks asserted within a hard-coded 2 
seconds.
   
   ### Modifications
   
   Replace each fixed sleep with an Awaitility poll on the same condition. 
**The assertions are unchanged** — only the waiting is. `awaitility` is already 
on every module's test classpath via the shared java-conventions plugin. The 
tests also get faster, since a poll returns as soon as the condition holds 
rather than always sleeping the full duration.
   
   ### Verifying this change
   
   All four suites pass: `./gradlew :mongo:test :influxdb:test :hdfs3:test 
:hbase:test` → `BUILD SUCCESSFUL`.
   
   More importantly, the race is **demonstrated**, not asserted. Taking 
master's `MongoSinkTest` and shortening its sleep from 1000 ms to 1 ms — 
simulating a runner slow enough that the flush has not fired — reproduces the 
CI signature exactly:
   
   ```
   MongoSinkTest > testWriteBadMessage FAILED
       Wanted but not invoked: ...
   MongoSinkTest > testWriteGoodMessage FAILED
       Wanted but not invoked: ...
   ```
   
   The Awaitility version passes with **no sleep at all**, because it waits on 
the condition rather than on a guessed duration.
   
   ### Notes
   
   - `HbaseGenericRecordSinkTest` is `@Test(enabled = false)` and does not run 
today, so its change is compile-only. Included so the pattern is not 
reintroduced when it is re-enabled.
   - Deliberately **not** changed, with reasons, in #85: `redis` (sleeps but 
asserts nothing afterwards), `jdbc/sqlite` (sleep inside a retry loop), 
`azure-data-explorer` (credential-gated, never runs in CI — see #49), and 
`file` (its sleeps are deliberate soak windows; its races were fixed in #41 and 
#71).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to