This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new d6c5a8da688 [test](regression) Stabilize update_after_create_rollup
and add test_writer_profile (#70309)
d6c5a8da688 is described below
commit d6c5a8da68853d2265cd6afd0656f27ccf6382ca
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Sat Nov 7 05:42:23 2026 +0800
[test](regression) Stabilize update_after_create_rollup and add
test_writer_profile (#70309)
### Background
`query_p0/update/update_after_create_rollup` checks partial `UPDATE` on
a merge-on-write table that has a rollup. `ALTER TABLE ... ADD ROLLUP`
starts an FE job that sends one alter task per tablet to the BEs, and
`SHOW ALTER TABLE ROLLUP` reports the job's state. Separately, a load
through the move-memtable sink (`enable_memtable_on_sink_node`, on by
default) can add a `DeltaWriterV2 <tablet>` and a `MemTableWriter
<tablet>` child to its profile for each tablet; since #64620 the BE
attaches them only when the session's `profile_level` is at least 2, the
default.
### What problem does this PR solve?
Issue Number: None
Related PR: #65310 (the branch-4.1 fix of the rollup suite by @shuke987,
ported here), #59863 (added test_writer_profile on branch-4.0, by
@0AyanamiRei), #65232 (pins its first half to profile level 1 on
branch-4.1, by @shuke987), #64620 (the master gate that
test_writer_profile covers), #64378 (made profile level 2 the default),
#61842 (moved the rollup suite from nereids_p0 to query_p0)
PR Type: Test
Problem Summary:
`update_after_create_rollup` sleeps 10 s after `ADD ROLLUP` and then
requires EXPLAIN of an unrelated GROUP BY to pick `rollup1`, so it fails
whenever the rollup job takes longer; as in #65310, it now waits until
the job reports FINISHED. `test_writer_profile`, which branch-4.x has
and master lacks, checks that a load's profile hides the writer details
at profile level 1 and shows them at level 2; master has had that gate
since #64620, with no test. The rollup suite becomes identical to
branch-4.2; `test_writer_profile` also waits for `COMPLETE` profiles and
honors TLS.
### Details
- **Failure:** `update_after_create_rollup` has not failed on its own in
master's public pipelines: since June 30, P0 ran it 7,257 times and
cloud_p0 739 times, and all 55 failures were in builds where most suites
failed. A forced slow rollup job reproduces it (see Testing).
- **Cause:** The rollup job converts all 54 tablets on the BEs, so how
long it takes depends on the BE's alter task queue, while the suite
allows a fixed 10 s. The EXPLAIN check also depends on the optimizer
choosing the rollup, which suites such as `rollup_p0/test_rollup_agg`
cover.
- **Stability evidence:** `getAlterRollupFinalState` polls `SHOW ALTER
TABLE ROLLUP` every second for up to 300 s and returns the final state,
so a CANCELLED job still fails. With each tablet's alter task delayed by
5 s, master's suite fails at the EXPLAIN check and the ported one passes
after 91 s.
- **Scenarios:** In `test_writer_profile`, an `INSERT INTO ... SELECT`
at `profile_level=1`, whose profile must contain neither `DeltaWriterV2`
nor `MemTableWriter`, then the same INSERT at `profile_level=2`, whose
profile must contain both; both checks wait for a `COMPLETE` profile,
which the BE reports after the INSERT returns; cloud mode is skipped.
- **What existing tests miss:** The closest suite,
`query_profile/test_load_channel_profile`, turns
`enable_memtable_on_sink_node` off and checks only that level 3 shows
writer details; no suite checks the level-1 gate of the move-memtable
sink.
- **Fails when broken:** Without `set profile_level=1`, the first half
fails with `should not contain DeltaWriterV2`, as a missing gate would
make it; with the second INSERT at level 1, the second half fails with
`should contain DeltaWriterV2`.
- **External dependencies:** Both INSERTs read `load/data by line.json`
from the regression bucket through the `S3` TVF.
### Testing
All runs used `./run-regression-test.sh --run -d query_p0/update -s
update_after_create_rollup` or `--run -d query_profile -s
test_writer_profile` against a local single-FE, single-BE cluster built
from master.
| Suite | Version | Result |
|---|---|---|
| `update_after_create_rollup` | master | passes |
| `update_after_create_rollup` | this PR | passes; the job was FINISHED
about 1 s after `ADD ROLLUP` |
| `update_after_create_rollup` | master, with BE debug point
`SchemaChangeJob::process_alter_tablet.leave.sleep` (5 s per tablet) |
fails: `Explain and check failed, expect contains 'rollup1'`, with the
job RUNNING at 9/54 tasks |
| `update_after_create_rollup` | this PR, same debug point | passes
after waiting 91 s |
| `update_after_create_rollup` | this PR, with `CANCEL ALTER TABLE
ROLLUP` right after `ADD ROLLUP` | fails as it should: `expected:
<FINISHED> but was: <CANCELLED>` |
| `test_writer_profile` | this PR | passes; each profile was `COMPLETE`
at the first read, the level-2 one has a `DeltaWriterV2` and a
`MemTableWriter` child, the level-1 one neither |
| `test_writer_profile` | this PR without #65232's `set profile_level=1`
| fails: `should not contain DeltaWriterV2 ==> expected: <false> but
was: <true>` |
| `test_writer_profile` | this PR, second INSERT at level 1 | fails as
it should: `should contain DeltaWriterV2 ==> expected: <true> but was:
<false>` |
My local regression config's OSS key is rejected (`InvalidAccessKeyId`),
so the `test_writer_profile` runs used a copy whose INSERT reads
`numbers("number" = "2")` instead of the `S3` TVF; nothing else differs.
The PR's NonConcurrent pipeline runs that suite as committed, and P0 and
cloud_p0 run the rollup suite.
### Notes for Reviewers
- After the CI review, `test_writer_profile` finds each INSERT's profile
by a marker through `ProfileAction`, where branch-4.2 reads the newest
LOAD profile over plain HTTP 500 ms after the INSERT.
- Two more suites from the same branch-4.1 batch need nothing on master:
master's renamed `test_jdbc_refresh_catalog_schema_refresh_non_blocking`
(#65126) already has #65335's fixes, and master #65696 replaced #65234's
suite with an FE unit test.
Co-authored-by: shuke <[email protected]>
Co-authored-by: Refrain <[email protected]>
---
.../update/update_after_create_rollup.groovy | 11 +--
.../query_profile/test_writer_profile.groovy | 92 ++++++++++++++++++++++
2 files changed, 93 insertions(+), 10 deletions(-)
diff --git
a/regression-test/suites/query_p0/update/update_after_create_rollup.groovy
b/regression-test/suites/query_p0/update/update_after_create_rollup.groovy
index 1442e235742..d1dbaaaffe4 100644
--- a/regression-test/suites/query_p0/update/update_after_create_rollup.groovy
+++ b/regression-test/suites/query_p0/update/update_after_create_rollup.groovy
@@ -123,16 +123,7 @@ suite('update_after_create_rollup') {
sql """
ALTER TABLE mow_table ADD ROLLUP rollup1(event_date, event_time,
user_id, country, update_time)
"""
- sleep(10000)
- explain {
- sql('''
- SELECT event_date, country, count(*)
- FROM mow_table
- WHERE event_date = '2025-09-22'
- GROUP BY event_date, country
- ''')
- contains "rollup1"
- }
+ assertEquals("FINISHED", getAlterRollupFinalState("mow_table"))
// Test 1: UPDATE column not in rollup1 (city)
sql 'UPDATE mow_table SET city = "beijing" WHERE user_id = 2000'
diff --git a/regression-test/suites/query_profile/test_writer_profile.groovy
b/regression-test/suites/query_profile/test_writer_profile.groovy
new file mode 100644
index 00000000000..161bb601dd6
--- /dev/null
+++ b/regression-test/suites/query_profile/test_writer_profile.groovy
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.apache.doris.regression.action.ProfileAction
+
+suite('test_writer_profile', "nonConcurrent") {
+ //cloud-mode
+ if (isCloudMode()) {
+ return
+ }
+
+ sql "set enable_profile=true;"
+ sql "set profile_level=1;"
+
+ def s3Endpoint = getS3Endpoint()
+ def s3Region = getS3Region()
+ def ak = getS3AK()
+ def sk = getS3SK()
+ def s3Uri = "s3://${getS3BucketName()}/load/data by line.json"
+
+ sql "drop table if exists t;"
+ sql """
+ CREATE TABLE t(
+ a INT,
+ b INT
+ )
+ DUPLICATE KEY(a)
+ PROPERTIES("replication_num" = "1");
+ """
+
+ // The INSERTs below run on the master FE, which keeps their profiles.
ProfileAction reads them
+ // with HttpCliAction, which uses HTTPS when the regression config sets
enableTLS.
+ def master = sql_return_maparray("SHOW FRONTENDS").find {
it.IsMaster.toString() == "true" }
+ assertNotNull(master, "Cannot locate the master FE")
+ def profileAction = new ProfileAction(context,
+ new InetSocketAddress(master.Host.toString(),
master.HttpPort.toString().toInteger()))
+
+ // BE reports the writer profiles after the INSERT returns, so wait until
the profile of this
+ // INSERT, found by its marker, is COMPLETE before checking which writer
details it has.
+ def insertAndGetProfile = {
+ def marker =
"test_writer_profile_${UUID.randomUUID().toString().replace('-', '')}"
+ sql """
+ /* ${marker} */ INSERT INTO t
+ SELECT * FROM S3(
+ "uri" = "$s3Uri",
+ "s3.access_key" = "$ak",
+ "s3.secret_key" = "$sk",
+ "s3.endpoint" = "${s3Endpoint}",
+ "s3.region" = "${s3Region}",
+ "format" = "json",
+ "read_json_by_line" = "true"
+ );
+ """
+ def profileString = profileAction.getProfileBySql(marker, [], 60000L,
500L)
+ logger.info(profileString)
+ return profileString
+ }
+
+ try {
+ def profileString = insertAndGetProfile()
+ assertFalse(profileString.contains("DeltaWriterV2"), "should not
contain DeltaWriterV2")
+ assertFalse(profileString.contains("MemTableWriter"), "should not
contain MemTableWriter")
+ } finally {
+ sql "set enable_profile=false;"
+ }
+
+ sql "set enable_profile=true;"
+ sql "set profile_level=2;"
+
+ try {
+ def profileString = insertAndGetProfile()
+ assertTrue(profileString.contains("DeltaWriterV2"), "should contain
DeltaWriterV2")
+ assertTrue(profileString.contains("MemTableWriter"), "should contain
MemTableWriter")
+ } finally {
+ sql "set enable_profile=false;"
+ sql "set profile_level=1;"
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]