This is an automated email from the ASF dual-hosted git repository.
Jackie-Jiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new 91fbab84f5d Move the segment assignment partition column to
SegmentAssignmentConfig (#19958)
91fbab84f5d is described below
commit 91fbab84f5d5100befd5171389dccf81c36db2bf
Author: Xiaotian (Jackie) Jiang <[email protected]>
AuthorDate: Thu Oct 22 11:25:54 2026 -0700
Move the segment assignment partition column to SegmentAssignmentConfig
(#19958)
---
.../assignment/InstanceAssignmentConfigUtils.java | 4 +-
.../utils/config/TableConfigSerDeUtilsTest.java | 46 ++--
.../api/resources/TableConfigValidationUtils.java | 19 +-
.../api/upload/SegmentValidationUtils.java | 56 ++---
.../strategy/SegmentAssignmentStrategyFactory.java | 74 +++---
.../api/upload/SegmentValidationUtilsTest.java | 8 +-
.../controller/helix/PinotResourceManagerTest.java | 2 -
.../instance/InstanceAssignmentTest.java | 3 +-
.../RealtimeReplicaGroupSegmentAssignmentTest.java | 11 +-
.../StrictRealtimeSegmentAssignmentTest.java | 9 +-
.../ReplicaGroupSegmentAssignmentStrategyTest.java | 18 +-
...nReplicaGroupSegmentAssignmentStrategyTest.java | 14 +-
.../RoundRobinSegmentAssignmentStrategyTest.java | 3 +-
.../SegmentAssignmentStrategyFactoryTest.java | 9 +-
.../tests/BaseClusterIntegrationTest.java | 12 +-
.../tests/BaseDedupIntegrationTest.java | 2 -
.../tests/DedupPreloadIntegrationTest.java | 2 -
.../tests/custom/OfflineUpsertTableTest.java | 17 +-
.../tests/custom/VectorUpsertTableTest.java | 2 -
.../simpleMeetup_realtime_table_config.json | 6 +-
.../segment/local/utils/TableConfigUtils.java | 198 +++++++++++++---
.../segment/local/utils/TableConfigUtilsTest.java | 263 ++++++++++++++++++++-
.../config/table/ReplicaGroupStrategyConfig.java | 4 +-
.../SegmentsValidationAndRetentionConfig.java | 9 +-
.../table/assignment/InstanceAssignmentConfig.java | 35 +--
.../InstanceReplicaGroupPartitionConfig.java | 9 +-
.../table/assignment/SegmentAssignmentConfig.java | 22 +-
.../apache/pinot/spi/utils/CommonConstants.java | 13 +
.../spi/utils/builder/TableConfigBuilder.java | 3 +-
.../userAttributes_offline_table_config.json | 3 +-
.../userFactEvents_offline_table_config.json | 6 +-
.../userGroups_offline_table_config.json | 6 +-
...upsertJsonMeetupRsvp_realtime_table_config.json | 1 -
.../upsertMeetupRsvp_realtime_table_config.json | 1 -
...ertPartialMeetupRsvp_realtime_table_config.json | 1 -
35 files changed, 625 insertions(+), 266 deletions(-)
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/assignment/InstanceAssignmentConfigUtils.java
b/pinot-common/src/main/java/org/apache/pinot/common/assignment/InstanceAssignmentConfigUtils.java
index d553cd377cd..0665f930f26 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/assignment/InstanceAssignmentConfigUtils.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/assignment/InstanceAssignmentConfigUtils.java
@@ -115,7 +115,9 @@ public class InstanceAssignmentConfigUtils {
SegmentsValidationAndRetentionConfig segmentConfig =
tableConfig.getValidationConfig();
int numReplicaGroups = tableConfig.getReplication();
ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
segmentConfig.getReplicaGroupStrategyConfig();
- Preconditions.checkState(replicaGroupStrategyConfig != null, "Failed to
find the replica-group strategy config");
+ Preconditions.checkState(replicaGroupStrategyConfig != null,
+ "Replica-group segment assignment requires the OFFLINE instance
assignment to be configured in "
+ + "'instanceAssignmentConfigMap'");
String partitionColumn = replicaGroupStrategyConfig.getPartitionColumn();
boolean minimizeDataMovement = segmentConfig.isMinimizeDataMovement();
if (partitionColumn != null) {
diff --git
a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java
b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java
index 4ddec5136ce..4aaa37e4363 100644
---
a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java
+++
b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java
@@ -32,9 +32,7 @@ import org.apache.pinot.spi.config.table.FieldConfig;
import org.apache.pinot.spi.config.table.HashFunction;
import org.apache.pinot.spi.config.table.QueryConfig;
import org.apache.pinot.spi.config.table.QuotaConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
-import org.apache.pinot.spi.config.table.SegmentsValidationAndRetentionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.TagOverrideConfig;
@@ -57,6 +55,7 @@ import
org.apache.pinot.spi.config.table.ingestion.ParallelSegmentConsumptionPol
import org.apache.pinot.spi.config.table.ingestion.StreamIngestionConfig;
import org.apache.pinot.spi.config.table.ingestion.TransformConfig;
import org.apache.pinot.spi.utils.CommonConstants;
+import org.apache.pinot.spi.utils.CommonConstants.Segment.AssignmentStrategy;
import org.apache.pinot.spi.utils.Enablement;
import org.apache.pinot.spi.utils.JsonUtils;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
@@ -145,24 +144,26 @@ public class TableConfigSerDeUtilsTest {
checkTenantConfigWithTagOverride(tableConfigToCompare);
}
{
- // With SegmentAssignmentStrategyConfig
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig = new
ReplicaGroupStrategyConfig("memberId", 5);
- TableConfig tableConfig =
tableConfigBuilder.setSegmentAssignmentConfigMap(
- Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig("ReplicaGroupSegmentAssignmentStrategy")))
- .setReplicaGroupStrategyConfig(replicaGroupStrategyConfig)
+ // With partitioned instance assignment config and segment assignment
config
+ InstanceAssignmentConfig instanceAssignmentConfig =
+ new InstanceAssignmentConfig(new
InstanceTagPoolConfig("tenant_OFFLINE", false, 0, null), null,
+ new InstanceReplicaGroupPartitionConfig(true, 0, 2, 0, 4, 1,
false, null), null, false);
+ TableConfig tableConfig = tableConfigBuilder
+
.setInstanceAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
instanceAssignmentConfig))
+
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
+ new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
"memberId")))
.build();
- checkSegmentAssignmentStrategyConfig(tableConfig);
+ checkSegmentAssignmentConfig(tableConfig);
// Serialize then de-serialize
TableConfig tableConfigToCompare =
JsonUtils.stringToObject(tableConfig.toJsonString(), TableConfig.class);
assertEquals(tableConfigToCompare, tableConfig);
- checkSegmentAssignmentStrategyConfig(tableConfigToCompare);
+ checkSegmentAssignmentConfig(tableConfigToCompare);
tableConfigToCompare =
TableConfigSerDeUtils.fromZNRecord(TableConfigSerDeUtils.toZNRecord(tableConfig));
assertEquals(tableConfigToCompare, tableConfig);
- checkSegmentAssignmentStrategyConfig(tableConfigToCompare);
+ checkSegmentAssignmentConfig(tableConfigToCompare);
}
{
// With completion config
@@ -441,18 +442,27 @@ public class TableConfigSerDeUtilsTest {
assertNull(tenantConfig.getTagOverrideConfig().getRealtimeCompleted());
}
- private void checkSegmentAssignmentStrategyConfig(TableConfig tableConfig) {
- SegmentsValidationAndRetentionConfig validationConfig =
tableConfig.getValidationConfig();
+ private void checkSegmentAssignmentConfig(TableConfig tableConfig) {
+ Map<String, InstanceAssignmentConfig> instanceAssignmentConfigMap =
tableConfig.getInstanceAssignmentConfigMap();
+ assertNotNull(instanceAssignmentConfigMap);
+ InstanceAssignmentConfig instanceAssignmentConfig =
+
instanceAssignmentConfigMap.get(InstancePartitionsType.OFFLINE.toString());
+ assertNotNull(instanceAssignmentConfig);
+ InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig =
+ instanceAssignmentConfig.getReplicaGroupPartitionConfig();
+ assertTrue(replicaGroupPartitionConfig.isReplicaGroupBased());
+ assertEquals(replicaGroupPartitionConfig.getNumReplicaGroups(), 2);
+ assertEquals(replicaGroupPartitionConfig.getNumPartitions(), 4);
+ assertEquals(replicaGroupPartitionConfig.getNumInstancesPerPartition(), 1);
+
Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
assertNotNull(segmentAssignmentConfigMap);
SegmentAssignmentConfig segmentAssignmentConfig =
segmentAssignmentConfigMap.get(InstancePartitionsType.OFFLINE.toString());
assertNotNull(segmentAssignmentConfig);
- assertEquals(segmentAssignmentConfig.getAssignmentStrategy(),
"ReplicaGroupSegmentAssignmentStrategy");
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
validationConfig.getReplicaGroupStrategyConfig();
- assertNotNull(replicaGroupStrategyConfig);
- assertEquals(replicaGroupStrategyConfig.getPartitionColumn(), "memberId");
- assertEquals(replicaGroupStrategyConfig.getNumInstancesPerPartition(), 5);
+ assertEquals(segmentAssignmentConfig.getAssignmentStrategy(),
+ AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY);
+ assertEquals(segmentAssignmentConfig.getPartitionColumn(), "memberId");
}
private void checkCompletionConfig(TableConfig tableConfig) {
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableConfigValidationUtils.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableConfigValidationUtils.java
index 58c3e96532a..4c7f7a6fd5b 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableConfigValidationUtils.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/TableConfigValidationUtils.java
@@ -23,6 +23,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.apache.helix.model.InstanceConfig;
import org.apache.pinot.common.assignment.InstanceAssignmentConfigUtils;
+import org.apache.pinot.common.assignment.InstancePartitions;
import org.apache.pinot.common.assignment.InstancePartitionsUtils;
import org.apache.pinot.controller.ControllerConf;
import org.apache.pinot.controller.helix.core.PinotHelixResourceManager;
@@ -120,7 +121,9 @@ public final class TableConfigValidationUtils {
}
/// Computes the instance partitions the table would get on creation, so
that an instance assignment that cannot be
- /// satisfied by the current instances is rejected before the table config
is persisted.
+ /// satisfied by the current instances is rejected before the table config
is persisted, and validates that the
+ /// OFFLINE segments are placed by partition when the OFFLINE instance
partitions have multiple partitions. This
+ /// covers pre-configured instance partitions, whose layout is not visible
in the table config.
private static void validateInstanceAssignment(PinotHelixResourceManager
resourceManager, TableConfig tableConfig) {
List<InstancePartitionsType> instancePartitionsTypes;
if (tableConfig.getTableType() == TableType.OFFLINE) {
@@ -131,14 +134,19 @@ public final class TableConfigValidationUtils {
instancePartitionsTypes = List.of(InstancePartitionsType.CONSUMING);
}
List<InstanceConfig> instanceConfigs =
resourceManager.getAllHelixInstanceConfigs();
+ InstancePartitions offlineInstancePartitions = null;
try {
for (InstancePartitionsType instancePartitionsType :
instancePartitionsTypes) {
+ InstancePartitions instancePartitions;
if (InstanceAssignmentConfigUtils.allowInstanceAssignment(tableConfig,
instancePartitionsType)) {
- InstanceAssignmentUtils.computeInstancePartitions(tableConfig,
instancePartitionsType,
+ instancePartitions =
InstanceAssignmentUtils.computeInstancePartitions(tableConfig,
instancePartitionsType,
resourceManager.getPropertyStore(), instanceConfigs, null);
} else {
-
InstancePartitionsUtils.computeDefaultInstancePartitions(resourceManager.getHelixZkManager(),
tableConfig,
- instancePartitionsType);
+ instancePartitions =
InstancePartitionsUtils.computeDefaultInstancePartitions(
+ resourceManager.getHelixZkManager(), tableConfig,
instancePartitionsType);
+ }
+ if (instancePartitionsType == InstancePartitionsType.OFFLINE) {
+ offlineInstancePartitions = instancePartitions;
}
}
} catch (Exception e) {
@@ -146,5 +154,8 @@ public final class TableConfigValidationUtils {
"Failed to calculate instance partitions for table: " +
tableConfig.getTableName() + ", reason: "
+ e.getMessage(), e);
}
+ if (offlineInstancePartitions != null &&
offlineInstancePartitions.getNumPartitions() > 1) {
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
InstancePartitionsType.OFFLINE.name());
+ }
}
}
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/upload/SegmentValidationUtils.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/upload/SegmentValidationUtils.java
index 88acb5e6b3d..1127d331a40 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/api/upload/SegmentValidationUtils.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/api/upload/SegmentValidationUtils.java
@@ -20,22 +20,16 @@ package org.apache.pinot.controller.api.upload;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nullable;
import javax.ws.rs.core.Response;
-import org.apache.commons.collections4.MapUtils;
-import org.apache.commons.lang3.StringUtils;
import
org.apache.pinot.controller.api.exception.ControllerApplicationException;
import org.apache.pinot.controller.validation.StorageQuotaChecker;
+import org.apache.pinot.segment.local.utils.TableConfigUtils;
import org.apache.pinot.segment.spi.ColumnMetadata;
import org.apache.pinot.segment.spi.SegmentMetadata;
-import org.apache.pinot.spi.config.table.IndexingConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
-import org.apache.pinot.spi.config.table.SegmentsValidationAndRetentionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
-import org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig;
-import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
-import
org.apache.pinot.spi.config.table.assignment.InstanceReplicaGroupPartitionConfig;
import org.apache.pinot.spi.utils.TimeUtils;
import org.joda.time.Interval;
import org.slf4j.Logger;
@@ -76,7 +70,7 @@ public class SegmentValidationUtils {
}
String partitionColumn = getPartitionColumn(tableConfig);
- if (StringUtils.isEmpty(partitionColumn)) {
+ if (partitionColumn == null) {
return;
}
@@ -90,46 +84,24 @@ public class SegmentValidationUtils {
}
}
+ /// Returns the partition column configured for segment assignment, falling
back to the single column of the segment
+ /// partition config, or `null` if neither is available.
+ @Nullable
private static String getPartitionColumn(TableConfig tableConfig) {
- if (!MapUtils.isEmpty(tableConfig.getInstanceAssignmentConfigMap())) {
- InstanceAssignmentConfig instanceAssignmentConfig =
-
tableConfig.getInstanceAssignmentConfigMap().get(InstancePartitionsType.OFFLINE.name());
- String partitionColumn = getPartitionColumn(instanceAssignmentConfig);
- if (StringUtils.isNotEmpty(partitionColumn)) {
- return partitionColumn;
- }
- }
-
- //noinspection deprecation
- SegmentsValidationAndRetentionConfig validationConfig =
tableConfig.getValidationConfig();
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
- validationConfig != null ?
validationConfig.getReplicaGroupStrategyConfig() : null;
- String partitionColumn =
- replicaGroupStrategyConfig != null ?
replicaGroupStrategyConfig.getPartitionColumn() : null;
- if (StringUtils.isNotEmpty(partitionColumn)) {
+ String partitionColumn = TableConfigUtils.getPartitionColumn(tableConfig);
+ if (partitionColumn != null) {
return partitionColumn;
}
-
- IndexingConfig indexingConfig = tableConfig.getIndexingConfig();
- SegmentPartitionConfig segmentPartitionConfig =
- indexingConfig != null ? indexingConfig.getSegmentPartitionConfig() :
null;
- Map<String, ?> columnPartitionMap =
- segmentPartitionConfig != null ?
segmentPartitionConfig.getColumnPartitionMap() : null;
- if (MapUtils.isNotEmpty(columnPartitionMap) && columnPartitionMap.size()
== 1) {
- return columnPartitionMap.keySet().iterator().next();
+ SegmentPartitionConfig segmentPartitionConfig =
tableConfig.getIndexingConfig().getSegmentPartitionConfig();
+ if (segmentPartitionConfig != null) {
+ Map<String, ?> columnPartitionMap =
segmentPartitionConfig.getColumnPartitionMap();
+ if (columnPartitionMap.size() == 1) {
+ return columnPartitionMap.keySet().iterator().next();
+ }
}
return null;
}
- private static String getPartitionColumn(InstanceAssignmentConfig
instanceAssignmentConfig) {
- if (instanceAssignmentConfig == null) {
- return null;
- }
- InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig =
- instanceAssignmentConfig.getReplicaGroupPartitionConfig();
- return replicaGroupPartitionConfig != null ?
replicaGroupPartitionConfig.getPartitionColumn() : null;
- }
-
public static void checkStorageQuota(String segmentName, long
tarSegmentSizeInBytes, long untarredSegmentSizeInBytes,
TableConfig tableConfig,
StorageQuotaChecker quotaChecker) {
diff --git
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactory.java
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactory.java
index c7b901393e4..03e2da94cf8 100644
---
a/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactory.java
+++
b/pinot-controller/src/main/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactory.java
@@ -19,6 +19,7 @@
package org.apache.pinot.controller.helix.core.assignment.segment.strategy;
import com.google.common.base.Preconditions;
+import java.util.Locale;
import java.util.Map;
import org.apache.helix.HelixManager;
import org.apache.pinot.common.assignment.InstancePartitions;
@@ -30,58 +31,22 @@ import
org.apache.pinot.spi.utils.CommonConstants.Segment.AssignmentStrategy;
/// Factory for SegmentAssignmentStrategy
public class SegmentAssignmentStrategyFactory {
-
private SegmentAssignmentStrategyFactory() {
}
- /// Determine Segment Assignment strategy
+ /// Returns the segment assignment strategy for the given instance
partitions type (`OFFLINE` or `COMPLETED`) or
+ /// tier: the strategy configured under that key in
`segmentAssignmentConfigMap`, otherwise the one derived from the
+ /// instance partitions.
public static SegmentAssignmentStrategy
getSegmentAssignmentStrategy(HelixManager helixManager,
TableConfig tableConfig, String assignmentType, InstancePartitions
instancePartitions) {
- String assignmentStrategy = null;
-
- TableType currentTableType = tableConfig.getTableType();
- // TODO: Handle segment assignment strategy in future for CONSUMING
segments in follow up PR
- // See https://github.com/apache/pinot/issues/9047
- // Accommodate new changes for assignment strategy
- Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
-
+ SegmentAssignmentStrategy segmentAssignmentStrategy;
if (tableConfig.isDimTable()) {
- // Segment Assignment Strategy for DIM tables
- Preconditions.checkState(currentTableType == TableType.OFFLINE,
+ // Dimension tables are always assigned to all servers
+ Preconditions.checkState(tableConfig.getTableType() == TableType.OFFLINE,
"All Servers Segment assignment Strategy is only applicable to Dim
OfflineTables");
- SegmentAssignmentStrategy segmentAssignmentStrategy = new
AllServersSegmentAssignmentStrategy();
- segmentAssignmentStrategy.init(helixManager, tableConfig);
- return segmentAssignmentStrategy;
+ segmentAssignmentStrategy = new AllServersSegmentAssignmentStrategy();
} else {
- // Try to determine segment assignment strategy from table config
- if (segmentAssignmentConfigMap != null) {
- SegmentAssignmentConfig segmentAssignmentConfig;
- // Use the pre-defined segment assignment strategy
- segmentAssignmentConfig =
segmentAssignmentConfigMap.get(assignmentType.toUpperCase());
- // Segment assignment config is only applicable to offline tables and
completed segments of realtime tables
- if (segmentAssignmentConfig != null) {
- assignmentStrategy =
segmentAssignmentConfig.getAssignmentStrategy().toLowerCase();
- }
- }
- }
-
- // Use the existing information to determine segment assignment strategy
- SegmentAssignmentStrategy segmentAssignmentStrategy;
- if (assignmentStrategy == null) {
- // Calculate numReplicaGroups and numPartitions to determine segment
assignment strategy
- Preconditions
- .checkState(instancePartitions != null, "Failed to find instance
partitions for segment assignment strategy");
- int numReplicaGroups = instancePartitions.getNumReplicaGroups();
- int numPartitions = instancePartitions.getNumPartitions();
-
- if (numReplicaGroups == 1 && numPartitions == 1) {
- segmentAssignmentStrategy = new BalancedNumSegmentAssignmentStrategy();
- } else {
- segmentAssignmentStrategy = new
ReplicaGroupSegmentAssignmentStrategy();
- }
- } else {
- // Set segment assignment strategy depending on strategy set in table
config
- switch (assignmentStrategy) {
+ switch (getAssignmentStrategy(tableConfig, assignmentType,
instancePartitions)) {
case AssignmentStrategy.ROUND_ROBIN_SEGMENT_ASSIGNMENT_STRATEGY:
segmentAssignmentStrategy = new
RoundRobinSegmentAssignmentStrategy();
break;
@@ -93,6 +58,7 @@ public class SegmentAssignmentStrategyFactory {
break;
case AssignmentStrategy.BALANCE_NUM_SEGMENT_ASSIGNMENT_STRATEGY:
default:
+ // Existing tables may carry a strategy name that was never
recognized, which has always run as balanced
segmentAssignmentStrategy = new
BalancedNumSegmentAssignmentStrategy();
break;
}
@@ -100,4 +66,24 @@ public class SegmentAssignmentStrategyFactory {
segmentAssignmentStrategy.init(helixManager, tableConfig);
return segmentAssignmentStrategy;
}
+
+ /// Returns the strategy name configured under the instance partitions type
or tier name, if any, otherwise the one
+ /// derived from the instance partitions: balanced unless they have multiple
replica-groups or partitions.
+ private static String getAssignmentStrategy(TableConfig tableConfig, String
assignmentType,
+ InstancePartitions instancePartitions) {
+ // TODO: Handle the segment assignment strategy for CONSUMING segments, see
+ // https://github.com/apache/pinot/issues/9047
+ Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
+ if (segmentAssignmentConfigMap != null) {
+ SegmentAssignmentConfig segmentAssignmentConfig =
segmentAssignmentConfigMap.get(assignmentType);
+ if (segmentAssignmentConfig != null &&
segmentAssignmentConfig.getAssignmentStrategy() != null) {
+ return
segmentAssignmentConfig.getAssignmentStrategy().toLowerCase(Locale.ROOT);
+ }
+ }
+ Preconditions.checkState(instancePartitions != null,
+ "Failed to find instance partitions for segment assignment strategy");
+ return instancePartitions.getNumReplicaGroups() == 1 &&
instancePartitions.getNumPartitions() == 1
+ ? AssignmentStrategy.BALANCE_NUM_SEGMENT_ASSIGNMENT_STRATEGY
+ : AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY;
+ }
}
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/api/upload/SegmentValidationUtilsTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/api/upload/SegmentValidationUtilsTest.java
index c0e320cf62a..d58cb9db913 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/api/upload/SegmentValidationUtilsTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/api/upload/SegmentValidationUtilsTest.java
@@ -25,7 +25,6 @@ import
org.apache.pinot.controller.api.exception.ControllerApplicationException;
import org.apache.pinot.segment.spi.ColumnMetadata;
import org.apache.pinot.segment.spi.SegmentMetadata;
import org.apache.pinot.spi.config.table.ColumnPartitionConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
@@ -34,6 +33,7 @@ import
org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
import
org.apache.pinot.spi.config.table.assignment.InstanceReplicaGroupPartitionConfig;
import org.apache.pinot.spi.config.table.assignment.InstanceTagPoolConfig;
+import org.apache.pinot.spi.config.table.assignment.SegmentAssignmentConfig;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
import org.testng.annotations.Test;
@@ -127,10 +127,11 @@ public class SegmentValidationUtilsTest {
TableConfig tableConfig = new TableConfigBuilder(TableType.OFFLINE)
.setTableName(RAW_TABLE_NAME)
.setUpsertConfig(new UpsertConfig(UpsertConfig.Mode.FULL))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(Map.of(PARTITION_COLUMN,
new ColumnPartitionConfig("Murmur", NUM_PARTITIONS),
"otherPartitionColumn",
new ColumnPartitionConfig("Modulo", NUM_PARTITIONS))))
+
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.name(),
+ new SegmentAssignmentConfig(null, PARTITION_COLUMN)))
.build();
SegmentValidationUtils.validateUpsertSegmentPartitionMetadata(mockSegmentMetadata(Set.of(1)),
tableConfig);
@@ -140,7 +141,8 @@ public class SegmentValidationUtilsTest {
return new TableConfigBuilder(TableType.OFFLINE)
.setTableName(RAW_TABLE_NAME)
.setUpsertConfig(new UpsertConfig(UpsertConfig.Mode.FULL))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1))
+
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.name(),
+ new SegmentAssignmentConfig(null, PARTITION_COLUMN)))
.build();
}
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/PinotResourceManagerTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/PinotResourceManagerTest.java
index eea36b23659..d16331690b2 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/PinotResourceManagerTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/PinotResourceManagerTest.java
@@ -31,7 +31,6 @@ import org.apache.pinot.common.utils.LLCSegmentName;
import org.apache.pinot.controller.helix.core.PinotHelixResourceManager;
import org.apache.pinot.controller.utils.SegmentMetadataMockUtils;
import org.apache.pinot.core.realtime.impl.fakestream.FakeStreamConfigUtils;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.UpsertConfig;
@@ -75,7 +74,6 @@ public class PinotResourceManagerTest {
TableConfig realtimeTableConfig =
new
TableConfigBuilder(TableType.REALTIME).setTableName(RAW_TABLE_NAME).setNumReplicas(NUM_REPLICAS)
.setStreamConfigs(streamConfigs)
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1))
.setUpsertConfig(new UpsertConfig(UpsertConfig.Mode.FULL)).build();
_resourceManager.addTable(realtimeTableConfig);
}
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/instance/InstanceAssignmentTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/instance/InstanceAssignmentTest.java
index 23661254021..941f8c6a7cf 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/instance/InstanceAssignmentTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/instance/InstanceAssignmentTest.java
@@ -81,7 +81,7 @@ public class InstanceAssignmentTest {
.setServerTenant(TENANT_NAME)
.setNumReplicas(numReplicas)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY)))
+ new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
.build();
int numInstancesPerPartition = 2;
tableConfig.getValidationConfig()
@@ -2769,7 +2769,6 @@ public class InstanceAssignmentTest {
.setInstanceAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
new InstanceAssignmentConfig(tagPoolConfig, null,
replicaPartitionConfig,
InstanceAssignmentConfig.PartitionSelector.FD_AWARE_INSTANCE_PARTITION_SELECTOR.toString(),
false)))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(partitionColumnName, numInstancesPerReplicaGroup))
.setSegmentPartitionConfig(segmentPartitionConfig)
.build();
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/RealtimeReplicaGroupSegmentAssignmentTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/RealtimeReplicaGroupSegmentAssignmentTest.java
index 3952bcc2273..68dd2c110e5 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/RealtimeReplicaGroupSegmentAssignmentTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/RealtimeReplicaGroupSegmentAssignmentTest.java
@@ -32,13 +32,10 @@ import
org.apache.pinot.common.assignment.InstancePartitions;
import org.apache.pinot.common.restlet.resources.RebalanceConfig;
import org.apache.pinot.common.utils.LLCSegmentName;
import org.apache.pinot.core.realtime.impl.fakestream.FakeStreamConfigUtils;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
-import org.apache.pinot.spi.config.table.assignment.SegmentAssignmentConfig;
import
org.apache.pinot.spi.utils.CommonConstants.Helix.StateModel.SegmentStateModel;
-import org.apache.pinot.spi.utils.CommonConstants.Segment.AssignmentStrategy;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -55,7 +52,6 @@ import static org.testng.Assert.assertTrue;
@SuppressWarnings("unchecked")
public class RealtimeReplicaGroupSegmentAssignmentTest {
private static final int NUM_REPLICAS = 3;
- private static final String PARTITION_COLUMN = "partitionColumn";
private static final int NUM_PARTITIONS = 4;
private static final int NUM_SEGMENTS = 24;
private static final String CONSUMING_INSTANCE_NAME_PREFIX =
"consumingInstance_";
@@ -87,10 +83,7 @@ public class RealtimeReplicaGroupSegmentAssignmentTest {
Map<String, String> streamConfigs =
FakeStreamConfigUtils.getDefaultLowLevelStreamConfigs().getStreamConfigsMap();
TableConfig tableConfig =
new
TableConfigBuilder(TableType.REALTIME).setTableName(RAW_TABLE_NAME).setNumReplicas(NUM_REPLICAS)
- .setStreamConfigs(streamConfigs)
-
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.COMPLETED.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY)))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1)).build();
+ .setStreamConfigs(streamConfigs).build();
_segmentAssignment =
SegmentAssignmentFactory.getSegmentAssignment(createHelixManager(),
tableConfig, null);
_instancePartitionsMap = new TreeMap<>();
@@ -654,8 +647,6 @@ public class RealtimeReplicaGroupSegmentAssignmentTest {
new
TableConfigBuilder(TableType.REALTIME).setTableName(RAW_TABLE_NAME).setNumReplicas(numReplicas)
.setStreamConfigs(streamConfigs)
.setInstancePartitionsMap(importedInstancePartitions)
-
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.COMPLETED.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY)))
.build();
assertTrue(InstanceAssignmentConfigUtils.shouldRelocateCompletedSegments(tableConfig),
"Imported COMPLETED instance partitions must trigger completed-segment
relocation during rebalance");
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/StrictRealtimeSegmentAssignmentTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/StrictRealtimeSegmentAssignmentTest.java
index 833be993b47..85aa85afb75 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/StrictRealtimeSegmentAssignmentTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/StrictRealtimeSegmentAssignmentTest.java
@@ -40,15 +40,12 @@ import org.apache.pinot.common.tier.TierSegmentSelector;
import org.apache.pinot.common.utils.LLCSegmentName;
import org.apache.pinot.core.realtime.impl.fakestream.FakeStreamConfigUtils;
import org.apache.pinot.spi.config.table.DedupConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.UpsertConfig;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
-import org.apache.pinot.spi.config.table.assignment.SegmentAssignmentConfig;
import
org.apache.pinot.spi.utils.CommonConstants.Helix.StateModel.SegmentStateModel;
import org.apache.pinot.spi.utils.CommonConstants.Segment;
-import org.apache.pinot.spi.utils.CommonConstants.Segment.AssignmentStrategy;
import org.apache.pinot.spi.utils.builder.TableConfigBuilder;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
@@ -66,7 +63,6 @@ import static org.testng.Assert.assertTrue;
@SuppressWarnings("unchecked")
public class StrictRealtimeSegmentAssignmentTest {
private static final int NUM_REPLICAS = 3;
- private static final String PARTITION_COLUMN = "partitionColumn";
private static final int NUM_PARTITIONS = 4;
private static final int NUM_SEGMENTS = 24;
private static final String CONSUMING_INSTANCE_NAME_PREFIX =
"consumingInstance_";
@@ -140,10 +136,7 @@ public class StrictRealtimeSegmentAssignmentTest {
private static SegmentAssignment createSegmentAssignment(String tableType,
HelixManager helixManager) {
TableConfigBuilder builder = new
TableConfigBuilder(TableType.REALTIME).setTableName(RAW_TABLE_NAME)
.setNumReplicas(NUM_REPLICAS)
-
.setStreamConfigs(FakeStreamConfigUtils.getDefaultLowLevelStreamConfigs().getStreamConfigsMap())
-
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.COMPLETED.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY)))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1));
+
.setStreamConfigs(FakeStreamConfigUtils.getDefaultLowLevelStreamConfigs().getStreamConfigsMap());
TableConfig tableConfig;
if ("upsert".equalsIgnoreCase(tableType)) {
tableConfig = builder.setUpsertConfig(new
UpsertConfig(UpsertConfig.Mode.FULL)).build();
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/ReplicaGroupSegmentAssignmentStrategyTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/ReplicaGroupSegmentAssignmentStrategyTest.java
index a8996ed11b8..aacdfe5df65 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/ReplicaGroupSegmentAssignmentStrategyTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/ReplicaGroupSegmentAssignmentStrategyTest.java
@@ -38,7 +38,6 @@ import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignme
import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignmentTestUtils;
import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignmentUtils;
import org.apache.pinot.segment.spi.partition.metadata.ColumnPartitionMetadata;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
@@ -92,7 +91,8 @@ public class ReplicaGroupSegmentAssignmentStrategyTest {
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITHOUT_PARTITION)
.setNumReplicas(NUM_REPLICAS)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY))).build();
+ new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
+ .build();
_segmentAssignmentWithoutPartition =
SegmentAssignmentFactory.getSegmentAssignment(null,
tableConfigWithoutPartitions, null);
@@ -137,14 +137,13 @@ public class ReplicaGroupSegmentAssignmentStrategyTest {
when(helixManagerWithPartitions.getHelixPropertyStore()).thenReturn(propertyStoreWithPartitions);
int numInstancesPerPartition = numInstancesPerReplicaGroup / NUM_REPLICAS;
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
- new ReplicaGroupStrategyConfig(PARTITION_COLUMN,
numInstancesPerPartition);
TableConfig tableConfigWithPartitions =
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITH_PARTITION)
.setNumReplicas(NUM_REPLICAS)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY)))
- .setReplicaGroupStrategyConfig(replicaGroupStrategyConfig).build();
+ new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ PARTITION_COLUMN)))
+ .build();
_segmentAssignmentWithPartition =
SegmentAssignmentFactory.getSegmentAssignment(helixManagerWithPartitions,
tableConfigWithPartitions, null);
@@ -397,13 +396,12 @@ public class ReplicaGroupSegmentAssignmentStrategyTest {
when(helixManager.getHelixPropertyStore()).thenReturn(propertyStore);
int numInstancesPerPartition = NUM_INSTANCES / NUM_PARTITIONS;
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
- new ReplicaGroupStrategyConfig(PARTITION_COLUMN,
numInstancesPerPartition);
TableConfig tableConfigWithPartitions =
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITH_PARTITION).setNumReplicas(1)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY))).build();
-
tableConfigWithPartitions.getValidationConfig().setReplicaGroupStrategyConfig(replicaGroupStrategyConfig);
+ new
SegmentAssignmentConfig(AssignmentStrategy.REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ PARTITION_COLUMN)))
+ .build();
SegmentAssignment segmentAssignment =
SegmentAssignmentFactory.getSegmentAssignment(helixManager,
tableConfigWithPartitions, null);
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinReplicaGroupSegmentAssignmentStrategyTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinReplicaGroupSegmentAssignmentStrategyTest.java
index b018dce2613..23e64feb78f 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinReplicaGroupSegmentAssignmentStrategyTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinReplicaGroupSegmentAssignmentStrategyTest.java
@@ -37,7 +37,6 @@ import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignme
import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignmentTestUtils;
import
org.apache.pinot.controller.helix.core.assignment.segment.SegmentAssignmentUtils;
import org.apache.pinot.segment.spi.partition.metadata.ColumnPartitionMetadata;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
@@ -94,8 +93,9 @@ public class
RoundRobinReplicaGroupSegmentAssignmentStrategyTest {
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITHOUT_PARTITION)
.setNumReplicas(NUM_REPLICAS)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new SegmentAssignmentConfig(
-
AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY))).build();
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ null)))
+ .build();
_segmentAssignmentWithoutPartition =
SegmentAssignmentFactory.getSegmentAssignment(null,
tableConfigWithoutPartitions, null);
@@ -139,15 +139,13 @@ public class
RoundRobinReplicaGroupSegmentAssignmentStrategyTest {
when(helixManagerWithPartitions.getHelixPropertyStore()).thenReturn(propertyStoreWithPartitions);
int numInstancesPerPartition = numInstancesPerReplicaGroup /
NUM_PARTITIONS;
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
- new ReplicaGroupStrategyConfig(PARTITION_COLUMN,
numInstancesPerPartition);
TableConfig tableConfigWithPartitions =
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITH_PARTITION)
.setNumReplicas(NUM_REPLICAS)
- .setReplicaGroupStrategyConfig(replicaGroupStrategyConfig)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new SegmentAssignmentConfig(
-
AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY))).build();
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ PARTITION_COLUMN)))
+ .build();
_segmentAssignmentWithPartition =
SegmentAssignmentFactory.getSegmentAssignment(helixManagerWithPartitions,
tableConfigWithPartitions, null);
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinSegmentAssignmentStrategyTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinSegmentAssignmentStrategyTest.java
index 882d9257d6b..a3acd3ef0a3 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinSegmentAssignmentStrategyTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/RoundRobinSegmentAssignmentStrategyTest.java
@@ -64,7 +64,8 @@ public class RoundRobinSegmentAssignmentStrategyTest {
TableConfig tableConfig =
new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME).setNumReplicas(NUM_REPLICAS)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_SEGMENT_ASSIGNMENT_STRATEGY))).build();
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
+ .build();
_segmentAssignment = SegmentAssignmentFactory.getSegmentAssignment(null,
tableConfig, null);
// {
diff --git
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactoryTest.java
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactoryTest.java
index 0918f87d761..b1393f4d1db 100644
---
a/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactoryTest.java
+++
b/pinot-controller/src/test/java/org/apache/pinot/controller/helix/core/assignment/segment/strategy/SegmentAssignmentStrategyFactoryTest.java
@@ -59,7 +59,8 @@ public class SegmentAssignmentStrategyFactoryTest {
public void testSegmentAssignmentStrategyFromTableConfig() {
// Set segment assignment config map in table config for balanced num
segment assignment strategy
Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap = new
HashMap<>();
- segmentAssignmentConfigMap.put(InstancePartitionsType.OFFLINE.toString(),
new SegmentAssignmentConfig("Balanced"));
+ segmentAssignmentConfigMap.put(InstancePartitionsType.OFFLINE.toString(),
+ new SegmentAssignmentConfig("Balanced", null));
TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME)
.setSegmentAssignmentConfigMap(segmentAssignmentConfigMap).build();
@@ -119,10 +120,10 @@ public class SegmentAssignmentStrategyFactoryTest {
new ReplicaGroupStrategyConfig(PARTITION_COLUMN,
numInstancesPerPartition);
Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap = new
HashMap<>();
segmentAssignmentConfigMap.put(InstancePartitionsType.OFFLINE.toString(),
- new SegmentAssignmentConfig("ReplicaGroup"));
+ new SegmentAssignmentConfig("ReplicaGroup", null));
TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME_WITH_PARTITION)
-
.setNumReplicas(NUM_REPLICAS).setSegmentAssignmentConfigMap(segmentAssignmentConfigMap)
- .setReplicaGroupStrategyConfig(replicaGroupStrategyConfig).build();
+
.setNumReplicas(NUM_REPLICAS).setSegmentAssignmentConfigMap(segmentAssignmentConfigMap).build();
+
tableConfig.getValidationConfig().setReplicaGroupStrategyConfig(replicaGroupStrategyConfig);
// {
// 0_0=[instance_0, instance_1], 1_0=[instance_2, instance_3],
2_0=[instance_4, instance_5],
diff --git
a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTest.java
b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTest.java
index ba8218a01ce..327eae47fd0 100644
---
a/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTest.java
+++
b/pinot-integration-test-base/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTest.java
@@ -73,7 +73,6 @@ import
org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.DedupConfig;
import org.apache.pinot.spi.config.table.FieldConfig;
import org.apache.pinot.spi.config.table.QueryConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
@@ -305,11 +304,6 @@ public abstract class BaseClusterIntegrationTest extends
ClusterTest {
return null;
}
- @Nullable
- protected ReplicaGroupStrategyConfig getReplicaGroupStrategyConfig() {
- return null;
- }
-
/// Creates a new schema.
protected Schema createSchema()
throws IOException {
@@ -475,8 +469,7 @@ public abstract class BaseClusterIntegrationTest extends
ClusterTest {
.setStreamConfigs(getStreamConfigs())
.setNullHandlingEnabled(getNullHandlingEnabled())
.setSegmentPartitionConfig(getSegmentPartitionConfig())
- .setOptimizeNoDictStatsCollection(true)
- .setReplicaGroupStrategyConfig(getReplicaGroupStrategyConfig());
+ .setOptimizeNoDictStatsCollection(true);
}
/// Creates a new Upsert enabled table config.
@@ -504,7 +497,6 @@ public abstract class BaseClusterIntegrationTest extends
ClusterTest {
.setRoutingConfig(
new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(primaryKeyColumn, 1))
.setOptimizeNoDictStatsCollection(true)
.setUpsertConfig(upsertConfig)
.build();
@@ -563,7 +555,6 @@ public abstract class BaseClusterIntegrationTest extends
ClusterTest {
.setRoutingConfig(
new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(primaryKeyColumn, 1))
.setOptimizeNoDictStatsCollection(true)
.setUpsertConfig(upsertConfig)
.build();
@@ -589,7 +580,6 @@ public abstract class BaseClusterIntegrationTest extends
ClusterTest {
.setRoutingConfig(
new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(primaryKeyColumn, 1))
.setDedupConfig(new DedupConfig())
.setOptimizeNoDictStatsCollection(true)
.build();
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseDedupIntegrationTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseDedupIntegrationTest.java
index be8adb5570c..b4bce719828 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseDedupIntegrationTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseDedupIntegrationTest.java
@@ -33,7 +33,6 @@ import org.apache.pinot.core.routing.SegmentsToQuery;
import org.apache.pinot.core.transport.ServerInstance;
import org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.DedupConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
@@ -169,7 +168,6 @@ public class BaseDedupIntegrationTest extends
BaseClusterIntegrationTestSet {
.setRoutingConfig(
new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(primaryKeyColumn, 2))
.setDedupConfig(dedupConfig)
.build();
if (PauselessConsumptionUtils.isPauselessEnabled(tableConfig)) {
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/DedupPreloadIntegrationTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/DedupPreloadIntegrationTest.java
index aabda566d7e..731955fc06c 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/DedupPreloadIntegrationTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/DedupPreloadIntegrationTest.java
@@ -27,7 +27,6 @@ import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.DedupConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
@@ -180,7 +179,6 @@ public class DedupPreloadIntegrationTest extends
BaseClusterIntegrationTestSet {
.setRoutingConfig(
new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(primaryKeyColumn, 1))
.setDedupConfig(dedupConfig)
.build();
}
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/OfflineUpsertTableTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/OfflineUpsertTableTest.java
index c5c68de0797..104b80d9b06 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/OfflineUpsertTableTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/OfflineUpsertTableTest.java
@@ -25,16 +25,21 @@ import java.util.List;
import java.util.Map;
import org.apache.pinot.client.ResultSet;
import org.apache.pinot.common.utils.TarCompressionUtils;
+import org.apache.pinot.common.utils.config.TagNameUtils;
import
org.apache.pinot.segment.local.segment.creator.impl.SegmentIndexCreationDriverImpl;
import org.apache.pinot.segment.local.segment.readers.GenericRowRecordReader;
import org.apache.pinot.segment.spi.creator.SegmentGeneratorConfig;
import org.apache.pinot.spi.config.table.ColumnPartitionConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.config.table.UpsertConfig;
+import org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig;
+import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
+import
org.apache.pinot.spi.config.table.assignment.InstanceReplicaGroupPartitionConfig;
+import org.apache.pinot.spi.config.table.assignment.InstanceTagPoolConfig;
+import org.apache.pinot.spi.config.table.assignment.SegmentAssignmentConfig;
import org.apache.pinot.spi.data.FieldSpec;
import org.apache.pinot.spi.data.Schema;
import org.apache.pinot.spi.data.readers.GenericRow;
@@ -102,6 +107,12 @@ public class OfflineUpsertTableTest extends
CustomDataQueryClusterIntegrationTes
Map<String, ColumnPartitionConfig> columnPartitionConfigMap = new
HashMap<>();
columnPartitionConfigMap.put(PRIMARY_KEY_COL, new
ColumnPartitionConfig("Murmur", NUM_PARTITIONS));
+ InstanceTagPoolConfig tagPoolConfig = new InstanceTagPoolConfig(
+ TagNameUtils.getOfflineTagForTenant(TagNameUtils.DEFAULT_TENANT_NAME),
false, 0, null);
+ InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig =
+ new InstanceReplicaGroupPartitionConfig(true, 0, 2, 0, NUM_PARTITIONS,
1, false, null);
+ InstanceAssignmentConfig instanceAssignmentConfig =
+ new InstanceAssignmentConfig(tagPoolConfig, null,
replicaGroupPartitionConfig, null, false);
return new TableConfigBuilder(TableType.OFFLINE)
.setTableName(TABLE_NAME)
@@ -111,7 +122,9 @@ public class OfflineUpsertTableTest extends
CustomDataQueryClusterIntegrationTes
.setRoutingConfig(new RoutingConfig(null, null,
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new
SegmentPartitionConfig(columnPartitionConfigMap))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(PRIMARY_KEY_COL, 1))
+
.setInstanceAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.name(),
instanceAssignmentConfig))
+
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.name(),
+ new SegmentAssignmentConfig(null, PRIMARY_KEY_COL)))
.build();
}
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/VectorUpsertTableTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/VectorUpsertTableTest.java
index 1ab4107b123..a3003306956 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/VectorUpsertTableTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/VectorUpsertTableTest.java
@@ -42,7 +42,6 @@ import
org.apache.pinot.segment.local.data.manager.TableDataManager;
import org.apache.pinot.server.starter.helix.BaseServerStarter;
import org.apache.pinot.spi.config.table.ColumnPartitionConfig;
import org.apache.pinot.spi.config.table.FieldConfig;
-import org.apache.pinot.spi.config.table.ReplicaGroupStrategyConfig;
import org.apache.pinot.spi.config.table.RoutingConfig;
import org.apache.pinot.spi.config.table.SegmentPartitionConfig;
import org.apache.pinot.spi.config.table.TableConfig;
@@ -317,7 +316,6 @@ public class VectorUpsertTableTest extends
CustomDataQueryClusterIntegrationTest
RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE, false))
.setSegmentPartitionConfig(new SegmentPartitionConfig(
Map.of(ENTITY_ID_COLUMN, new ColumnPartitionConfig("Murmur",
NUM_PARTITIONS))))
- .setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig(ENTITY_ID_COLUMN, 1))
.build();
}
diff --git
a/pinot-integration-tests/src/test/resources/simpleMeetup_realtime_table_config.json
b/pinot-integration-tests/src/test/resources/simpleMeetup_realtime_table_config.json
index 838df06bb51..9def7e24d14 100644
---
a/pinot-integration-tests/src/test/resources/simpleMeetup_realtime_table_config.json
+++
b/pinot-integration-tests/src/test/resources/simpleMeetup_realtime_table_config.json
@@ -5,11 +5,7 @@
"timeColumnName": "mtime",
"timeType": "MILLISECONDS",
"segmentPushType": "APPEND",
- "replicasPerPartition": "1",
- "replicaGroupStrategyConfig": {
- "partitionColumn": "event_id",
- "numInstancesPerPartition": 1
- }
+ "replicasPerPartition": "1"
},
"tenants": {},
"tableIndexConfig": {
diff --git
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
index 4e76120982b..b933a997ddb 100644
---
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
+++
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java
@@ -22,16 +22,17 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
@@ -84,6 +85,7 @@ import org.apache.pinot.spi.config.table.TimestampConfig;
import org.apache.pinot.spi.config.table.UpsertConfig;
import org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig;
import org.apache.pinot.spi.config.table.assignment.InstancePartitionsType;
+import
org.apache.pinot.spi.config.table.assignment.InstanceReplicaGroupPartitionConfig;
import org.apache.pinot.spi.config.table.assignment.SegmentAssignmentConfig;
import org.apache.pinot.spi.config.table.ingestion.AggregationConfig;
import org.apache.pinot.spi.config.table.ingestion.BatchIngestionConfig;
@@ -141,9 +143,10 @@ public final class TableConfigUtils {
private static final String KINESIS_STREAM_TYPE = "kinesis";
private static final String CONSUMING_SEGMENT_TIER = "consuming";
- private static final Set<String> UPSERT_DEDUP_ALLOWED_ROUTING_STRATEGIES =
-
ImmutableSet.of(RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE,
- RoutingConfig.MULTI_STAGE_REPLICA_GROUP_SELECTOR_TYPE);
+ private static final Set<String> UPSERT_DEDUP_ALLOWED_ROUTING_STRATEGIES =
Set.of(
+ RoutingConfig.STRICT_REPLICA_GROUP_INSTANCE_SELECTOR_TYPE,
+ RoutingConfig.MULTI_STAGE_REPLICA_GROUP_SELECTOR_TYPE
+ );
private static boolean _disableGroovy;
@@ -211,7 +214,8 @@ public final class TableConfigUtils {
existingOverriddenColumns);
validateValidationConfig(tableConfig, schema);
- validateSegmentAssignmentConfig(tableConfig);
+ validateSegmentAssignmentConfigs(tableConfig);
+ validatePartitionColumnConsistency(tableConfig);
validateIngestionConfig(tableConfig, schema, existingTableConfig);
if (tableConfig.getTableType() == TableType.REALTIME) {
validateStreamConfigMaps(tableConfig);
@@ -431,29 +435,79 @@ public final class TableConfigUtils {
validateRetentionConfig(tableConfig);
}
- private static void validateSegmentAssignmentConfig(TableConfig tableConfig)
{
+ /// Validates the segment assignment configs: the strategy must be a known
one (`allservers` for a dimension table),
+ /// and the partition column, which only applies to partition based
strategies, must be a column of the segment
+ /// partition config.
+ @VisibleForTesting
+ static void validateSegmentAssignmentConfigs(TableConfig tableConfig) {
Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
- if (segmentAssignmentConfigMap == null) {
+ if (MapUtils.isEmpty(segmentAssignmentConfigMap)) {
return;
}
- if (tableConfig.isDimTable()) {
- SegmentAssignmentConfig segmentAssignmentConfig =
-
segmentAssignmentConfigMap.get(InstancePartitionsType.OFFLINE.toString());
- if (segmentAssignmentConfig == null) {
- return;
- }
- String segmentAssignmentStrategy =
segmentAssignmentConfig.getAssignmentStrategy();
- if (segmentAssignmentStrategy != null
- &&
!segmentAssignmentStrategy.equalsIgnoreCase(AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY))
{
- throw new IllegalStateException(
- String.format("Dimension table: %s can only use '%s' segment
assignment strategy, found: %s",
- tableConfig.getTableName(),
-
CommonConstants.Segment.AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY,
- segmentAssignmentStrategy));
+ String tableName = tableConfig.getTableName();
+ boolean isDimTable = tableConfig.isDimTable();
+ for (Map.Entry<String, SegmentAssignmentConfig> entry :
segmentAssignmentConfigMap.entrySet()) {
+ String key = entry.getKey();
+ SegmentAssignmentConfig segmentAssignmentConfig = entry.getValue();
+ String assignmentStrategy =
segmentAssignmentConfig.getAssignmentStrategy();
+ boolean partitionBased = !isDimTable;
+ if (assignmentStrategy != null) {
+ assignmentStrategy = assignmentStrategy.toLowerCase(Locale.ROOT);
+ if (isDimTable) {
+
Preconditions.checkState(assignmentStrategy.equals(AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY),
+ "Dimension table: %s can only use '%s' segment assignment
strategy, found: %s", tableName,
+ AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY,
assignmentStrategy);
+ } else {
+
Preconditions.checkState(AssignmentStrategy.CONFIGURABLE_STRATEGIES.contains(assignmentStrategy),
+ "Invalid segment assignment strategy: %s for: %s of table: %s",
assignmentStrategy, key, tableName);
+ }
+ partitionBased =
AssignmentStrategy.PARTITION_BASED_STRATEGIES.contains(assignmentStrategy);
+ }
+ String partitionColumn = segmentAssignmentConfig.getPartitionColumn();
+ if (StringUtils.isNotEmpty(partitionColumn)) {
+ Preconditions.checkState(partitionBased,
+ "Partition column: %s does not apply to the segment assignment
strategy for: %s of table: %s",
+ partitionColumn, key, tableName);
+ validatePartitionColumnInSegmentPartitionConfig(tableConfig,
partitionColumn);
}
}
}
+ /// Validates that every place that configures the partition column for
segment assignment names the same column:
+ /// the segment assignment configs, and the deprecated instance assignment
configs and `replicaGroupStrategyConfig`
+ /// that existing tables may still carry. The column is resolved table-wide,
so a disagreement would be settled by
+ /// precedence and map iteration order.
+ @VisibleForTesting
+ static void validatePartitionColumnConsistency(TableConfig tableConfig) {
+ Set<String> partitionColumns = new TreeSet<>();
+ Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
+ if (segmentAssignmentConfigMap != null) {
+ for (SegmentAssignmentConfig segmentAssignmentConfig :
segmentAssignmentConfigMap.values()) {
+ addIfNotEmpty(partitionColumns,
segmentAssignmentConfig.getPartitionColumn());
+ }
+ }
+ Map<String, InstanceAssignmentConfig> instanceAssignmentConfigMap =
tableConfig.getInstanceAssignmentConfigMap();
+ if (instanceAssignmentConfigMap != null) {
+ for (InstanceAssignmentConfig instanceAssignmentConfig :
instanceAssignmentConfigMap.values()) {
+ addIfNotEmpty(partitionColumns,
instanceAssignmentConfig.getReplicaGroupPartitionConfig().getPartitionColumn());
+ }
+ }
+ ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
+ tableConfig.getValidationConfig().getReplicaGroupStrategyConfig();
+ if (replicaGroupStrategyConfig != null) {
+ addIfNotEmpty(partitionColumns,
replicaGroupStrategyConfig.getPartitionColumn());
+ }
+ Preconditions.checkState(partitionColumns.size() <= 1,
+ "Table: %s must configure the same partition column in
segmentAssignmentConfigMap, instanceAssignmentConfigMap "
+ + "and replicaGroupStrategyConfig, found: %s",
tableConfig.getTableName(), partitionColumns);
+ }
+
+ private static void addIfNotEmpty(Set<String> values, @Nullable String
value) {
+ if (StringUtils.isNotEmpty(value)) {
+ values.add(value);
+ }
+ }
+
private static boolean isValidPeerDownloadScheme(String
peerSegmentDownloadScheme) {
return
CommonConstants.HTTP_PROTOCOL.equalsIgnoreCase(peerSegmentDownloadScheme)
||
CommonConstants.HTTPS_PROTOCOL.equalsIgnoreCase(peerSegmentDownloadScheme);
@@ -1426,6 +1480,18 @@ public final class TableConfigUtils {
if (tableConfig.getInstanceAssignmentConfigMap() == null) {
return;
}
+ // Keys of the instance assignment configs that place OFFLINE segments:
the OFFLINE instance partitions and the
+ // tiers of an OFFLINE table
+ Set<String> offlineSegmentKeys = new HashSet<>();
+ if (tableConfig.getTableType() == TableType.OFFLINE) {
+ offlineSegmentKeys.add(InstancePartitionsType.OFFLINE.name());
+ List<TierConfig> tierConfigs = tableConfig.getTierConfigsList();
+ if (tierConfigs != null) {
+ for (TierConfig tierConfig : tierConfigs) {
+ offlineSegmentKeys.add(tierConfig.getName());
+ }
+ }
+ }
for (Map.Entry<String, InstanceAssignmentConfig>
instanceAssignmentConfigMapEntry
: tableConfig.getInstanceAssignmentConfigMap()
.entrySet()) {
@@ -1448,9 +1514,61 @@ public final class TableConfigUtils {
"numInstancesPerPartition must be 1 when using
IMPLICIT_REALTIME_TABLE_PARTITION_SELECTOR");
}
// TODO: Add more validations for other partition selectors here
+
+ InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig =
+ instanceAssignmentConfig.getReplicaGroupPartitionConfig();
+ // Explicitly partitioned instance partitions require the OFFLINE
segments to be placed by partition
+ if (offlineSegmentKeys.contains(instancePartitionsType) &&
replicaGroupPartitionConfig.isReplicaGroupBased()
+ && replicaGroupPartitionConfig.getNumPartitions() > 1) {
+ validatePartitionedSegmentAssignment(tableConfig,
instancePartitionsType);
+ }
+ }
+ }
+
+ /// Validates that OFFLINE segments are placed by partition for the given
instance partitions type or tier, which
+ /// is required when its instance partitions have multiple partitions. The
segment assignment strategy configured
+ /// for it, if any, must be partition based, and the partition column must
be resolvable: the column configured
+ /// for segment assignment must be a column of the segment partition config,
and without a configured column the
+ /// segment partition config must have exactly one column, which is how the
partition id of a segment is read from
+ /// its metadata. The OFFLINE instance partitions may also be
pre-configured, in which case the controller runs
+ /// this validation on the fetched ones. Dimension tables are exempt, since
their segments are assigned to all
+ /// servers regardless of the instance partitions.
+ public static void validatePartitionedSegmentAssignment(TableConfig
tableConfig, String key) {
+ if (tableConfig.isDimTable()) {
+ return;
+ }
+ Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
+ SegmentAssignmentConfig segmentAssignmentConfig =
+ segmentAssignmentConfigMap != null ?
segmentAssignmentConfigMap.get(key) : null;
+ String assignmentStrategy =
+ segmentAssignmentConfig != null ?
segmentAssignmentConfig.getAssignmentStrategy() : null;
+ if (assignmentStrategy != null) {
+ Preconditions.checkState(
+
AssignmentStrategy.PARTITION_BASED_STRATEGIES.contains(assignmentStrategy.toLowerCase(Locale.ROOT)),
+ "Segment assignment strategy: %s for: %s of table: %s must be
partition based because the instance "
+ + "partitions are partitioned", assignmentStrategy, key,
tableConfig.getTableName());
+ }
+ Map<String, ColumnPartitionConfig> columnPartitionMap =
getColumnPartitionMap(tableConfig);
+ Preconditions.checkState(!columnPartitionMap.isEmpty(),
+ "Offline table with partitioned instance partitions must have segment
partition config "
+ + "(segmentPartitionConfig in the indexingConfig) to resolve the
partition of a segment");
+ String partitionColumn = getPartitionColumn(tableConfig);
+ if (partitionColumn != null) {
+ validatePartitionColumnInSegmentPartitionConfig(tableConfig,
partitionColumn);
+ } else {
+ Preconditions.checkState(columnPartitionMap.size() == 1,
+ "Offline table with partitioned instance partitions must configure
the partition column (partitionColumn in "
+ + "the segment assignment config) when segment partition config
has multiple columns");
}
}
+ private static void
validatePartitionColumnInSegmentPartitionConfig(TableConfig tableConfig,
+ String partitionColumn) {
+
Preconditions.checkState(getColumnPartitionMap(tableConfig).containsKey(partitionColumn),
+ "Partition column: %s configured for segment assignment is not found
in segment partition config",
+ partitionColumn);
+ }
+
/// Validates the partial upsert-related configurations:
/// - Null handling must be enabled
/// - Merger cannot be applied to private key columns
@@ -2594,26 +2712,36 @@ public final class TableConfigUtils {
return tierOverwrites != null && tierOverwrites.isObject() ?
tierOverwrites.get(tier) : null;
}
- /// Get the partition column from tableConfig instance assignment config map.
- /// @param tableConfig table config
- /// @return partition column
+ /// Returns the partition column configured for segment assignment, or
`null` if none is configured. The column is
+ /// read from the segment assignment configs, falling back to the deprecated
partition column of the instance
+ /// assignment configs and then to the deprecated
`replicaGroupStrategyConfig`.
+ @Nullable
public static String getPartitionColumn(TableConfig tableConfig) {
- // check InstanceAssignmentConfigMap is null or empty,
- if (!MapUtils.isEmpty(tableConfig.getInstanceAssignmentConfigMap())) {
- for (InstanceAssignmentConfig instanceAssignmentConfig :
tableConfig.getInstanceAssignmentConfigMap().values()) {
- //check InstanceAssignmentConfig has the
InstanceReplicaGroupPartitionConfig with non-empty partitionColumn
- if
(StringUtils.isNotEmpty(instanceAssignmentConfig.getReplicaGroupPartitionConfig().getPartitionColumn()))
{
- return
instanceAssignmentConfig.getReplicaGroupPartitionConfig().getPartitionColumn();
+ // TODO: Revisit to resolve the partition column per key (instance
partitions type or tier) instead of returning
+ // the first configured one across all entries.
+ Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
tableConfig.getSegmentAssignmentConfigMap();
+ if (segmentAssignmentConfigMap != null) {
+ for (SegmentAssignmentConfig segmentAssignmentConfig :
segmentAssignmentConfigMap.values()) {
+ String partitionColumn = segmentAssignmentConfig.getPartitionColumn();
+ if (StringUtils.isNotEmpty(partitionColumn)) {
+ return partitionColumn;
+ }
+ }
+ }
+ Map<String, InstanceAssignmentConfig> instanceAssignmentConfigMap =
tableConfig.getInstanceAssignmentConfigMap();
+ if (instanceAssignmentConfigMap != null) {
+ for (InstanceAssignmentConfig instanceAssignmentConfig :
instanceAssignmentConfigMap.values()) {
+ String partitionColumn =
instanceAssignmentConfig.getReplicaGroupPartitionConfig().getPartitionColumn();
+ if (StringUtils.isNotEmpty(partitionColumn)) {
+ return partitionColumn;
}
}
}
-
- // for backward-compatibility, If partitionColumn value isn't there in
InstanceReplicaGroupPartitionConfig
- // check ReplicaGroupStrategyConfig for partitionColumn
- //noinspection deprecation
ReplicaGroupStrategyConfig replicaGroupStrategyConfig =
tableConfig.getValidationConfig().getReplicaGroupStrategyConfig();
- return replicaGroupStrategyConfig != null ?
replicaGroupStrategyConfig.getPartitionColumn() : null;
+ String partitionColumn =
+ replicaGroupStrategyConfig != null ?
replicaGroupStrategyConfig.getPartitionColumn() : null;
+ return StringUtils.isNotEmpty(partitionColumn) ? partitionColumn : null;
}
public static Set<String> getRelevantTags(TableConfig tableConfig) {
diff --git
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
index 66eef1d9794..ed33075921d 100644
---
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
+++
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java
@@ -21,6 +21,7 @@ package org.apache.pinot.segment.local.utils;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Throwables;
+import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -299,7 +300,7 @@ public class TableConfigUtilsTest {
tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
.setIsDimTable(true)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new
SegmentAssignmentConfig(AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY)))
+ new
SegmentAssignmentConfig(AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
.build();
TableConfigUtils.validate(tableConfig, schema);
@@ -307,7 +308,7 @@ public class TableConfigUtilsTest {
tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
.setIsDimTable(true)
.setSegmentAssignmentConfigMap(Map.of(InstancePartitionsType.OFFLINE.toString(),
- new SegmentAssignmentConfig("replicaGroup")))
+ new SegmentAssignmentConfig("replicaGroup", null)))
.build();
try {
TableConfigUtils.validate(tableConfig, schema);
@@ -3851,6 +3852,7 @@ public class TableConfigUtilsTest {
TableConfigUtils.validateTTLForUpsertConfig(tableConfigWithValidTimestampTTLConfig,
schema);
}
+ @SuppressWarnings("removal")
@Test
public void testValidatePartitionedReplicaGroupInstance() {
String partitionColumn = "testPartitionCol";
@@ -4300,18 +4302,259 @@ public class TableConfigUtilsTest {
assertNull(TableConfigUtils.getPartitionColumn(tableConfig));
}
- @SuppressWarnings("deprecation")
+ @SuppressWarnings("removal")
@Test
- public void testGetPartitionColumnWithReplicaGroupConfig() {
- ReplicaGroupStrategyConfig replicaGroupStrategyConfig = new
ReplicaGroupStrategyConfig(PARTITION_COLUMN, 1);
- TableConfig tableConfig = new
TableConfigBuilder(TableType.REALTIME).setTableName(TABLE_NAME).build();
+ public void testValidateAcceptsReplicaGroupStrategyConfig()
+ throws IOException {
+ Schema schema = new
Schema.SchemaBuilder().setSchemaName(TABLE_NAME).build();
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME).build();
+ tableConfig.getValidationConfig().setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig("myCol", 1));
+ // The deprecated config must still be parsed and accepted
+
TableConfigUtils.validate(JsonUtils.stringToObject(tableConfig.toJsonString(),
TableConfig.class), schema);
+ }
+
+ @Test
+ public void testValidateSegmentAssignmentConfigs() {
+ String offlineKey = InstancePartitionsType.OFFLINE.name();
+ SegmentPartitionConfig segmentPartitionConfig =
+ new SegmentPartitionConfig(Map.of("myCol", new
ColumnPartitionConfig("murmur", 4)));
+
+ // Both the strategy and the partition column are optional, and the
strategy is case insensitive
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(segmentPartitionConfig)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, null)))
+ .build();
+ TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, "myCol")));
+ TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ "myCol")));
+ TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig("ReplicaGroup", "myCol")));
+ TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_SEGMENT_ASSIGNMENT_STRATEGY,
null)));
+ TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig);
+
+ // The strategy must be a known one
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig("unknown", null)));
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig));
+ assertEquals(e.getMessage(),
+ "Invalid segment assignment strategy: unknown for: OFFLINE of table:
testTable_OFFLINE");
+
+ // The partition column only applies to partition based strategies
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.BALANCE_NUM_SEGMENT_ASSIGNMENT_STRATEGY,
"myCol")));
+ e = expectThrows(IllegalStateException.class, () ->
TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig));
+ assertEquals(e.getMessage(), "Partition column: myCol does not apply to
the segment assignment strategy for: "
+ + "OFFLINE of table: testTable_OFFLINE");
+ TableConfig dimTableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setIsDimTable(true)
+ .setSegmentPartitionConfig(segmentPartitionConfig)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, "myCol")))
+ .build();
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validateSegmentAssignmentConfigs(dimTableConfig));
+ assertEquals(e.getMessage(), "Partition column: myCol does not apply to
the segment assignment strategy for: "
+ + "OFFLINE of table: testTable_OFFLINE");
+
+ // The partition column must be a column of the segment partition config
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, "otherCol")));
+ e = expectThrows(IllegalStateException.class, () ->
TableConfigUtils.validateSegmentAssignmentConfigs(tableConfig));
+ assertEquals(e.getMessage(),
+ "Partition column: otherCol configured for segment assignment is not
found in segment partition config");
+ }
+
+ private static InstanceAssignmentConfig
createInstanceAssignmentConfig(@Nullable String partitionColumn) {
+ return new InstanceAssignmentConfig(new
InstanceTagPoolConfig("DefaultTenant_OFFLINE", false, 0, null), null,
+ new InstanceReplicaGroupPartitionConfig(true, 0, 2, 0, 4, 1, false,
partitionColumn), null, false);
+ }
+
+ @Test
+ public void testValidatePartitionedSegmentAssignment() {
+ String offlineKey = InstancePartitionsType.OFFLINE.name();
+ SegmentPartitionConfig singleColumnPartitionConfig =
+ new SegmentPartitionConfig(Map.of("myCol", new
ColumnPartitionConfig("murmur", 4)));
+ SegmentPartitionConfig multiColumnPartitionConfig = new
SegmentPartitionConfig(Map.of(
+ "myCol", new ColumnPartitionConfig("murmur", 4),
+ "otherCol", new ColumnPartitionConfig("murmur", 4)
+ ));
+
+ // Without configured partition column, the segment partition config must
have exactly one column
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME).build();
+ TableConfig noPartitionConfig = tableConfig;
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionedSegmentAssignment(noPartitionConfig,
offlineKey));
+ assertEquals(e.getMessage(), "Offline table with partitioned instance
partitions must have segment partition "
+ + "config (segmentPartitionConfig in the indexingConfig) to resolve
the partition of a segment");
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(singleColumnPartitionConfig)
+ .build();
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
offlineKey);
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(multiColumnPartitionConfig)
+ .build();
+ TableConfig multiColumnConfig = tableConfig;
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionedSegmentAssignment(multiColumnConfig,
offlineKey));
+ assertEquals(e.getMessage(), "Offline table with partitioned instance
partitions must configure the partition "
+ + "column (partitionColumn in the segment assignment config) when
segment partition config has multiple "
+ + "columns");
+
+ // The configured partition column must be a column of the segment
partition config
+ Map<String, SegmentAssignmentConfig> segmentAssignmentConfigMap =
+ Map.of(offlineKey, new SegmentAssignmentConfig(null, "myCol"));
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(multiColumnPartitionConfig)
+ .setSegmentAssignmentConfigMap(segmentAssignmentConfigMap)
+ .build();
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
offlineKey);
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(
+ new SegmentPartitionConfig(Map.of("otherCol", new
ColumnPartitionConfig("murmur", 4))))
+ .setSegmentAssignmentConfigMap(segmentAssignmentConfigMap)
+ .build();
+ TableConfig missingColumnConfig = tableConfig;
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionedSegmentAssignment(missingColumnConfig,
offlineKey));
+ assertEquals(e.getMessage(),
+ "Partition column: myCol configured for segment assignment is not
found in segment partition config");
- // setting up ReplicaGroupStrategyConfig for backward compatibility test.
- SegmentsValidationAndRetentionConfig validationConfig = new
SegmentsValidationAndRetentionConfig();
- validationConfig.setReplicaGroupStrategyConfig(replicaGroupStrategyConfig);
- tableConfig.setValidationConfig(validationConfig);
+ // The deprecated partition column of the instance assignment config is
still honored
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(multiColumnPartitionConfig)
+ .setInstanceAssignmentConfigMap(Map.of(offlineKey,
createInstanceAssignmentConfig("myCol")))
+ .build();
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
offlineKey);
+ // The segment assignment strategy configured for the key, if any, must be
partition based
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(singleColumnPartitionConfig)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ null)))
+ .build();
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
offlineKey);
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(singleColumnPartitionConfig)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.BALANCE_NUM_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
+ .build();
+ TableConfig balancedConfig = tableConfig;
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionedSegmentAssignment(balancedConfig,
offlineKey));
+ assertEquals(e.getMessage(), "Segment assignment strategy: balanced for:
OFFLINE of table: testTable_OFFLINE must "
+ + "be partition based because the instance partitions are
partitioned");
+
+ // Dimension tables are assigned to all servers regardless of the instance
partitions
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setIsDimTable(true)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey,
+ new
SegmentAssignmentConfig(AssignmentStrategy.DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY,
null)))
+ .build();
+ TableConfigUtils.validatePartitionedSegmentAssignment(tableConfig,
offlineKey);
+
+ // Partitioned OFFLINE instance assignment config runs the validation
+ InstanceAssignmentConfig instanceAssignmentConfig =
createInstanceAssignmentConfig(null);
+ Map<String, InstanceAssignmentConfig> instanceAssignmentConfigMap =
Map.of(offlineKey, instanceAssignmentConfig);
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setInstanceAssignmentConfigMap(instanceAssignmentConfigMap)
+ .build();
+ TableConfig partitionedConfig = tableConfig;
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validateInstanceAssignmentConfigs(partitionedConfig));
+ assertEquals(e.getMessage(), "Offline table with partitioned instance
partitions must have segment partition "
+ + "config (segmentPartitionConfig in the indexingConfig) to resolve
the partition of a segment");
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentPartitionConfig(singleColumnPartitionConfig)
+ .setInstanceAssignmentConfigMap(instanceAssignmentConfigMap)
+ .build();
+ TableConfigUtils.validateInstanceAssignmentConfigs(tableConfig);
+
+ // Partitioned instance assignment config of a tier of an OFFLINE table
runs the validation too
+ List<TierConfig> tierConfigs = List.of(new TierConfig("hotTier",
TierFactory.TIME_SEGMENT_SELECTOR_TYPE, "30d",
+ null, TierFactory.PINOT_SERVER_STORAGE_TYPE, "hotTier_OFFLINE", null,
null));
+ Map<String, InstanceAssignmentConfig> tierInstanceAssignmentConfigMap =
Map.of("hotTier", instanceAssignmentConfig);
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setTierConfigList(tierConfigs)
+ .setInstanceAssignmentConfigMap(tierInstanceAssignmentConfigMap)
+ .build();
+ TableConfig tierConfigWithoutPartitionConfig = tableConfig;
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validateInstanceAssignmentConfigs(tierConfigWithoutPartitionConfig));
+ assertEquals(e.getMessage(), "Offline table with partitioned instance
partitions must have segment partition "
+ + "config (segmentPartitionConfig in the indexingConfig) to resolve
the partition of a segment");
+ tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setTierConfigList(tierConfigs)
+ .setSegmentPartitionConfig(singleColumnPartitionConfig)
+ .setInstanceAssignmentConfigMap(tierInstanceAssignmentConfigMap)
+ .build();
+ TableConfigUtils.validateInstanceAssignmentConfigs(tableConfig);
+
+ // Instance assignment configs of a REALTIME table are not validated
because the partition of a realtime segment
+ // is encoded in its name
+ tableConfig = new
TableConfigBuilder(TableType.REALTIME).setTableName(TABLE_NAME)
+
.setInstanceAssignmentConfigMap(Map.of(InstancePartitionsType.COMPLETED.name(),
instanceAssignmentConfig))
+ .build();
+ TableConfigUtils.validateInstanceAssignmentConfigs(tableConfig);
+ }
+
+ @SuppressWarnings("removal")
+ @Test
+ public void testValidatePartitionColumnConsistency() {
+ String offlineKey = InstancePartitionsType.OFFLINE.name();
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentAssignmentConfigMap(Map.of(
+ offlineKey, new SegmentAssignmentConfig(null, "myCol"),
+ "hotTier", new SegmentAssignmentConfig(null, "myCol")
+ ))
+ .setInstanceAssignmentConfigMap(Map.of(offlineKey,
createInstanceAssignmentConfig("myCol")))
+ .build();
+ TableConfigUtils.validatePartitionColumnConsistency(tableConfig);
+
+ // A different column is rejected wherever it is configured
+ String expectedMessage = "Table: testTable_OFFLINE must configure the same
partition column in "
+ + "segmentAssignmentConfigMap, instanceAssignmentConfigMap and
replicaGroupStrategyConfig, found: [myCol, "
+ + "otherCol]";
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(
+ offlineKey, new SegmentAssignmentConfig(null, "myCol"),
+ "hotTier", new SegmentAssignmentConfig(null, "otherCol")
+ ));
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionColumnConsistency(tableConfig));
+ assertEquals(e.getMessage(), expectedMessage);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, "myCol")));
+ tableConfig.setInstanceAssignmentConfigMap(Map.of(offlineKey,
createInstanceAssignmentConfig("otherCol")));
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionColumnConsistency(tableConfig));
+ assertEquals(e.getMessage(), expectedMessage);
+ tableConfig.setInstanceAssignmentConfigMap(null);
+ tableConfig.getValidationConfig().setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig("otherCol", 1));
+ e = expectThrows(IllegalStateException.class,
+ () ->
TableConfigUtils.validatePartitionColumnConsistency(tableConfig));
+ assertEquals(e.getMessage(), expectedMessage);
+ }
+
+ @SuppressWarnings("removal")
+ @Test
+ public void testGetPartitionColumn() {
+ String offlineKey = InstancePartitionsType.OFFLINE.name();
+ TableConfig tableConfig = new
TableConfigBuilder(TableType.OFFLINE).setTableName(TABLE_NAME)
+ .setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, PARTITION_COLUMN)))
+ .setInstanceAssignmentConfigMap(Map.of(offlineKey,
createInstanceAssignmentConfig("instanceAssignmentCol")))
+ .build();
+ tableConfig.getValidationConfig().setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig("legacyCol", 1));
+
+ // The segment assignment config takes precedence over the deprecated
configs of existing tables
assertEquals(TableConfigUtils.getPartitionColumn(tableConfig),
PARTITION_COLUMN);
+ tableConfig.setSegmentAssignmentConfigMap(Map.of(offlineKey, new
SegmentAssignmentConfig(null, null)));
+ assertEquals(TableConfigUtils.getPartitionColumn(tableConfig),
"instanceAssignmentCol");
+ tableConfig.setInstanceAssignmentConfigMap(null);
+ assertEquals(TableConfigUtils.getPartitionColumn(tableConfig),
"legacyCol");
+ tableConfig.getValidationConfig().setReplicaGroupStrategyConfig(new
ReplicaGroupStrategyConfig("", 1));
+ assertNull(TableConfigUtils.getPartitionColumn(tableConfig));
}
@DataProvider(name = "tableTypeTestDataProvider")
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/ReplicaGroupStrategyConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/ReplicaGroupStrategyConfig.java
index 4507a3a083c..012bed291cc 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/ReplicaGroupStrategyConfig.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/ReplicaGroupStrategyConfig.java
@@ -25,7 +25,9 @@ import javax.annotation.Nullable;
import org.apache.pinot.spi.config.BaseJsonConfig;
-/// Class representing configurations related to segment assignment strategy.
+/// Legacy replica-group config, superseded by `InstanceAssignmentConfig` for
the instance assignment and by the
+/// partition column of `SegmentAssignmentConfig`. It is still accepted and
honored until it is removed.
+@Deprecated(since = "1.3.0", forRemoval = true)
public class ReplicaGroupStrategyConfig extends BaseJsonConfig {
private final String _partitionColumn;
private final int _numInstancesPerPartition;
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/SegmentsValidationAndRetentionConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/SegmentsValidationAndRetentionConfig.java
index f8c59b64d59..ae12ddae980 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/SegmentsValidationAndRetentionConfig.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/SegmentsValidationAndRetentionConfig.java
@@ -40,7 +40,8 @@ public class SegmentsValidationAndRetentionConfig extends
BaseJsonConfig {
private String _replicasPerPartition;
private String _timeColumnName;
private TimeUnit _timeType;
- @Deprecated // Use SegmentAssignmentConfig instead
+ // Superseded by the instance assignment config and the segment assignment
config, still accepted and honored
+ @Deprecated(since = "1.3.0", forRemoval = true)
private ReplicaGroupStrategyConfig _replicaGroupStrategyConfig;
private CompletionConfig _completionConfig;
private String _crypterClassName;
@@ -233,13 +234,15 @@ public class SegmentsValidationAndRetentionConfig extends
BaseJsonConfig {
_replicasPerPartition = replicasPerPartition;
}
- /// @deprecated Use
[org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig] instead.
+ /// @deprecated Configure the instance assignment in
`instanceAssignmentConfigMap` with
+ /// [org.apache.pinot.spi.config.table.assignment.InstanceAssignmentConfig]
and the partition column in
+ /// `segmentAssignmentConfigMap` instead. This config is still accepted and
honored.
@Deprecated(since = "1.3.0", forRemoval = true)
public ReplicaGroupStrategyConfig getReplicaGroupStrategyConfig() {
return _replicaGroupStrategyConfig;
}
- @Deprecated
+ @Deprecated(since = "1.3.0", forRemoval = true)
public void setReplicaGroupStrategyConfig(ReplicaGroupStrategyConfig
replicaGroupStrategyConfig) {
_replicaGroupStrategyConfig = replicaGroupStrategyConfig;
}
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceAssignmentConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceAssignmentConfig.java
index 973cf368c7e..7ad00b20aca 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceAssignmentConfig.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceAssignmentConfig.java
@@ -28,19 +28,20 @@ import org.apache.pinot.spi.config.BaseJsonConfig;
public class InstanceAssignmentConfig extends BaseJsonConfig {
- @JsonPropertyDescription("Configuration for the strategy to assign instances
to partitions")
- private final PartitionSelector _partitionSelector;
@JsonPropertyDescription("Configuration for the instance tag and pool of the
instance assignment (mandatory)")
private final InstanceTagPoolConfig _tagPoolConfig;
- @JsonPropertyDescription("Configuration for the instance constraints of the
instance assignment,"
- + " which filters out unqualified instances and sorts instances for
picking priority")
+ @JsonPropertyDescription("Configuration for the instance constraints of the
instance assignment, which filters out "
+ + "unqualified instances and sorts instances for picking priority")
private final InstanceConstraintConfig _constraintConfig;
@JsonPropertyDescription(
"Configuration for the instance replica-group and partition of the
instance assignment (mandatory)")
private final InstanceReplicaGroupPartitionConfig
_replicaGroupPartitionConfig;
+ @JsonPropertyDescription("Configuration for the strategy to assign instances
to partitions")
+ private final PartitionSelector _partitionSelector;
+
@JsonPropertyDescription("Configuration to minimize data movement for pool
and instance assignment")
private final boolean _minimizeDataMovement;
@@ -49,25 +50,21 @@ public class InstanceAssignmentConfig extends
BaseJsonConfig {
@JsonProperty(value = "tagPoolConfig", required = true)
InstanceTagPoolConfig tagPoolConfig,
@JsonProperty("constraintConfig") @Nullable InstanceConstraintConfig
constraintConfig,
@JsonProperty(value = "replicaGroupPartitionConfig", required = true)
- InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig,
+ InstanceReplicaGroupPartitionConfig replicaGroupPartitionConfig,
@JsonProperty("partitionSelector") @Nullable String partitionSelector,
@JsonProperty("minimizeDataMovement") boolean minimizeDataMovement) {
Preconditions.checkArgument(tagPoolConfig != null, "'tagPoolConfig' must
be configured");
- Preconditions
- .checkArgument(replicaGroupPartitionConfig != null,
"'replicaGroupPartitionConfig' must be configured");
+ Preconditions.checkArgument(replicaGroupPartitionConfig != null,
+ "'replicaGroupPartitionConfig' must be configured");
_tagPoolConfig = tagPoolConfig;
_constraintConfig = constraintConfig;
_replicaGroupPartitionConfig = replicaGroupPartitionConfig;
- _partitionSelector =
- partitionSelector == null ?
PartitionSelector.INSTANCE_REPLICA_GROUP_PARTITION_SELECTOR
- : PartitionSelector.valueOf(partitionSelector);
+ _partitionSelector = partitionSelector == null
+ ? PartitionSelector.INSTANCE_REPLICA_GROUP_PARTITION_SELECTOR
+ : PartitionSelector.valueOf(partitionSelector);
_minimizeDataMovement = minimizeDataMovement;
}
- public PartitionSelector getPartitionSelector() {
- return _partitionSelector;
- }
-
public InstanceTagPoolConfig getTagPoolConfig() {
return _tagPoolConfig;
}
@@ -81,12 +78,18 @@ public class InstanceAssignmentConfig extends
BaseJsonConfig {
return _replicaGroupPartitionConfig;
}
+ public PartitionSelector getPartitionSelector() {
+ return _partitionSelector;
+ }
+
public boolean isMinimizeDataMovement() {
return _minimizeDataMovement;
}
public enum PartitionSelector {
- FD_AWARE_INSTANCE_PARTITION_SELECTOR,
INSTANCE_REPLICA_GROUP_PARTITION_SELECTOR,
- MIRROR_SERVER_SET_PARTITION_SELECTOR,
IMPLICIT_REALTIME_TABLE_PARTITION_SELECTOR;
+ FD_AWARE_INSTANCE_PARTITION_SELECTOR,
+ INSTANCE_REPLICA_GROUP_PARTITION_SELECTOR,
+ MIRROR_SERVER_SET_PARTITION_SELECTOR,
+ IMPLICIT_REALTIME_TABLE_PARTITION_SELECTOR;
}
}
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceReplicaGroupPartitionConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceReplicaGroupPartitionConfig.java
index 30628bdb68b..d427efb7a84 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceReplicaGroupPartitionConfig.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/InstanceReplicaGroupPartitionConfig.java
@@ -52,8 +52,9 @@ public class InstanceReplicaGroupPartitionConfig extends
BaseJsonConfig {
+ "instances if not " + "specified")
private final int _numInstancesPerPartition;
- @JsonPropertyDescription(
- "Name of the column used for partition, if not provided table level
replica group will be used")
+ // Superseded by the partition column of the segment assignment config,
still accepted and honored
+ @Deprecated(since = "1.7.0", forRemoval = true)
+ @JsonPropertyDescription("Deprecated, configure the partition column in the
segment assignment config instead")
private final String _partitionColumn;
// TODO: remove this config in the next official release
@@ -108,6 +109,10 @@ public class InstanceReplicaGroupPartitionConfig extends
BaseJsonConfig {
return _minimizeDataMovement;
}
+ /// @deprecated Configure the partition column in
`segmentAssignmentConfigMap` with [SegmentAssignmentConfig]
+ /// instead, which is where the segment assignment reads it from. This
column is still accepted and honored, and the
+ /// segment assignment config takes precedence when both are configured.
+ @Deprecated(since = "1.7.0", forRemoval = true)
@Nullable
public String getPartitionColumn() {
return _partitionColumn;
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/SegmentAssignmentConfig.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/SegmentAssignmentConfig.java
index eef95257f00..1238c6e59c0 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/SegmentAssignmentConfig.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/assignment/SegmentAssignmentConfig.java
@@ -21,21 +21,39 @@ package org.apache.pinot.spi.config.table.assignment;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
+import javax.annotation.Nullable;
import org.apache.pinot.spi.config.BaseJsonConfig;
+/// Config of how segments are assigned to the instance partitions of an
instance partitions type (`OFFLINE` or
+/// `COMPLETED`) or a tier, keyed by its name in `segmentAssignmentConfigMap`
of the table config. Both fields are
+/// optional: the strategy defaults to the one derived from the instance
partitions, and the partition column defaults
+/// to the single column of the segment partition config.
public class SegmentAssignmentConfig extends BaseJsonConfig {
- @JsonPropertyDescription("Configuration for Segment Assignment Strategy")
+ @JsonPropertyDescription("Segment assignment strategy: balanced,
replicagroup, roundrobin or roundrobinreplicagroup "
+ + "(allservers for a dimension table), derived from the instance
partitions if not specified")
@JsonProperty("segmentAssignmentStrategy")
private final String _assignmentStrategy;
+ @JsonPropertyDescription("Column used to resolve the partition of a segment
for partition based segment assignment, "
+ + "the single column of the segment partition config if not specified")
+ private final String _partitionColumn;
+
@JsonCreator
- public SegmentAssignmentConfig(@JsonProperty(value =
"segmentAssignmentStrategy") String assignmentStrategy) {
+ public SegmentAssignmentConfig(@JsonProperty("segmentAssignmentStrategy")
@Nullable String assignmentStrategy,
+ @JsonProperty("partitionColumn") @Nullable String partitionColumn) {
_assignmentStrategy = assignmentStrategy;
+ _partitionColumn = partitionColumn;
}
+ @Nullable
public String getAssignmentStrategy() {
return _assignmentStrategy;
}
+
+ @Nullable
+ public String getPartitionColumn() {
+ return _partitionColumn;
+ }
}
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
index 46b2bd84ddc..6e935bb3cec 100644
--- a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/CommonConstants.java
@@ -2536,6 +2536,19 @@ public class CommonConstants {
public static final String REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY =
"replicagroup";
public static final String
ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY =
"roundrobinreplicagroup";
public static final String DIM_TABLE_SEGMENT_ASSIGNMENT_STRATEGY =
"allservers";
+
+ // Strategies that can be configured for a table other than a dimension
table
+ public static final Set<String> CONFIGURABLE_STRATEGIES = Set.of(
+ BALANCE_NUM_SEGMENT_ASSIGNMENT_STRATEGY,
+ ROUND_ROBIN_SEGMENT_ASSIGNMENT_STRATEGY,
+ REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY
+ );
+ // Strategies that place a segment by its partition, the only ones the
partition column applies to
+ public static final Set<String> PARTITION_BASED_STRATEGIES = Set.of(
+ REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY,
+ ROUND_ROBIN_REPLICA_GROUP_SEGMENT_ASSIGNMENT_STRATEGY
+ );
}
public static class BuiltInVirtualColumn {
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/TableConfigBuilder.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/TableConfigBuilder.java
index f61f433a4da..8c2950880bc 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/TableConfigBuilder.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/utils/builder/TableConfigBuilder.java
@@ -85,7 +85,7 @@ public class TableConfigBuilder {
@Deprecated
private String _segmentPushType = DEFAULT_SEGMENT_PUSH_TYPE;
private String _peerSegmentDownloadScheme;
- @Deprecated
+ @Deprecated(since = "1.3.0", forRemoval = true)
private ReplicaGroupStrategyConfig _replicaGroupStrategyConfig;
private CompletionConfig _completionConfig;
private String _crypterClassName;
@@ -242,6 +242,7 @@ public class TableConfigBuilder {
return this;
}
+ @Deprecated(since = "1.3.0", forRemoval = true)
public TableConfigBuilder
setReplicaGroupStrategyConfig(ReplicaGroupStrategyConfig
replicaGroupStrategyConfig) {
_replicaGroupStrategyConfig = replicaGroupStrategyConfig;
return this;
diff --git
a/pinot-tools/src/main/resources/examples/batch/colocated/userAttributes/userAttributes_offline_table_config.json
b/pinot-tools/src/main/resources/examples/batch/colocated/userAttributes/userAttributes_offline_table_config.json
index 6a5aecb8688..52655c24e49 100644
---
a/pinot-tools/src/main/resources/examples/batch/colocated/userAttributes/userAttributes_offline_table_config.json
+++
b/pinot-tools/src/main/resources/examples/batch/colocated/userAttributes/userAttributes_offline_table_config.json
@@ -32,8 +32,7 @@
"numReplicaGroups": 2,
"numInstancesPerReplicaGroup": 2,
"numPartitions": 2,
- "numInstancesPerPartition": 1,
- "partitionColumn": "userUUID"
+ "numInstancesPerPartition": 1
}
}
},
diff --git
a/pinot-tools/src/main/resources/examples/batch/colocated/userFactEvents/userFactEvents_offline_table_config.json
b/pinot-tools/src/main/resources/examples/batch/colocated/userFactEvents/userFactEvents_offline_table_config.json
index 99430f74485..33c51d507b9 100644
---
a/pinot-tools/src/main/resources/examples/batch/colocated/userFactEvents/userFactEvents_offline_table_config.json
+++
b/pinot-tools/src/main/resources/examples/batch/colocated/userFactEvents/userFactEvents_offline_table_config.json
@@ -3,11 +3,7 @@
"tableType": "OFFLINE",
"segmentsConfig": {
"segmentPushType": "APPEND",
- "replication": 2,
- "replicaGroupStrategyConfig": {
- "partitionColumn": "userUUID",
- "numInstancesPerPartition": 2
- }
+ "replication": 2
},
"tenants": {
"broker": "DefaultTenant",
diff --git
a/pinot-tools/src/main/resources/examples/batch/colocated/userGroups/userGroups_offline_table_config.json
b/pinot-tools/src/main/resources/examples/batch/colocated/userGroups/userGroups_offline_table_config.json
index 9f7d3fd0456..3386556dca6 100644
---
a/pinot-tools/src/main/resources/examples/batch/colocated/userGroups/userGroups_offline_table_config.json
+++
b/pinot-tools/src/main/resources/examples/batch/colocated/userGroups/userGroups_offline_table_config.json
@@ -3,11 +3,7 @@
"tableType": "OFFLINE",
"segmentsConfig": {
"segmentPushType": "APPEND",
- "replication": "2",
- "replicaGroupStrategyConfig": {
- "partitionColumn": "userUUID",
- "numInstancesPerPartition": 2
- }
+ "replication": "2"
},
"tenants": {
"broker": "DefaultTenant",
diff --git
a/pinot-tools/src/main/resources/examples/stream/upsertJsonMeetupRsvp/upsertJsonMeetupRsvp_realtime_table_config.json
b/pinot-tools/src/main/resources/examples/stream/upsertJsonMeetupRsvp/upsertJsonMeetupRsvp_realtime_table_config.json
index a5589b96703..70bee25d52d 100644
---
a/pinot-tools/src/main/resources/examples/stream/upsertJsonMeetupRsvp/upsertJsonMeetupRsvp_realtime_table_config.json
+++
b/pinot-tools/src/main/resources/examples/stream/upsertJsonMeetupRsvp/upsertJsonMeetupRsvp_realtime_table_config.json
@@ -39,7 +39,6 @@
"replicaGroupPartitionConfig": {
"replicaGroupBased": true,
"numReplicaGroups": 1,
- "partitionColumn": "rsvp_id",
"numPartitions": 2,
"numInstancesPerPartition": 1
}
diff --git
a/pinot-tools/src/main/resources/examples/stream/upsertMeetupRsvp/upsertMeetupRsvp_realtime_table_config.json
b/pinot-tools/src/main/resources/examples/stream/upsertMeetupRsvp/upsertMeetupRsvp_realtime_table_config.json
index 393b5fa7e47..863f7fab41f 100644
---
a/pinot-tools/src/main/resources/examples/stream/upsertMeetupRsvp/upsertMeetupRsvp_realtime_table_config.json
+++
b/pinot-tools/src/main/resources/examples/stream/upsertMeetupRsvp/upsertMeetupRsvp_realtime_table_config.json
@@ -27,7 +27,6 @@
"replicaGroupPartitionConfig": {
"replicaGroupBased": true,
"numReplicaGroups": 1,
- "partitionColumn": "event_id",
"numPartitions": 2,
"numInstancesPerPartition": 1
}
diff --git
a/pinot-tools/src/main/resources/examples/stream/upsertPartialMeetupRsvp/upsertPartialMeetupRsvp_realtime_table_config.json
b/pinot-tools/src/main/resources/examples/stream/upsertPartialMeetupRsvp/upsertPartialMeetupRsvp_realtime_table_config.json
index 1cc953a95d0..70c2f9f85aa 100644
---
a/pinot-tools/src/main/resources/examples/stream/upsertPartialMeetupRsvp/upsertPartialMeetupRsvp_realtime_table_config.json
+++
b/pinot-tools/src/main/resources/examples/stream/upsertPartialMeetupRsvp/upsertPartialMeetupRsvp_realtime_table_config.json
@@ -27,7 +27,6 @@
"replicaGroupPartitionConfig": {
"replicaGroupBased": true,
"numReplicaGroups": 1,
- "partitionColumn": "event_id",
"numPartitions": 2,
"numInstancesPerPartition": 1
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]