[runtime] Preserve byte[] MemoryUpdate values across durable-execution serde (#865)#871
Closed
weiqingy wants to merge 1 commit into
Closed
[runtime] Preserve byte[] MemoryUpdate values across durable-execution serde (#865)#871weiqingy wants to merge 1 commit into
weiqingy wants to merge 1 commit into
Conversation
…n serde (apache#865) ActionStateSerde serialized MemoryUpdate.value (declared Object) via a type-info-less Jackson ObjectMapper, so a byte[] was written as a base64 String and, with no type tag, deserialized back as String on crash/replay — silently writing the wrong type into memory. This is a pre-existing, Java-native defect (a Java agent can set a byte[] memory value directly); admitting Python bytes into the memory contract only raised its likelihood. Add a targeted, field-scoped envelope (de)serializer bound to MemoryUpdate.value via a mixin: a byte[] is written as {"__flink_agents_bytes__":"<base64>"} and reversed back to byte[] on read, while every other value type delegates to stock untyped Object (de)serialization and stays byte-identical on disk. Field-scoping (mixin, not a global byte[] serializer) leaves CallResult's statically-typed byte[] fields untouched, and adds no polymorphic-typing deserialization surface. Only a top-level byte[] value is preserved; a byte[] nested inside a List or Map value is out of scope and documented as such.
Collaborator
Author
|
Closing this in favor of #874, which supersedes it. Per the discussion on #872, rather than land this narrow top-level |
Closed
2 tasks
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.
Linked issue: #865
Purpose of change
ActionStateSerdeserializesMemoryUpdate.value(declaredObject) via a plain, type-info-less JacksonObjectMapper, so abyte[]is written as a base64Stringand — with no type tag — deserialized back asStringon crash/replay, silently writing the wrong type into memory.This is a pre-existing, Java-native defect: a Java agent can
setabyte[]memory value directly, so the bug predates admitting Pythonbytesinto the memory contract (#846); #846 only makes it more likely to be hit.The fix adds a targeted, field-scoped envelope (de)serializer bound to
MemoryUpdate.valuevia a Jackson mixin. Abyte[]is written as{"__flink_agents_bytes__":"<base64>"}and reversed back tobyte[]on read; every other value type delegates to Jackson's stock untyped-Object(de)serialization and stays byte-identical on disk, so in-flight durable state remains replay-compatible.The (de)serializer is bound per-property (mixin on
value), not registered globally onbyte[], soCallResult's statically-typedbyte[]fields are untouched. The envelope carries only base64 text →byte[], so it adds no polymorphic-typing deserialization surface.Scope: only a top-level
byte[]value is preserved. Abyte[]nested inside aList/Mapvalue goes through the default serializers and is out of scope, documented in the code.Tests
Added round-trip regressions in
ActionStateSerdeTest(the first mirrors the issue repro exactly):byte[]on a short-term memory update round-trips asbyte[](issue repro;assertArrayEquals)byte[]on a sensory memory updatebyte[0]Stringvalue still round-trips asString(envelope doesn't disturb the common case)Mapvalue still round-trips as aMap(not misread as an envelope; on-disk shape unchanged)Mapthat is exactly{"__flink_agents_bytes__":"<base64>"}recovers asbyte[](documented residual), while any second key keeps it aMapmvn test -Dtest=ActionStateSerdeTest -pl runtime→ 16 tests, 0 failures.mvn test -pl runtime→ 396 tests, 0 failures.API
No public API change.
MemoryUpdate,ActionState, andActionStateSerde.serialize/deserializesignatures are unchanged; only the on-disk encoding of abyte[]value changes (it was previously broken).Documentation
doc-neededdoc-not-neededdoc-included