jason810496 opened a new pull request, #71536:
URL: https://github.com/apache/airflow/pull/71536

   - related: #69757 shipped the `@task.stub` TaskFlow arg-binding contract; 
this fills in the value half of it.
   
   ## Why
   
   A `@task.stub` TaskFlow call may only carry values `json.dumps` already 
knows, so the most natural arguments to pass a foreign-language task were 
rejected outright:
   
   ```python
   @task.stub(queue="golang")
   def schedule_window(starts_at: datetime, every: timedelta, trace_id: UUID): 
...
   
   
   schedule_window(datetime(2024, 1, 2, 3, 4, 5), timedelta(minutes=5), 
UUID("6ba7b810-..."))
   ```
   
   ```
   ValueError: @task.stub task 'schedule_window' parameter 'starts_at' received 
a literal of
   type datetime that is not JSON-serializable, so it cannot be passed to the 
foreign runtime
   ```
   
   The parameter's `value_schema` already told the runtime this was `{"type": 
"string", "format": "date-time"}` but the *value* could not travel.
   
   ## What
   
   The literal is now rendered through the **same pydantic adapter that 
produced its `value_schema`**, so the two cannot disagree by construction:
   
   | Python literal | Wire value | `value_schema` |
   | --- | --- | --- |
   | `datetime(2024, 1, 2, 3, 4, 5)` | `"2024-01-02T03:04:05Z"` | `{"type": 
"string", "format": "date-time"}` |
   | `date(2024, 1, 2)` | `"2024-01-02"` | `{"type": "string", "format": 
"date"}` |
   | `timedelta(days=1, hours=2)` | `"P1DT2H"` | `{"type": "string", "format": 
"duration"}` |
   | `UUID("6BA7B810-...")` | `"6ba7b810-..."` (normalized) | `{"type": 
"string", "format": "uuid"}` |
   
   Values that were already JSON pass through untouched, and an argument with 
no usable annotation still hits the existing "not JSON-serializable" error.
   
   ## Timezone-naive timestamps
   
   A naive `datetime` is pinned to an explicit offset before serializing, via 
the same `coerce_datetime` the rest of Airflow uses. An offset-less timestamp 
is a *different instant* to each language runtime, so leaving it naive would 
make a task's behaviour depend on which language happens to run it.
   
   | Wire value | Go | Java `Instant.parse` | JS `new Date` |
   | --- | --- | --- | --- |
   | `2024-01-02T03:04:05Z` | `03:04:05Z` | `03:04:05Z` | `03:04:05Z` |
   | `2024-01-02T03:04:05` | `03:04:05Z` | throws | `08:04:05Z` (worker-local) |
   
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [x] Yes, with help of Claude Code following [the 
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
   


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