[runtime] Preserve typed Flink key identity in action state - #1100
Draft
rob-9 wants to merge 5 commits into
Draft
Conversation
…action name Action.hashCode() folds in JavaFunction's Class[] parameterTypes, and Class.hashCode() is the per-JVM identity hash, so every durable-state key changes across a process restart and recovery lookups can never hit. Kill/restore trials: 0/134 replays before this fix; 90/90 with 0% divergence after (non-deterministic strategy, Kafka action-state store).
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.
Closes #1099.
This branch is stacked on PR #1094, which makes the action identifier stable across JVM restarts. The two changes fix separate parts of the action-state key.
Purpose of change
We currently store action progress under the current key so recovery can find completed work and avoid repeating its side effects. The existing format turns that key into text. Different typed keys with the same text, such as
Long(1)andString("1"), can therefore point to the same action state. A lookup or prune for one key can remove the other key's completed state, allowing recovery to run that action again.This change gives each typed key a durable identity derived from its serialized bytes. Kafka and Fluss use that identity consistently for writes, lookups, cleanup, partitioning, and recovery.
Runtime flow
ActionStateKeyEncoderserializes the typed key and hashes the bytes with SHA-256. The versioned state key contains that digest, the key-group, sequence number, event ID, action ID, and serializer fingerprint.Key decisions
Related work
Issue #1034 manages the Kafka offset boundary for deleting an older log prefix, while this PR defines the identity of each record. PR #885 manages Kafka tombstones. When those changes are combined, replay must validate the record key before applying a value or tombstone, and pruning must derive the same typed identity.
Behavioral Semantics
Interaction decisions
Behavioral contracts
Long(1),String("1"), and custom keys sharing a string representation receive separate identities, including at maximum parallelism1.Failure behavior
API
The supported user-facing API and configuration remain unchanged. The stores, key utilities, and Kafka partitioner now carry explicit
@Internalannotations. Their construction path receives anActionStateKeyEncoder, so direct callers of these implementation classes must update their constructor calls.The durable record format changes incompatibly. A recovery range containing unversioned records requires a fresh Kafka topic or Fluss table and a fresh job state. Versioned recovery also requires the same key type and a byte-for-byte-equivalent serializer snapshot configuration.
Documentation
doc-neededdoc-not-neededdoc-includedThe deployment and configuration documentation explains the format transition, serializer compatibility, backend isolation, and digest security boundary.
Was this patch authored or co-authored using generative AI tooling?