jonathansudhakar1 commented on issue #25374:
URL: https://github.com/apache/beam/issues/25374#issuecomment-6710411217

   @claudevdm, I'd like to fix this, building on your analysis above. Since it 
touches `transforms/core.py`, I wanted to check the approach with you before 
sending a PR.
   
   **It still reproduces on master** (431b7c7ef0a, Python 3.13, DirectRunner):
   
   ```python
   main | beam.FlatMap(lambda x, side: [x + sum(side)], 
beam.pvalue.AsIter(side_pcoll)) \
        .with_exception_handling(use_subprocess=True)
   ```
   
   Every element goes to the dead-letter output with `AttributeError: 
'_thread._local' object has no attribute 'side_input_cache_tokens'`.
   - **Subprocess mode:** the pool's queue feeder thread pickles the 
`_StateBackedIterable`, and its `__reduce__` reads state through a handler 
whose context is thread-local.
   - **Timeout mode:** the same pipeline with `timeout=30` and no subprocess 
fails the same way, because `_TimeoutDoFn` iterates the side input on a 
`ThreadPoolExecutor` thread.
   - **Unaffected:** `AsList` and `AsDict` work in both modes, since they're 
already materialized.
   
   **Proposed fix.** I tried parts 1 and 2 locally, and with them the repro 
passes in both modes:
   1. `_SubprocessDoFn.process` pickles `(args, kwargs)` itself, in the 
dispatching thread, and passes the bytes to `_remote_process`, which unpickles 
them. The pickling is the same as today (a lazy side input still becomes a list 
through `__reduce__`); it just happens in the thread that has the state context.
   2. `_TimeoutDoFn.process` turns any `_StateBackedIterable` argument into a 
list in the dispatching thread before submitting to its pool. That gives up 
lazy iteration in timeout mode, which fails outright today anyway.
      - The alternative is to carry the state handler's thread-local context 
into the worker thread, the way #32571 carried the state sampler. But `core.py` 
has no handle on the state handler, so that looks more invasive.
   3. Tests: an `AsIter` side-input case in `DeadLettersTest` in 
`ptransform_test.py`, which already runs with `use_subprocess` False and True, 
plus a timeout-only case.
   
   **Out of scope:** `AsMultiMap`. With `use_subprocess=True` it still raises 
`TypeError` from `MultiMap.__reduce__` (the existing TODO), and with `timeout` 
its per-key lookups would still run in the worker thread.
   
   **Question:** does this split work for you? In particular, is it OK to 
materialize `AsIter` side inputs in the timeout path (part 2)? Or would you 
rather this fix only cover the subprocess path, or propagate the state context 
instead?
   
   .take-issue
   


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