Skip to content

[fix](fe) Gate serving until startup initialization completes - #68330

Open
morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:fix/fe-startup-readiness-gate
Open

morrySnow wants to merge 1 commit into
apache:masterfrom
morrySnow:fix/fe-startup-readiness-gate

Conversation

@morrySnow

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: N/A

Related PR: #68302

Problem Summary:

If UNKNOWN interrupts a FE's first FOLLOWER/OBSERVER transition, initialization returns early while the previous FE type is retained. The replayer can subsequently set the metadata readiness/readability flags to true before initialization has completed. This can release waitForReady() and allow local reads while startup work is still incomplete. Clearing those flags once does not close the race, since the replayer can set them again.

Add a process-local startupInitialized gate to isReady() and canRead(). The state listener opens the gate only after a successful MASTER/FOLLOWER/OBSERVER initialization and publication of the new FE type. UNKNOWN handling cannot open it. Initialization's own waits continue to use metadata readiness, avoiding a circular dependency.

Once initialization has completed, the gate stays open so an initialized FE entering UNKNOWN retains its existing read policy and metadata freshness checks.

Release note

Fix a race that could let an FE report ready or serve local reads before startup initialization completed after an UNKNOWN state interruption.

Check List (For Author)

  • Test
    • Regression test
    • Unit Test
    • Manual test (details below)
    • No need to test or manual test.
  • Behavior changed:
    • No.
    • Yes. An FE remains not ready and cannot serve local reads until its first initialization completes.
  • Does this need documentation?
    • No.
    • Yes.

Validation:

  • ./run-fe-ut.sh --run org.apache.doris.catalog.EnvStateListenerTest,org.apache.doris.catalog.EnvTest,org.apache.doris.qe.StmtExecutorTest: 34 tests passed.
  • New deterministic tests cover INIT/UNKNOWN → FOLLOWER/OBSERVER interrupted by UNKNOWN, actual replayer readiness updates, initialization retry/completion, initialized UNKNOWN behavior, metadata expiry, and ignore_meta_check. With the two serving gates disabled, all five new cases fail; they pass with the fix.
  • cd fe && mvn checkstyle:check -pl fe-core and git diff --check: passed.
  • Full FE build using ./build.sh --fe: passed.
  • Deployed the FE build to an existing single-FE sandbox and ran test_select_constant and test_numbers through run-regression-test.sh: both suites passed.
  • Restarted the FE with the final commit build; verified its version, SHOW FRONTENDS health, /metrics, and SELECT COUNT(*), SUM(number) FROM numbers("number"="1000") returning 1000, 499500. UNKNOWN interruption interleavings are covered by unit tests; no multi-FE network-failure test was run.

Check List (For Reviewer who merge this PR)

  • Confirm the release note
  • Confirm test cases
  • Confirm document
  • Add branch pick label

### What problem does this PR solve?

Issue Number: N/A

Related PR: apache#68302

Problem Summary:

An initial FOLLOWER or OBSERVER transition can be interrupted by UNKNOWN before
metadata post-processing, daemon startup, and metrics initialization run. The
replayer can still publish readiness, and the retained INIT/UNKNOWN state handles
UNKNOWN without completing initialization. This can release startup services and
allow local queries against an incompletely initialized FE.

Gate public readiness and read eligibility on completion of the first successful
MASTER/FOLLOWER/OBSERVER initialization and FE type commit. Initialization waits
use metadata readiness directly to avoid a circular wait. Keep the gate open for
an already initialized FE entering UNKNOWN, preserving its metadata-based read
policy. Include both readiness conditions in startup wait diagnostics.

Exercise real replayer updates at the interruption boundary, successful retries,
all non-master initialization steps, initialized UNKNOWN reads and metadata
expiry, and ignore_meta_check. Separate listener creation from thread startup so
the event interleaving can be tested deterministically.

### Release note

Fix FE startup transitions that could expose a follower or observer before
initialization completed when an UNKNOWN notification interrupted startup.

### Check List (For Author)

- Test: Unit Test
  - ./run-fe-ut.sh --run org.apache.doris.catalog.EnvStateListenerTest,org.apache.doris.catalog.EnvTest,org.apache.doris.qe.StmtExecutorTest
  - All 34 tests passed; the 5 new regression cases failed with serving gates disabled.
  - cd fe && mvn checkstyle:check -pl fe-core
- Behavior changed: Yes. Startup services and local reads require completed initialization; initialized UNKNOWN nodes retain the existing read policy.
- Does this need documentation: No
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@morrySnow

Copy link
Copy Markdown
Contributor Author

/review

@morrySnow

Copy link
Copy Markdown
Contributor Author

run buildall

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static review opinion: approve; no blocking or actionable issue found at 9f6a76192aeb2073b7a45172c110989c22c70e83.

Critical checkpoints:

  • Goal and correctness: The change correctly separates replayer-owned metadata freshness from one-time serving readiness. Raw isReady/canRead updates cannot release startup services or local reads until the state listener finishes the first MASTER/FOLLOWER/OBSERVER initialization, commits feType, and publishes the volatile gate.
  • Scope and clarity: The implementation is focused on Env readiness semantics plus deterministic state-listener tests. The listener factory extraction preserves production meta-context and startup behavior.
  • Concurrency and lifecycle: I traced the BDB callback, transfer queue, state-listener thread, replayer thread, main waitForReady thread, and readiness-dependent daemons. The volatile gate is written after initialization and role assignment; public readers acquire it before consulting the atomic metadata flags. Interrupted INIT/UNKNOWN to FOLLOWER/OBSERVER transitions remain fail-closed and retry correctly. After successful startup, UNKNOWN retains the existing read policy while replay error and metadata expiry still close readiness/readability.
  • Parallel paths and compatibility: MASTER, BDB, non-BDB, and Cloud serving startup all reach the same listener publication. Checkpoint/snapshot Env paths are not alternate serving-startup paths. No configuration, persistence, EditLog, transaction, storage-format, FE-BE protocol, or rolling-upgrade compatibility change is introduced.
  • Conditions, errors, and performance: The queue-interruption condition has a concrete stale-transition purpose and leaves initialization uncommitted. No new silent error path, lock-order issue, or material performance concern was found; the extra volatile read is limited to readiness checks.
  • Tests: The added cases cover INIT/UNKNOWN to FOLLOWER/OBSERVER interrupted by UNKNOWN, real replayer flag updates, retry/completion ordering, sampled initialization callbacks, initialized UNKNOWN behavior, freshness expiry, ignore_meta_check, and listener cleanup. MASTER/Cloud/non-BDB behavior was verified statically through the shared listener commit. Per the review prompt, I did not run builds or tests; the author's reported 34 FE unit tests, checkstyle/build, regression suites, and manual restart remain author-provided validation rather than independent execution.
  • Observability: Startup wait logging now distinguishes metadata readiness from initialization publication, which is sufficient for this lifecycle change. No additional metric is needed.
  • User focus: No additional user-provided focus points were supplied.

Round 1 converged across the main review, two complementary full-review agents, and a separate lifecycle risk review, all with NO_NEW_VALUABLE_FINDINGS. No inline comments are proposed.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 27836 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 9f6a76192aeb2073b7a45172c110989c22c70e83, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17621	3796	3752	3752
q2	2247	365	313	313
q3	9998	1382	793	793
q4	4684	471	352	352
q5	7510	837	542	542
q6	185	181	140	140
q7	760	771	593	593
q8	9363	1591	1527	1527
q9	5410	4233	4158	4158
q10	6812	1324	1018	1018
q11	427	268	239	239
q12	632	410	289	289
q13	18110	2610	2010	2010
q14	270	264	235	235
q15	q16	739	715	680	680
q17	1791	1133	978	978
q18	6528	5579	5557	5557
q19	1362	1222	1062	1062
q20	487	391	265	265
q21	5809	3260	3018	3018
q22	455	375	315	315
Total cold run time: 101200 ms
Total hot run time: 27836 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4667	4675	4389	4389
q2	725	581	535	535
q3	4790	5134	4605	4605
q4	2215	2336	1452	1452
q5	4515	4388	4610	4388
q6	244	174	131	131
q7	1789	1701	1476	1476
q8	2316	2015	2003	2003
q9	7306	7204	7179	7179
q10	3683	3611	3122	3122
q11	506	373	339	339
q12	699	706	504	504
q13	2266	2558	1999	1999
q14	276	269	257	257
q15	q16	679	686	605	605
q17	7263	6766	6655	6655
q18	11774	11081	11610	11081
q19	1121	1012	978	978
q20	2198	2199	1933	1933
q21	5047	4086	4277	4086
q22	510	448	404	404
Total cold run time: 64589 ms
Total hot run time: 58121 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 152078 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 9f6a76192aeb2073b7a45172c110989c22c70e83, data reload: false

query5	4307	600	459	459
query6	428	216	188	188
query7	4803	551	288	288
query8	318	181	175	175
query9	8774	3961	3916	3916
query10	441	302	251	251
query11	5955	3563	3243	3243
query12	146	92	86	86
query13	1274	573	408	408
query14	6519	4504	4196	4196
query14_1	3938	3937	3963	3937
query15	217	195	185	185
query16	995	411	418	411
query17	911	680	548	548
query18	2437	461	333	333
query19	198	180	144	144
query20	83	82	80	80
query21	223	143	118	118
query22	13039	12973	12799	12799
query23	13903	13128	12377	12377
query23_1	12489	12493	12418	12418
query24	7255	1179	652	652
query24_1	722	719	693	693
query25	565	442	374	374
query26	1270	319	168	168
query27	2687	556	317	317
query28	4552	1960	1993	1960
query29	1627	741	542	542
query30	293	213	183	183
query31	890	759	639	639
query32	139	102	96	96
query33	522	324	252	252
query34	1222	1137	649	649
query35	723	752	653	653
query36	812	794	686	686
query37	149	109	95	95
query38	1822	1769	1668	1668
query39	715	696	667	667
query39_1	663	627	640	627
query40	230	128	110	110
query41	72	73	69	69
query42	100	96	96	96
query43	336	346	296	296
query44	1365	718	714	714
query45	193	181	168	168
query46	1099	1173	753	753
query47	1483	1509	1449	1449
query48	395	406	289	289
query49	602	398	285	285
query50	991	342	253	253
query51	10456	10367	10597	10367
query52	86	86	75	75
query53	234	247	177	177
query54	259	203	190	190
query55	79	74	70	70
query56	219	202	213	202
query57	1376	1454	1308	1308
query58	278	267	246	246
query59	1954	2072	1854	1854
query60	277	237	222	222
query61	145	147	145	145
query62	393	318	267	267
query63	206	174	183	174
query64	2756	974	803	803
query65	3467	3421	3424	3421
query66	1774	415	304	304
query67	19980	20263	19964	19964
query68	3212	1517	876	876
query69	423	340	254	254
query70	908	809	816	809
query71	295	222	218	218
query72	2576	2498	2174	2174
query73	812	790	436	436
query74	4620	4505	4278	4278
query75	2346	2282	1958	1958
query76	2304	1092	760	760
query77	351	395	299	299
query78	9062	9017	8415	8415
query79	1345	1117	748	748
query80	1230	441	384	384
query81	589	318	282	282
query82	681	169	123	123
query83	308	224	190	190
query84	312	139	114	114
query85	877	461	384	384
query86	406	233	232	232
query87	1988	1957	1821	1821
query88	3683	2756	2717	2717
query89	364	279	239	239
query90	1970	180	178	178
query91	166	166	126	126
query92	102	89	90	89
query93	1517	1381	882	882
query94	715	351	286	286
query95	664	451	333	333
query96	1068	802	340	340
query97	2417	2427	2322	2322
query98	158	151	144	144
query99	715	723	616	616
Total cold run time: 236712 ms
Total hot run time: 152078 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 24.03 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 9f6a76192aeb2073b7a45172c110989c22c70e83, data reload: false

query1	0.01	0.01	0.00
query2	0.10	0.05	0.04
query3	0.26	0.14	0.13
query4	1.61	0.14	0.14
query5	0.25	0.22	0.22
query6	1.16	0.97	0.94
query7	0.04	0.00	0.00
query8	0.05	0.04	0.04
query9	0.41	0.35	0.35
query10	0.56	0.57	0.55
query11	0.20	0.15	0.14
query12	0.19	0.15	0.15
query13	0.47	0.47	0.49
query14	0.98	0.94	0.93
query15	0.61	0.58	0.59
query16	0.31	0.31	0.33
query17	1.10	1.10	1.11
query18	0.22	0.20	0.20
query19	2.10	2.00	1.93
query20	0.02	0.02	0.01
query21	15.43	0.21	0.14
query22	4.85	0.06	0.05
query23	16.16	0.31	0.12
query24	2.99	0.42	0.32
query25	0.11	0.05	0.03
query26	0.73	0.20	0.15
query27	0.04	0.03	0.03
query28	3.57	0.84	0.34
query29	12.48	4.00	3.19
query30	0.28	0.15	0.15
query31	2.77	0.55	0.31
query32	3.22	0.60	0.50
query33	3.13	3.26	3.24
query34	15.53	3.94	3.26
query35	3.23	3.21	3.24
query36	0.56	0.45	0.42
query37	0.09	0.07	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.18	0.14	0.14
query41	0.09	0.03	0.02
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.26 s
Total hot run time: 24.03 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE UT Coverage Report

Increment line coverage 93.33% (14/15) 🎉
Increment coverage report
Complete coverage report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants