Skip to content

[fix](fe) Keep CDC end offset consistent with current progress#65688

Merged
JNSimba merged 2 commits into
apache:masterfrom
JNSimba:fix_pg_latest_alter_cred_flaky
Jul 20, 2026
Merged

[fix](fe) Keep CDC end offset consistent with current progress#65688
JNSimba merged 2 commits into
apache:masterfrom
JNSimba:fix_pg_latest_alter_cred_flaky

Conversation

@JNSimba

@JNSimba JNSimba commented Jul 16, 2026

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: None

Related PR: None

Problem Summary:

Streaming CDC jobs periodically fetch the source end offset, while a successful task commits its current offset independently. A task can advance beyond the previously fetched end offset. The FE previously converted the offset comparison into a boolean, so it could stop scheduling but could not distinguish equality from the current offset being ahead, leaving CurrentOffset greater than EndOffset in job output.

This change preserves the three-way comparison result and advances EndOffset to CurrentOffset when the fetched end is behind. End-offset publication is synchronized so an obsolete comparison result cannot overwrite a newer fetched end. The PostgreSQL latest-offset credential regression case now waits for the first task to commit the resolved latest offset before inserting new rows.

Release note

Keep the displayed streaming CDC end offset from falling behind committed current progress after offset comparison.

Check List (For Author)

  • Test

    • Regression test
    • Unit Test
    • Verification was not run at user request. Focused FE unit coverage and regression coverage are included in this PR.
  • Behavior changed:

    • Yes. EndOffset is advanced to CurrentOffset when the committed current position is ahead of the fetched end position.
  • Does this need documentation?

    • No.

Check List (For Reviewer who merge this PR)

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

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

Copilot AI 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.

Pull request overview

This PR fixes streaming CDC job end-offset reporting in FE so that the published EndOffset cannot lag behind the committed CurrentOffset when the task has progressed beyond a previously fetched end offset. It also adds targeted FE unit coverage and hardens a PostgreSQL CDC regression case by waiting for the first committed task before inserting new rows.

Changes:

  • Preserve the three-way offset comparison result and, when the fetched end is behind, advance EndOffset to the committed current binlog offset.
  • Synchronize end-offset publication so a stale compare result can’t overwrite a newer fetched end offset.
  • Add FE unit tests and adjust the Postgres “latest offset” regression test to wait for the first successful task commit.

Review Checkpoints (Part 1.3)

  • Goal & correctness: The intent is clear and is backed by a new FE unit test class plus a regression timing adjustment; one correctness issue remains in compareOffset() (see PR comment).
  • Scope/focus: Changes are focused to CDC offset comparison + synchronization and associated tests.
  • Concurrency: New locking around endBinlogOffset/hasMoreData looks consistent with existing splitsLock usage, and heavy RPC work remains outside the lock.
  • Test coverage: Added FE unit coverage for the new comparison behavior and a regression stabilization for Postgres “latest offset”.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
regression-test/suites/job_p0/streaming_job/cdc/tvf/test_streaming_job_cdc_stream_postgres_latest_alter_cred.groovy Waits for first successful task commit (resolved latest offset) before inserting new rows to reduce flakiness.
fe/fe-core/src/test/java/org/apache/doris/job/offset/jdbc/JdbcSourceOffsetProviderOffsetTest.java Adds FE unit tests to validate end-offset advancement and stale-compare overwrite protection.
fe/fe-core/src/main/java/org/apache/doris/job/offset/jdbc/JdbcSourceOffsetProvider.java Implements three-way compare handling, advances EndOffset when behind, and synchronizes end-offset publication.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 390 to +392
Integer cmp = parseCdcResponseData(
result.getResponse(), new TypeReference<Integer>() {});
return cmp != null && cmp > 0;
return cmp;
@JNSimba

JNSimba commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

run buildall

@JNSimba

JNSimba commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

/review

@hello-stephen

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

------ Round 1 ----------------------------------
============================================
q1	17733	4196	4062	4062
q2	2008	316	203	203
q3	10302	1444	828	828
q4	4674	473	339	339
q5	7568	870	575	575
q6	183	169	136	136
q7	774	830	618	618
q8	9329	1647	1683	1647
q9	5552	4351	4372	4351
q10	6771	1733	1478	1478
q11	503	361	338	338
q12	727	586	468	468
q13	18111	3454	2860	2860
q14	269	275	247	247
q15	q16	791	799	713	713
q17	1034	918	936	918
q18	6919	5688	5539	5539
q19	1205	1332	1157	1157
q20	876	694	605	605
q21	5867	2672	2595	2595
q22	440	356	301	301
Total cold run time: 101636 ms
Total hot run time: 29978 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4459	4349	4311	4311
q2	301	318	219	219
q3	4554	4925	4396	4396
q4	2089	2159	1379	1379
q5	4380	4297	4265	4265
q6	232	176	130	130
q7	1699	1995	1849	1849
q8	2561	2248	2232	2232
q9	7958	8056	7751	7751
q10	4768	4643	4206	4206
q11	575	423	386	386
q12	748	771	557	557
q13	3288	3613	3032	3032
q14	301	314	279	279
q15	q16	714	737	656	656
q17	1390	1362	1402	1362
q18	7943	7284	7207	7207
q19	1161	1127	1075	1075
q20	2231	2202	1954	1954
q21	5296	4621	4486	4486
q22	516	467	402	402
Total cold run time: 57164 ms
Total hot run time: 52134 ms

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

Automated review summary

Overall: Request changes. The signed comparison handles the direct CurrentOffset > EndOffset case correctly, but asynchronous end-offset publication is still unsafe in both completion orders described in the inline comment.

Critical checkpoint conclusions:

  • Goal and proof: argument order/sign are correct and the new unit tests prove the positive/negative paths plus stale compare/current replacement. They do not cover an unchanged zero result, equal-valued refresh, or stale fetch completion, so the intended invariant is not fully proved.
  • Scope and clarity: the production changes are focused on CDC offset publication and mirror the binlog commit update in both base and TVF providers.
  • Concurrency: metadata fetch, task scheduling/compare, and transaction/ALTER/replay publication run on independent paths; BE forwarding is concurrent. RPCs remain outside the single splitsLock, with no new deadlock or heavy-under-lock issue, but fetch responses lack the generation/state validation applied to compare responses.
  • Lifecycle and persistence: committed current progress remains covered by existing bop/attachment/checkpoint and cloud/non-cloud replay paths; fetched EndOffset is intentionally transient. No static initialization, reference-cycle, or release issue was found.
  • Configuration and compatibility: no config, persisted format, or wire payload changed. /api/compareOffset still returns first.compareTo(second), and sign-only handling is compatible with non-canonical comparator magnitudes.
  • Parallel paths and conditions: base/TVF and shared-nothing/cloud current-offset paths are aligned; sign branches are otherwise correct. The successful-null response issue at line 404 is already covered by the existing Copilot thread and is not duplicated here.
  • Tests and results: SucceedTaskCount >= 1 is ordered after the transaction callback publishes the resolved latest offset, so the regression readiness gate is valid; no expected-result file changed. The two missing concurrency cases should be added with the fix.
  • Observability and performance: existing RPC logs/metrics are adequate. The equal-value reference churn can defeat idle backoff and run empty loads.
  • Transactions, data, and protocol state: no table-data visibility, delete-bitmap, memory-accounting, or new FE-BE variable issue applies. Current-offset publication occurs before task success accounting.
  • Validation: static review only, as the review-runner instructions prohibit builds and local test execution.

User focus: no additional focus was provided; the full PR was reviewed.

if (endBinlogOffset == null || !endBinlogOffset.equals(newEndOffset)) {
hasMoreData = true;
}
endBinlogOffset = newEndOffset;

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.

[P2] Make fetch publication participate in stale-state validation

Putting the assignment under splitsLock does not ensure that the asynchronously fetched value is current, and it interacts badly with the new reference-identity guard in both directions:

  1. If a compare snapshots E1, an unchanged periodic fetch is deserialized as E2; this assignment replaces the reference even though the values are equal. A valid zero comparison then looks stale, returns true, and can dispatch an empty load instead of idling.
  2. If a fetch starts at E, then a task commits C > E and the negative compare branch promotes EndOffset to C, the older fetch can finish afterward and lower EndOffset back to E, recreating the exact CurrentOffset > EndOffset state this change is fixing.

The BE forwards these requests on a concurrent heavy-work pool, so both completion orders are possible. Please snapshot/version current and end state around fetchEndOffset, preserve the existing map reference for a value-equal response, and reject a response made stale by intervening progress. The focused tests should cover both the equal-replacement and reverse-completion interleavings.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This interval will be very short; the next correction will take place after 500ms.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 178145 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 ce5dfd7865ce98b8bfc295454de40d389427d202, data reload: false

query5	4301	625	484	484
query6	478	229	217	217
query7	4854	588	336	336
query8	336	190	177	177
query9	8768	4213	4173	4173
query10	469	364	317	317
query11	5819	2326	2168	2168
query12	164	107	104	104
query13	1258	607	425	425
query14	6235	5304	4964	4964
query14_1	4311	4311	4335	4311
query15	215	212	186	186
query16	994	497	470	470
query17	943	720	593	593
query18	2446	484	356	356
query19	214	200	154	154
query20	113	108	107	107
query21	235	166	142	142
query22	13561	13535	13365	13365
query23	17524	16744	16177	16177
query23_1	16292	16288	16220	16220
query24	7543	1792	1275	1275
query24_1	1276	1311	1317	1311
query25	569	460	405	405
query26	1334	349	211	211
query27	2622	619	393	393
query28	4439	2000	2004	2000
query29	1091	628	497	497
query30	336	258	230	230
query31	1114	1095	985	985
query32	105	66	66	66
query33	552	338	268	268
query34	1157	1164	649	649
query35	768	785	671	671
query36	1233	1193	1064	1064
query37	197	111	90	90
query38	1884	1691	1661	1661
query39	884	865	850	850
query39_1	827	819	850	819
query40	249	162	141	141
query41	65	64	63	63
query42	92	92	93	92
query43	325	321	277	277
query44	1481	764	764	764
query45	197	191	175	175
query46	1067	1188	736	736
query47	2101	2071	1908	1908
query48	425	441	307	307
query49	581	420	311	311
query50	1063	442	341	341
query51	10792	10489	10392	10392
query52	87	86	77	77
query53	272	282	198	198
query54	275	243	215	215
query55	73	73	65	65
query56	319	280	282	280
query57	1329	1266	1195	1195
query58	291	271	252	252
query59	1606	1657	1441	1441
query60	332	281	261	261
query61	155	150	145	145
query62	553	495	430	430
query63	246	206	201	201
query64	2814	1031	821	821
query65	4740	4670	4635	4635
query66	1839	507	377	377
query67	29377	29209	29106	29106
query68	3106	1601	960	960
query69	396	298	273	273
query70	1069	992	950	950
query71	375	338	343	338
query72	3029	2759	2351	2351
query73	820	778	416	416
query74	5077	4942	4676	4676
query75	2545	2491	2120	2120
query76	2308	1202	815	815
query77	351	384	276	276
query78	11909	11970	11414	11414
query79	1376	1147	768	768
query80	1288	557	488	488
query81	527	334	292	292
query82	643	158	118	118
query83	381	333	301	301
query84	324	160	133	133
query85	986	620	521	521
query86	436	279	278	278
query87	1836	1825	1754	1754
query88	3709	2777	2784	2777
query89	435	375	329	329
query90	1948	200	194	194
query91	199	201	165	165
query92	64	59	57	57
query93	1670	1434	938	938
query94	719	331	322	322
query95	781	597	463	463
query96	1056	822	341	341
query97	2619	2645	2562	2562
query98	214	211	199	199
query99	1093	1133	967	967
Total cold run time: 263857 ms
Total hot run time: 178145 ms

@hello-stephen

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

query1	0.01	0.01	0.01
query2	0.12	0.05	0.05
query3	0.25	0.13	0.12
query4	1.61	0.14	0.13
query5	0.24	0.24	0.23
query6	1.24	1.09	1.09
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.42	0.34	0.33
query10	0.57	0.58	0.58
query11	0.20	0.15	0.14
query12	0.18	0.14	0.14
query13	0.49	0.50	0.50
query14	1.04	1.01	1.00
query15	0.64	0.62	0.61
query16	0.33	0.33	0.34
query17	1.14	1.12	1.08
query18	0.24	0.22	0.22
query19	2.06	1.95	1.98
query20	0.01	0.01	0.02
query21	15.46	0.22	0.13
query22	4.89	0.06	0.06
query23	16.14	0.32	0.13
query24	2.95	0.42	0.31
query25	0.09	0.04	0.06
query26	0.73	0.20	0.15
query27	0.05	0.04	0.03
query28	3.56	1.00	0.58
query29	12.54	4.21	3.33
query30	0.27	0.16	0.16
query31	2.77	0.61	0.33
query32	3.22	0.62	0.49
query33	3.27	3.25	3.24
query34	15.44	4.40	3.59
query35	3.53	3.51	3.51
query36	0.57	0.46	0.44
query37	0.09	0.06	0.06
query38	0.05	0.04	0.03
query39	0.04	0.03	0.03
query40	0.19	0.16	0.15
query41	0.08	0.02	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.9 s
Total hot run time: 25.44 s

@JNSimba

JNSimba commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

run p0

@liaoxin01 liaoxin01 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.

LGTM

@JNSimba
JNSimba merged commit c831663 into apache:master Jul 20, 2026
33 of 34 checks passed
github-actions Bot pushed a commit that referenced this pull request Jul 20, 2026
### What problem does this PR solve?

Streaming CDC jobs periodically fetch the source end offset, while a
successful task commits its current offset independently. A task can
advance beyond the previously fetched end offset. The FE previously
converted the offset comparison into a boolean, so it could stop
scheduling but could not distinguish equality from the current offset
being ahead, leaving CurrentOffset greater than EndOffset in job output.

This change preserves the three-way comparison result and advances
EndOffset to CurrentOffset when the fetched end is behind. End-offset
publication is synchronized so an obsolete comparison result cannot
overwrite a newer fetched end. The PostgreSQL latest-offset credential
regression case now waits for the first task to commit the resolved
latest offset before inserting new rows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants