mobuchowski commented on code in PR #75860:
URL: https://github.com/apache/airflow/pull/75860#discussion_r4401827383


##########
providers/openlineage/src/airflow/providers/openlineage/utils/utils.py:
##########
@@ -1522,6 +1526,7 @@ class TaskInfoComplete(TaskInfo):
         "_BaseOperator__instantiated",
         "_BaseOperator__init_kwargs",  # Causes recursion error on AF3, 
nothing useful there
         "_dag",
+        "dag",  # A stored operator's Dag, e.g. in the scheduler, which can't 
be pickled

Review Comment:
   With `include_full_task_info` on, `TaskInfoComplete` copies every attribute 
in the operator's `__dict__` that isn't in `excludes`. On a scheduler-side 
mapped operator, that includes `expand_input`, which `SerializedDAG` 
deserialization sets with `setattr(task, k, kwargs_ref.deref(dag))`. When the 
mapped task's input comes from an upstream task, `deref` makes it a 
`SchedulerPlainXComArg` whose `.operator` is the live upstream operator. From 
there pickling reaches the operator's Dag, and through the Dag the other 
operators and their `methodtools` caches. `_cast_basic_types` leaves attrs 
objects as they are, so all of this ends up in the dict item.
   
   I reproduced it by changing one line of the new test to 
`PythonOperator.partial(task_id="mapped", 
python_callable=list).expand(op_kwargs=plain.output)`. It then fails on 
`TaskInfoComplete(dag.get_task("mapped"))`:
   ```
   _pickle.PicklingError: Can't pickle <functools._lru_cache_wrapper object at 
0x…>: it's not the same object as
   
airflow.serialization.definitions.mappedoperator.SerializedMappedOperator.get_parse_time_mapped_ti_count
   ```
   `expand_input` is the only item that fails. The `isidentifier()` filter 
doesn't help here, because the cache is reached through a value rather than 
being a key on the encoded operator. In production, task events for a mapped 
task fed from an upstream task's output would still be dropped with `Failed to 
submit method to executor` whenever full task info is on. Mapping over an 
upstream task's output is probably the most common way dynamic mapping is used.
   
   Adding `"expand_input"` and `"op_kwargs_expand_input"` to 
`TaskInfoComplete.excludes` makes the changed test pass. Could you add that, 
and test the upstream-output case next to the literal one? Longer term, storing 
only JSON-safe values in `TaskInfoComplete` (for example 
`json.loads(json.dumps(v, default=str))`) would stop the next live attribute 
from causing the same failure.



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