MartijnVisser opened a new pull request, #320:
URL: https://github.com/apache/flink-connector-kafka/pull/320

   ## What is the purpose of the change
   
   
`DynamicKafkaSourceReaderTest.testHandleSourceEventRetainsRemovedClusterOffsetsUntilExpired`
 is
   flaky (FLINK-40398). The reader stamps a removed cluster's retention 
deadline from
   `System.currentTimeMillis()` and prunes against it in `snapshotState`, and 
the test gives it a one
   second window, so the assertions have to win a race against the wall clock.
   
   The window is not filled by scheduler jitter. `handleSourceEvents` stamps 
the deadline and then,
   in the same call, closes both `KafkaSourceReader`s and recreates the 
surviving one. Timed locally
   that call takes 25 ms on an idle machine but 571, 575 and 579 ms in three of 
six runs under CPU
   contention, so on a loaded runner it crosses the second and the split is 
pruned before the
   assertions read it. The `Time elapsed: 1.199 s` in the report fits that and 
rules out a GC pause
   longer than a second inside the method.
   
   The retention logic is correct. What is missing is a way for a test to 
control time, so this gives
   the reader an injectable clock.
   
   ## Brief change log
   
   - `DynamicKafkaSourceReader` takes a `Clock` through a new package-private 
constructor and reads
     it in the three places that used `System.currentTimeMillis()`. Both public 
constructors pass
     `SystemClock.getInstance()`, so production behaviour is unchanged, and 
deadlines stay absolute
     timestamps because they are written into checkpoints.
   - The flaky test becomes four that drive a `ManualClock` and assert the 
exact expiry boundary:
     retained up to the millisecond before the deadline and dropped at it, 
reactivated when the
     cluster returns before the deadline, not reactivated after it, and a 
restored split retained
     until its own deadline. The last two are new coverage.
   - The frozen ArchUnit store gains no violation. One existing entry moves to 
the new constructor
     signature, 59 entries before and after. The constructor is not annotated 
`@VisibleForTesting`,
     because that annotation is itself non public API and would add an entry.
   
   ## Verifying this change
   
   This change added tests and can be verified as follows. All runs are local, 
on 6b99bb38 and on
   this branch.
   
   | Tree | Test | Condition | Result |
   |---|---|---|---|
   | base | old test | `Thread.sleep(1_100)` after the removal event | red 3/3, 
`NoSuchElementException: No value present` at 
`DynamicKafkaSourceReaderTest.java:294`, the same frame as CI |
   | base | old test | CPU contention, no sleep | 0/30, the condition never 
occurred locally |
   | head | new test 1 | the same `Thread.sleep(1_100)` | green |
   | head | the three clock reads reverted | none | red 3/4, so the tests pin 
the wiring and not only the timing |
   | head | `DynamicKafkaSourceReaderTest` | none, and under CPU contention | 
green 18/18, and 20/20 over 20 sequential runs |
   | head | the four new tests | `@RepeatedTest(500)` | green 2000/2000 in 13.3 
s |
   
   The unforced loop reproduces nothing locally, as expected: this test failed 
twice in roughly 180
   CI executions since 2026-08-16, which would need about 300 local runs of a 
class that starts two
   Kafka brokers. The forced condition carries the evidence.
   
   Also run: `DynamicKafkaSourceReaderIdlenessTest`, 
`DynamicKafkaSourceReaderPauseResumeTest`,
   `*ArchitectureTest` with a clean `archunit-violations` afterwards, 
`spotless:check`,
   `checkstyle:check` and the module's unit test phase (441/441).
   
   `testActiveSplitCountMetricTracksMetadataRemoval` keeps the real clock on 
purpose: it only asserts
   that retained state is present, over a 60 s window, never a deadline.
   
   `DynamicKafkaSourceEnumerator` reads the wall clock the same way and
   
`DynamicKafkaSourceEnumeratorTest.testEnumeratorStateRetainsRemovedClusterUntilExpired`
 has the
   same one second window. It has not been seen failing, so it gets its own 
ticket rather than being
   pulled into this one.
   
   ## Does this pull request potentially affect one of the following parts:
   
     - Dependencies (does it add or upgrade a dependency): **no**. `flink-core` 
is already a
       `provided` dependency and `Clock`, `SystemClock` and `ManualClock` are 
`@PublicEvolving` in
       its main jar.
     - The public API, i.e., is any changed class annotated with 
`@Public(Evolving)`: **no**
     - The serializers: **no**
     - The runtime per-record code paths (performance sensitive): **no**
     - Anything that affects deployment or recovery: JobManager (and its 
components), Checkpointing,
       Kubernetes/Yarn, ZooKeeper: **no**
     - The S3 file system connector: **no**
   
   ## Documentation
   
     - Does this pull request introduce a new feature? **no**
     - If yes, how is the feature documented? **not applicable**
   
   ## AI Disclosure
   
     - [x] This pull request was created with the assistance of an AI tool.
   


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