[api][runtime][test] Add @JsonCreator to built-in event subclasses for ActionStateSerde durable recovery#869
Conversation
wenjin272
left a comment
There was a problem hiding this comment.
Thanks for this fix @rosemarYuan. Overall looks good to me, I left some comments about the details.
Besides, I think we need to state in the "custom-event-subclasses" section of the documentation that users must declare a JsonCreator for their custom Event subclasses.
| } | ||
|
|
||
| @Test | ||
| public void testBuiltinChatToolAndContextEventsRoundTripThroughOutputEvents() throws Exception { |
There was a problem hiding this comment.
The test case name is overly verbose and its meaning is unclear. suggest to: testBuiltInEventSerDeRoundTrip
| originalState.addEvent( | ||
| new ContextRetrievalResponseEvent(requestId, "query text", List.of(doc))); | ||
|
|
||
| byte[] serialized = ActionStateSerde.serialize(originalState); |
There was a problem hiding this comment.
Currently, we inject the type information of Event during serialization by declaring mixins for the ObjectMapper.
// Add type information for polymorphic Event deserialization
mapper.addMixIn(Event.class, EventTypeInfoMixin.class);
mapper.addMixIn(InputEvent.class, EventTypeInfoMixin.class);
mapper.addMixIn(OutputEvent.class, EventTypeInfoMixin.class);
This allows the ObjectMapper to reconstruct the specific subclass of Event during deserialization. But I think that it’s sufficient to keep only mapper.addMixIn(Event.class, EventTypeInfoMixin.class); here.
There was a problem hiding this comment.
Thanks for you suggestion. Updated the PR based on your comments: simplified the test name, kept only the base Event mixin in ActionStateSerde, and added documentation for custom Java Event subclasses to explain the required Jackson creator annotations during durable recovery.
…r ActionStateSerde durable recovery
0b51c59 to
2603cd9
Compare
Linked issue: #868
Purpose of change
ActionStateSerdeuses Jackson polymorphic deserialization (@JsonTypeInfo(Id.CLASS)) to restore the concreteEventsubclasses persisted inActionState(taskEvent/outputEvents) for durable execution recovery. Jackson requires each concrete subclass to declare its own creator — the@JsonCreatoron the baseEventconstructor is not inherited.Only
InputEvent/OutputEventannotate their(UUID, Map<String, Object>)constructors with@JsonCreator/@JsonProperty. The six built-in event subclasses underorg.apache.flink.agents.api.event.*(ChatRequestEvent,ChatResponseEvent,ToolRequestEvent,ToolResponseEvent,ContextRetrievalRequestEvent,ContextRetrievalResponseEvent) have the same constructors but lack the annotations, so deserializing any of them from a persistedActionStatefails with:This PR annotates the
(UUID, Map<String, Object>)constructor of all six classes, consistent withInputEvent/OutputEvent.Tests
Added
ActionStateSerdeTest#testBuiltinChatToolAndContextEventsRoundTripThroughOutputEvents, which:ActionStateSerdeboth astaskEventand insideoutputEvents, asserting the concrete class is restored (fails with the exception above without the fix);fromEvent()consumption path used by the built-in actions (ChatMessage,ToolResponse,Document, andUUIDrequest ids), not raw maps.Verified with
mvn -pl runtime test -Dtest=ActionStateSerdeTest(11/11 pass) and the fullapimodule test suite.API
No signature changes. Adds Jackson annotations to existing public constructors of the six built-in event classes; serialized JSON format is unchanged.
Documentation
doc-neededdoc-not-neededdoc-included