joeyutong commented on code in PR #923:
URL: https://github.com/apache/flink-agents/pull/923#discussion_r3643415986


##########
python/flink_agents/api/events/event.py:
##########
@@ -96,35 +115,44 @@ def model_dump_json(self, **kwargs: Any) -> str:
         # Set fallback if not provided in kwargs
         if "fallback" not in kwargs:
             kwargs["fallback"] = self.__serialize_unknown
+        if "by_alias" not in kwargs:
+            kwargs["by_alias"] = True
         return super().model_dump_json(**kwargs)
 
-    def _generate_content_based_id(self) -> UUID:
-        """Generate a deterministic UUID based on event content using MD5 hash.
-
-        Similar to Java's UUID.nameUUIDFromBytes(), uses MD5 for version 3 
UUID.
-        """
-        # Serialize content excluding 'id' to avoid circular dependency
-        content_json = super().model_dump_json(
-            exclude={"id"}, fallback=self.__serialize_unknown
-        )
-        md5_hash = hashlib.md5(content_json.encode()).digest()
-        return UUID(bytes=md5_hash, version=3)
+    @model_serializer(mode="wrap")
+    def _serialize_event(
+        self, handler: SerializerFunctionWrapHandler
+    ) -> Dict[str, Any]:
+        """Omit empty lineage without changing other null-valued business 
data."""
+        serialized: Dict[str, Any] = handler(self)
+        if self.upstream_event_id is None:
+            serialized.pop("upstream_event_id", None)
+            serialized.pop("upstreamEventId", None)
+        if self.upstream_action_name is None:
+            serialized.pop("upstream_action_name", None)
+            serialized.pop("upstreamActionName", None)
+        return serialized
 
     @model_validator(mode="after")
-    def validate_and_set_id(self) -> "Event":
-        """Validate that fields are serializable and generate content-based 
ID."""
-        if self.id is None:
-            object.__setattr__(self, "id", self._generate_content_based_id())
+    def validate_serializable_fields(self) -> "Event":
+        """Validate that all Event fields can be serialized."""
         self.model_dump_json()
         return self
 
     def __setattr__(self, name: str, value: Any) -> None:
         super().__setattr__(name, value)
         # Ensure added property can be serialized.
         self.model_dump_json()
-        # Regenerate ID if content changed (but not if setting 'id' itself)
-        if name != "id":
-            object.__setattr__(self, "id", self._generate_content_based_id())
+
+    def with_framework_metadata_from(self, source: "Event") -> Self:

Review Comment:
   The Java and Python helpers currently have different contracts: Python 
returns a copy and includes the Event ID, while Java mutates the current object 
and does not copy the ID. Also, “framework metadata” describes ownership rather 
than the Event-domain meaning. Could the names and contracts be aligned around 
preserving/reconstructing the same Event occurrence?



##########
runtime/src/main/java/org/apache/flink/agents/runtime/operator/ActionExecutionOperator.java:
##########
@@ -454,6 +456,13 @@ private void processActionTaskForKey(Object key) throws 
Exception {
         }
     }
 
+    private static void setOutputEventLineage(ActionTask actionTask, 
List<Event> outputEvents) {

Review Comment:
   This rule describes how a concrete Action invocation finalizes its output 
Events, rather than Operator scheduling. Could it be owned by `ActionTask`, 
which already holds the triggering Event and Action? That would keep the 
Operator independent of lineage field details and provide one place to reject 
`outputEvent.id == triggerEvent.id`; currently `ctx.sendEvent(event)` can 
create a self-loop and mutate the triggering Event shared by sibling 
ActionTasks.



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