Repository navigation
[runtime][api][python] Add checkpoint-aligned Kafka action-state cleanup - #1101
Conversation
e71972e to
d075edd
Compare
6aa9a43 to
a432009
Compare
|
Rebased onto main after #885 and #1100 merged and cleaned up history. Fixed conflicts and ran a review pass. |
|
@joeyutong Could you help review this PR. |
|
Overall, this PR looks good to me. One pre-existing issue is worth tracking separately: a durable call result can be written to Kafka before a checkpoint while the action is still pending. Recovery starts from the checkpoint’s end offset, may miss that result, and may run the call again. This PR does not cause the issue, but cleanup may remove an older checkpoint and the records that could have provided a fallback. |
|
@joeyutong thanks for taking a look. I'll open this as a separate issue since it already happens without cleanup. |
|
Thanks for the contribution @rob-9 and the thoughtful reviews @joeyutong |
Closes #1034.
This PR builds on #885 and #1100, now merged into main, and adds checkpoint-aligned Kafka prefix cleanup.
Purpose of change
Kafka action-state records can remain essential to Flink checkpoints and savepoints. Deleting a record too early can erase the evidence that an action already completed, allowing recovery to repeat the action and its external side effects. Flink Agents therefore needs a durable agreement about the oldest recovery point that operators still expect to use.
This change gives operators a plan/apply workflow for choosing that recovery point and reclaiming the older Kafka prefix. The plan shows the exact partition offsets that become eligible for deletion. Apply records the boundary before asking Kafka to delete data. Recovery then enforces the boundary and gives a clear error for an older checkpoint or savepoint.
For example, checkpoint C0 needs partition 0 from offset 100 and C1 needs it from offset 150. Choosing C1 allows Kafka to discard records before offset 150. C1 and newer recovery points remain supported. Restoring C0 stops with an error that names offsets 100 and 150.
Runtime flow
KafkaActionStateCleanupTool planagainst the selected checkpoint or savepoint. The tool reads every subtask marker through Flink's State Processor API, takes the minimum offset for each partition, and writes a deterministic JSON plan whose ID comes from its contents.apply.COMMITTEDrecord to a dedicated compacted control topic, and callsdeleteRecords.APPLIED. ACOMMITTEDoperation can safely resume after interruption.kafkaActionStateCleanupControlTopicconfigured, recovery validates its marker and Kafka metadata against the effective committed boundary before replaying the captured offset range.Key decisions
COMMITTEDrecord precedes deletion, giving interrupted operations one stable plan to retry.deleteRecords, which operates on a topic name that a recreated topic could reuse.cleanup.policy=compact,deleteso explicit prefix deletion is available, withretention.ms=-1andretention.bytes=-1so Kafka cannot independently retire records required by a supported recovery point.Related work
PR #885 writes tombstones for selected keys. This PR deletes an entire Kafka prefix after the operator advances the oldest supported recovery point. Cleanup mode rejects simultaneous tombstones because each mechanism defines a different recovery guarantee. PR #1100 fixed typed action-state key identity. Recovery retains those key checks before applying values or tombstones.
Behavioral Semantics
Interaction decisions
Behavioral contracts
COMMITTEDalways precedesdeleteRecords;APPLIEDfollows verification of every resulting beginning offset.COMMITTEDand immediately before and after deletion.Failure behavior
COMMITTED.COMMITTEDleaves the same plan ready for retry.clients.
Tests
KafkaActionStateCleanupPlanTestKafkaActionStateCleanupCoordinatorTestdeleteRecords, beginning offsets, and boundary readsKafkaActionStateCleanupCoordinatorIntegrationTestKafkaActionStateStoreTestKafkaActionStateCleanupToolTestpython/flink_agents/api/tests/test_core_options.pyImplementation details for traceability
cleanup.policy=compact,delete,retention.ms=-1, andretention.bytes=-1; existing topics must be migrated to those settings before apply.cleanup.policy=compact.deleteRecords. Recovery refreshes metadata before offset reads and after replay.API
This change adds
kafkaActionStateCleanupControlTopicto the Java and Python configuration APIs and adds a language-neutral administrative CLI backed by internal Java runtime types.Existing configurations keep coordinated cleanup disabled. Legacy marker maps continue to support standard recovery in that mode. Newly written markers use the versioned, topic-aware format. Cleanup mode adds explicit checks for topic identity, partition identity, boundary position, and offset availability.
Jobs migrating from tombstones must first stop tombstone emission, restart from a recovery point valid under the existing tombstone trade-off, and complete a new checkpoint or savepoint. The first cleanup plan must use that post-tombstone recovery point so its marker follows every old tombstone.
Documentation
doc-neededdoc-not-neededdoc-includedThe deployment and configuration documentation covers the operator workflow, control-topic requirements, recovery guarantees, failure behavior, and tombstone interaction.
Was this patch authored or co-authored using generative AI tooling?
Generated-by: OpenAI Codex CLI 0.153.0 (GPT-5)