twalthr opened a new pull request, #29657:
URL: https://github.com/apache/flink/pull/29657

   ## What is the purpose of the change
   
   `ProcessTableFunction.Context#clearAllTimers()` (and `clearAll()`) did not 
scope the removal of unnamed timers to the current partition key. 
`WritableInternalTimeContext#clearUnnamedTimers` iterated the unnamed timers 
via `InternalTimerService#forEachEventTimeTimer`. That iteration covers the 
timers of **all keys** in the subtask and sets the key context to the key of 
each visited timer without restoring it. As a result:
   
   1. Timestamps of other keys' timers were collected.
   2. The deletes ran under the key of the last visited timer instead of the 
current key. Timers of the current key survived and fired later, and timers of 
other keys with the same timestamp were silently deleted.
   3. The operator's key context was left on an arbitrary key. Later calls in 
the same `eval()`/`onTimer()` ran under the wrong key: the clearing of named 
timers in `clearAllTimers()`, `clearAllState()` in `clearAll()`, and the 
write-back of state entries.
   
   Named timers are tracked in keyed map state, so the timer lookup itself was 
key-scoped. They were only affected indirectly, through the corrupted key 
context described in 3.
   
   ## Brief change log
   
     - `WritableInternalTimeContext#clearUnnamedTimers` only collects the 
timers of the current key and restores the key context afterwards.
     - `AbstractProcessTableOperator` passes the `KeyedStateBackend` to 
`WritableInternalTimeContext`.
     - The key comparison relies on value-based key equality, which is only 
guaranteed for `BinaryRowData`. The key selectors of the PTF node always 
produce `BinaryRowData`, and the heap state backend already relies on key 
`equals` for its own lookups. To make this invariant explicit, 
`AbstractProcessTableOperator#setCurrentKey` (through which every key enters 
the operator) now throws an `IllegalStateException` for any other key type.
     - No new state is introduced, so there is no change to the state layout or 
checkpoint compatibility, and the timer registration path is unchanged. 
Clearing still iterates all unnamed timers of the subtask, but that only 
happens when `clearAllTimers()` is called. A per-key index of unnamed timers 
could make this cheaper but would change the state layout, so it is left for a 
follow-up.
   
   ## Verifying this change
   
   Please make sure both new and modified tests in this PR follow [the 
conventions for tests defined in our code quality 
guide](https://flink.apache.org/how-to-contribute/code-style-and-quality-common/#7-testing).
   
   This change added tests and can be verified as follows:
   
     - Added `PROCESS_CLEAR_ALL_UNNAMED_TIMERS_PER_KEY` to 
`ProcessTableFunctionSemanticTests`: three keys register an unnamed timer for 
the same time, two of them call `clearAllTimers()`, only the untouched key's 
timer fires, and the cleared keys keep consistent state afterwards. The test 
fails without the fix and passes with it.
     - Added `ProcessSetTableOperatorTest#testNonBinaryKey` which verifies that 
non-binary keys are rejected.
     - Additionally verified manually (not part of the PR) that `equals` of the 
keys agrees with equality of the serialized keys, for 15 partition key types on 
the heap and RocksDB state backends (with both timer service factories) and 
after a serializer round trip.
     - Ran spotless, checkstyle, and the ArchUnit tests locally.
   
   ## Does this pull request potentially affect one of the following parts:
   
     - Dependencies (does it add or upgrade a dependency): no
     - 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): yes (a single 
`instanceof` check when the key context is set)
     - 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
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes (please specify the tool below)
   
   Generated-by: Claude Code (Claude Sonnet 5.5)
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


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