This is an automated email from the ASF dual-hosted git repository.

luwei16 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 e85575e3ad6 [fix](binlog) Preserve row binlog compaction policy 
(#68033)
e85575e3ad6 is described below

commit e85575e3ad60389259dfe267a90124e6299a230a
Author: Luwei <[email protected]>
AuthorDate: Thu Sep 17 16:48:32 2026 +0800

    [fix](binlog) Preserve row binlog compaction policy (#68033)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Related PR: None
    
    Problem Summary: Changing a cloud table compaction policy sent the same
    policy to every visible index, including hidden row-binlog tablets.
    Those tablets require the dedicated binlog policy, so the ALTER
    persisted and synchronized an incompatible policy. Exclude row-binlog
    indexes from compaction-policy updates while preserving their inclusion
    for other tablet metadata updates.
    
    ### Release note
    
    Preserve the dedicated binlog compaction policy on hidden row-binlog
    tablets when altering a cloud table compaction policy.
    
    ### Check List (For Author)
    
    - Test: Unit Test
    - FE_UT_PARALLEL=1 bash run-fe-ut.sh --run CloudSchemaChangeHandlerTest
    - Behavior changed: Yes. Cloud compaction-policy ALTER no longer updates
    hidden row-binlog tablets.
    - Does this need documentation: No
---
 .../cloud/alter/CloudSchemaChangeHandler.java      |  4 +-
 .../cloud/alter/CloudSchemaChangeHandlerTest.java  | 89 ++++++++++++++++++++++
 2 files changed, 92 insertions(+), 1 deletion(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandler.java
 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandler.java
index 41c9827cb9a..fa861cdcec6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandler.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandler.java
@@ -476,7 +476,9 @@ public class CloudSchemaChangeHandler extends 
SchemaChangeHandler {
                 throw new DdlException(
                         "Partition[" + partitionName + "] does not exist in 
table[" + olapTable.getName() + "]");
             }
-            for (MaterializedIndex index : 
partition.getMaterializedIndices(IndexExtState.VISIBLE, true)) {
+            boolean includeRowBinlog = param.type != 
UpdatePartitionMetaParam.TabletMetaType.COMPACTION_POLICY;
+            for (MaterializedIndex index
+                    : partition.getMaterializedIndices(IndexExtState.VISIBLE, 
includeRowBinlog)) {
                 for (Tablet tablet : index.getTablets()) {
                     tabletIds.add(tablet.getId());
                 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandlerTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandlerTest.java
index 885e39052fb..5d1fcca0bfe 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandlerTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/cloud/alter/CloudSchemaChangeHandlerTest.java
@@ -155,6 +155,66 @@ public class CloudSchemaChangeHandlerTest {
         Assertions.assertEquals(Arrays.asList(103L), 
syncRequests.get(3).getTabletIdsList());
     }
 
+    @Test
+    public void testUpdateCompactionPolicyExcludesRowBinlogTablets() throws 
Exception {
+        CloudSchemaChangeHandler handler = new CloudSchemaChangeHandler();
+        Database db = createMockDatabaseWithRowBinlogTablet();
+        Env env = Mockito.mock(Env.class);
+        MetaServiceProxy metaServiceProxy = 
Mockito.mock(MetaServiceProxy.class);
+        
Mockito.when(metaServiceProxy.updateTablet(Mockito.any())).thenReturn(okUpdateTabletResponse());
+
+        Config.enable_debug_points = true;
+        
DebugPointUtil.addDebugPoint("CloudSchemaChangeHandler.notifyBackendsToSyncTabletMeta.skip");
+        try (MockedStatic<Env> envMock = Mockito.mockStatic(Env.class);
+                MockedStatic<MetaServiceProxy> metaProxyMock = 
Mockito.mockStatic(MetaServiceProxy.class)) {
+            envMock.when(Env::getCurrentEnv).thenReturn(env);
+            
metaProxyMock.when(MetaServiceProxy::getInstance).thenReturn(metaServiceProxy);
+
+            Map<String, String> properties = new HashMap<>();
+            properties.put(PropertyAnalyzer.PROPERTIES_COMPACTION_POLICY,
+                    PropertyAnalyzer.TIME_SERIES_COMPACTION_POLICY);
+            handler.updateTableProperties(db, "tbl", properties);
+        }
+
+        ArgumentCaptor<Cloud.UpdateTabletRequest> updateCaptor =
+                ArgumentCaptor.forClass(Cloud.UpdateTabletRequest.class);
+        Mockito.verify(metaServiceProxy).updateTablet(updateCaptor.capture());
+        List<Cloud.TabletMetaInfoPB> tabletMetaInfos = 
updateCaptor.getValue().getTabletMetaInfosList();
+        Assertions.assertEquals(Arrays.asList(101L), tabletMetaInfos.stream()
+                
.map(Cloud.TabletMetaInfoPB::getTabletId).collect(Collectors.toList()));
+        Assertions.assertTrue(tabletMetaInfos.stream().allMatch(info ->
+                
PropertyAnalyzer.TIME_SERIES_COMPACTION_POLICY.equals(info.getCompactionPolicy())));
+    }
+
+    @Test
+    public void testUpdateTtlIncludesRowBinlogTablets() throws Exception {
+        CloudSchemaChangeHandler handler = new CloudSchemaChangeHandler();
+        Database db = createMockDatabaseWithRowBinlogTablet();
+        Env env = Mockito.mock(Env.class);
+        MetaServiceProxy metaServiceProxy = 
Mockito.mock(MetaServiceProxy.class);
+        
Mockito.when(metaServiceProxy.updateTablet(Mockito.any())).thenReturn(okUpdateTabletResponse());
+
+        Config.enable_debug_points = true;
+        
DebugPointUtil.addDebugPoint("CloudSchemaChangeHandler.notifyBackendsToSyncTabletMeta.skip");
+        try (MockedStatic<Env> envMock = Mockito.mockStatic(Env.class);
+                MockedStatic<MetaServiceProxy> metaProxyMock = 
Mockito.mockStatic(MetaServiceProxy.class)) {
+            envMock.when(Env::getCurrentEnv).thenReturn(env);
+            
metaProxyMock.when(MetaServiceProxy::getInstance).thenReturn(metaServiceProxy);
+
+            Map<String, String> properties = new HashMap<>();
+            properties.put(PropertyAnalyzer.PROPERTIES_FILE_CACHE_TTL_SECONDS, 
"300");
+            handler.updateTableProperties(db, "tbl", properties);
+        }
+
+        ArgumentCaptor<Cloud.UpdateTabletRequest> updateCaptor =
+                ArgumentCaptor.forClass(Cloud.UpdateTabletRequest.class);
+        Mockito.verify(metaServiceProxy).updateTablet(updateCaptor.capture());
+        List<Cloud.TabletMetaInfoPB> tabletMetaInfos = 
updateCaptor.getValue().getTabletMetaInfosList();
+        Assertions.assertEquals(Arrays.asList(101L, 201L), 
tabletMetaInfos.stream()
+                
.map(Cloud.TabletMetaInfoPB::getTabletId).collect(Collectors.toList()));
+        Assertions.assertTrue(tabletMetaInfos.stream().allMatch(info -> 
info.getTtlSeconds() == 300));
+    }
+
     @Test
     public void testUpdateTablePropertiesThrowsWhenUpdateTabletFails() throws 
Exception {
         CloudSchemaChangeHandler handler = new CloudSchemaChangeHandler();
@@ -552,6 +612,8 @@ public class CloudSchemaChangeHandlerTest {
         Mockito.when(partition.getName()).thenReturn("p1");
         
Mockito.when(partition.getMaterializedIndices(MaterializedIndex.IndexExtState.VISIBLE,
 true))
                 .thenReturn(Arrays.asList(index));
+        
Mockito.when(partition.getMaterializedIndices(MaterializedIndex.IndexExtState.VISIBLE,
 false))
+                .thenReturn(Arrays.asList(index));
         Mockito.when(index.getTablets()).thenReturn(Arrays.asList(tablet1, 
tablet2, tablet3));
         Mockito.when(tablet1.getId()).thenReturn(101L);
         Mockito.when(tablet2.getId()).thenReturn(102L);
@@ -559,6 +621,33 @@ public class CloudSchemaChangeHandlerTest {
         return db;
     }
 
+    private Database createMockDatabaseWithRowBinlogTablet() throws Exception {
+        Database db = Mockito.mock(Database.class);
+        OlapTable table = Mockito.mock(OlapTable.class);
+        Partition partition = Mockito.mock(Partition.class);
+        MaterializedIndex baseIndex = Mockito.mock(MaterializedIndex.class);
+        MaterializedIndex rowBinlogIndex = 
Mockito.mock(MaterializedIndex.class);
+        org.apache.doris.catalog.Tablet baseTablet = 
Mockito.mock(org.apache.doris.catalog.Tablet.class);
+        org.apache.doris.catalog.Tablet rowBinlogTablet = 
Mockito.mock(org.apache.doris.catalog.Tablet.class);
+
+        Mockito.when(db.getTableOrMetaException("tbl", 
Table.TableType.OLAP)).thenReturn(table);
+        Mockito.when(table.getName()).thenReturn("tbl");
+        
Mockito.when(table.getCompactionPolicy()).thenReturn(PropertyAnalyzer.SIZE_BASED_COMPACTION_POLICY);
+        Mockito.when(table.getKeysType()).thenReturn(KeysType.DUP_KEYS);
+        
Mockito.when(table.getPartitions()).thenReturn(Arrays.asList(partition));
+        Mockito.when(table.getPartition("p1")).thenReturn(partition);
+        Mockito.when(partition.getName()).thenReturn("p1");
+        
Mockito.when(partition.getMaterializedIndices(MaterializedIndex.IndexExtState.VISIBLE,
 true))
+                .thenReturn(Arrays.asList(baseIndex, rowBinlogIndex));
+        
Mockito.when(partition.getMaterializedIndices(MaterializedIndex.IndexExtState.VISIBLE,
 false))
+                .thenReturn(Arrays.asList(baseIndex));
+        
Mockito.when(baseIndex.getTablets()).thenReturn(Arrays.asList(baseTablet));
+        
Mockito.when(rowBinlogIndex.getTablets()).thenReturn(Arrays.asList(rowBinlogTablet));
+        Mockito.when(baseTablet.getId()).thenReturn(101L);
+        Mockito.when(rowBinlogTablet.getId()).thenReturn(201L);
+        return db;
+    }
+
     private InternalService.PSyncTabletMetaResponse okSyncTabletMetaResponse() 
{
         return InternalService.PSyncTabletMetaResponse.newBuilder()
                 .setStatus(org.apache.doris.proto.Types.PStatus.newBuilder()


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to