shahar1 opened a new pull request, #39213:
URL: https://github.com/apache/beam/pull/39213

   ## What & why
   
   `EnvoyRateLimiter` (`sdks/python/apache_beam/io/components/rate_limiter.py`) 
depends on `envoy-data-plane` purely to obtain a handful of protobuf message 
classes. That package pulls in `betterproto==2.0.0b6` — an outdated pre-release 
of a protobuf *reimplementation* — plus `grpclib` and a transitive subtree 
(`h2`, `hpack`, `hyperframe`, `multidict`).
   
   This PR removes `envoy-data-plane` (and therefore `betterproto`) entirely, 
replacing it with a minimal, self-contained vendored proto.
   
   **Why this is worth doing, and why vendoring beats bumping the dependency:**
   
   - **The dependency was already fought, not used.** `betterproto` emits 
*async* `grpclib` stubs that are incompatible with Beam's synchronous `grpcio`. 
The code already hand-writes the `RateLimitServiceStub` bridge to work around 
that — so the package only ever contributed 6 message dataclasses, and the wire 
is plain protobuf over `grpcio` regardless.
   - **It resolves a real downstream block.** The `betterproto==2.0.0b6` pin is 
the last blocker stopping Apache Airflow from un-suspending its Beam provider 
(apache/airflow#66952). Because Airflow's constraint solver reads Beam's 
`install_requires`, removing the dependency here fixes it for **all** Python 
versions — no `betterproto` pin needed on Airflow's side.
   - **Bumping to `envoy-data-plane>=2.1.0` would only move the problem.** That 
route swaps in `betterproto2` (still pre-1.0, `0.9.x`), requires porting to the 
betterproto2 API, and drops Python 3.10 support (2.x requires `>=3.11`). 
Vendoring ends the version-chase permanently and lets us delete the existing 
`python_version` split in `setup.py`.
   - **This is an established Beam pattern, not a novelty.** 
`apache_beam/coders/proto2_coder_test_messages_pb2.py` is already a checked-in, 
hand-regenerated `_pb2.py` outside the `gen_protos.py` model pipeline. This 
change follows it exactly (same lint-exclusion spots, same header style). The 
vendored proto is a frozen external contract — Envoy RLS v3 field numbers are 
GA and cannot change without breaking every client — so it is a write-once 
artifact, not an ongoing maintenance burden.
   
   ## How it works
   
   - New `sdks/python/apache_beam/io/components/rate_limit.proto`: a ~30-line 
self-contained subset of the Envoy Rate Limit Service. **Field numbers match 
Envoy's `rls.proto` / `ratelimit.proto`**, so the messages are wire-compatible 
with a real RLS server (protobuf carries only field numbers and types on the 
wire — not message or package names).
   - New checked-in `rate_limit_pb2.py`, generated via `grpc_tools.protoc`. The 
generated `runtime_version` guard is removed so the module stays compatible 
across Beam's full `protobuf>=3.20.3,<7` runtime range (matching the existing 
test pb2). The regeneration command is documented in both files' headers.
   - `rate_limiter.py` / `rate_limiter_test.py`: swapped imports to 
`rate_limit_pb2`; the one behavioral adjustment is `google.protobuf.Duration` 
handling (`dur.ToTimedelta().total_seconds()` — `betterproto` used to auto-map 
`Duration` → `timedelta`).
   
   ## Testing
   
   - **8/8 unit tests pass.** The original 5 mock-based tests cover the 
retry/throttle logic; **3 new wire-format tests** pin the exact serialized 
bytes and enum values against Envoy's field numbers — these fail loudly if the 
vendored proto ever drifts, which the mock tests cannot catch.
   - Verified `rate_limiter` imports and constructs with `envoy_data_plane` and 
`betterproto` blocked from `sys.modules`, confirming the dependency is 
genuinely gone.
   - `yapf`, `isort` (repo CI flags), and `ruff` all clean.
   
   ## Follow-up
   
   The 12 container `*_requirements.txt` files have the two **direct** packages 
(`envoy-data-plane`, `betterproto`) removed so they stay consistent with 
`setup.py`. A full `./gradlew 
:sdks:python:container:generatePythonRequirementsAll` regeneration should run 
in CI/by a committer to also prune the now-orphaned transitives (`grpclib`, 
`h2`, `multidict`, …) and refresh pins — that step requires interpreters for 
all supported Python versions plus a full network resolution.
   
   ------------------------
   
    - [x] Mention the appropriate issue in your description — Part of #37854 
(removes the `envoy-data-plane` tech debt called out there; does **not** close 
the issue, whose TFT/protobuf-5/6 conflict remains open). Unblocks 
apache/airflow#66952.
    - [x] Update `CHANGES.md` with noteworthy changes.
    - [ ] If this contribution is large, please file an Apache ICLA. (Not 
large.)
   
   ------------------------
   
   ##### Was AI tooling used to author this PR?
   
   Yes — authored with Claude Code (Opus 4.8, 1M context). All changes were 
reviewed by the PR author. Generated following the project's gen-AI 
contribution guidelines.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)


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