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

   ## Why
   
   `airflow standalone` prints "Airflow is ready" without checking the 
component that serves the UI. `is_ready()` only looks at the scheduler, Dag 
processor and triggerer heartbeats, so the banner fires while the API server is 
still importing the app and binding its port. Developers follow the banner to 
the browser and get a connection refused.
   
   The check is not new. `is_ready()` gated on the port from the command's 
introduction in #15826, and #20505 later fixed it to read the configured port 
instead of a hard-coded 8080. #46942 ("Remove old UI and webserver") then 
deleted the attribute holding the port but left the call that read it, so 
`is_ready()` raised `AttributeError`; the follow-up hot-fix #47145 resolved 
that by deleting the call rather than repointing it at the renamed `[api] 
port`. `port_open` and its two tests have been unreachable since.
   
   ## What
   
   `airflow-core/src/airflow/cli/commands/standalone_command.py`:
   
   - `is_ready()` gates on `port_open` again, first in the chain so the three 
heartbeat queries are skipped while the API server is still coming up.
   - `run()` resolves `[api] port` once at startup, matching the shape the 
pre-#47145 code used. Keeping the lookup out of the poll loop matters: 
`conf.getint` raises on a malformed value, the loop only handles 
`KeyboardInterrupt`, and the `command.stop()` / `command.join()` shutdown sits 
after the `try` rather than in a `finally`, so an escape would leave all four 
components running as orphans. With the lookup in `run()`, a bad `[api] port` 
fails before anything is spawned.
   - Two stale docstrings corrected: `is_ready()` claimed to be time-based, 
which it has not been since #15826, and `port_open` still referred to the 
webserver.
   
   `airflow-core/tests/unit/cli/commands/test_standalone_command.py`: the 
`is_ready` tests are consolidated into one parametrized test covering 
port-open, a component not heartbeating, and port-closed. It asserts 
`port_open` is called with the resolved port, and the port-closed case passes 
an empty iterator so the short-circuit is pinned. A new test covers the config 
resolution in `run()`. Reverting the source change fails all four.
   
   ### Deliberately not in this PR
   
   `port_open` is restored as it was, so its pre-existing limitations come back 
with it and are worth a maintainer's call:
   
   - It probes `127.0.0.1` over IPv4 and ignores `[api] host`. The default 
`0.0.0.0` is fine, but a user who binds a specific non-loopback address would 
never see the banner.
   - A TCP accept proves something is listening, not that it is this 
standalone's API server. A stale process holding the port still yields a ready 
banner.
   - With `[api] workers > 1` or `server_type = gunicorn` the parent binds 
before workers import the app, so the accept precedes app readiness.
   
   All three point at the same deeper fix: polling `GET 
/api/v2/monitor/health`, which is already the idiom in the Helm chart, breeze, 
and `dev/verify_*_rc.sh`, and which would subsume the heartbeat checks too. 
That is a larger change than restoring a lost gate, so I have kept it out.
   
   Separately, `ready_time` latches and is never re-evaluated, so the banner 
still makes a 3-second-stale claim, and standalone never notices a component 
dying. Both are pre-existing and unchanged here.
   
   `.github/workflows/basic-tests.yml` greps this banner, so that job now 
genuinely depends on the API server binding.
   
   ### How to test
   
   Run `airflow standalone` and confirm the banner appears only once 
`http://localhost:8080` actually answers.
   
   ---
   
   ##### Was generative AI tooling used to co-author this PR?
   
   - [X] Yes — Claude Code (Opus 5)
   
   Generated-by: Claude Code (Opus 5) 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