From 0dcf5c621f93ce0b2f185c234cbb97159da2ec39 Mon Sep 17 00:00:00 2001 From: lanchengx <52209337+lanchengx@users.noreply.github.com> Date: Sun, 30 Jan 2022 10:33:00 +0800 Subject: [PATCH] [DistSQL]Support `alter traffic rule` syntax. (#15155) * Support `alter traffic rule` syntax. * Rename variable. * Add successful test. * Add converter. --- .../src/main/antlr4/imports/RALStatement.g4 | 20 ++-- .../parser/autogen/CommonDistSQLStatement.g4 | 1 + .../common/CommonDistSQLStatementVisitor.java | 9 +- .../rdl/create/AlterTrafficRuleStatement.java | 35 ++++++ .../rule/RequiredRuleMissedException.java | 4 + .../alter/AlterStatementExecutorFactory.java | 5 + .../excutor/AlterTrafficRuleExecutor.java | 94 +++++++++++++++ .../common/convert/TrafficRuleConverter.java | 67 +++++++++++ .../create/CreateTrafficRuleHandler.java | 34 +----- .../alter/AlterTrafficRuleHandlerTest.java | 112 ++++++++++++++++++ 10 files changed, 340 insertions(+), 41 deletions(-) create mode 100644 shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java create mode 100644 shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java create mode 100644 shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java create mode 100644 shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java diff --git a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4 b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4 index ab6c8384c1807..c28e031e97973 100644 --- a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4 +++ b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/imports/RALStatement.g4 @@ -83,6 +83,18 @@ createTrafficRule : CREATE TRAFFIC RULE trafficRuleDefinition (COMMA trafficRuleDefinition)* ; +alterTrafficRule + : ALTER TRAFFIC RULE trafficRuleDefinition (COMMA trafficRuleDefinition)* + ; + +showTrafficRules + : SHOW TRAFFIC (RULES | RULE ruleName) + ; + +dropTrafficRule + : DROP TRAFFIC RULE ifExists? ruleName (COMMA ruleName)* + ; + trafficRuleDefinition : ruleName LP labelDefinition COMMA trafficAlgorithmDefinition COMMA loadBanlanceDefinition RP ; @@ -107,14 +119,6 @@ typeName : IDENTIFIER ; -showTrafficRules - : SHOW TRAFFIC (RULES | RULE ruleName) - ; - -dropTrafficRule - : DROP TRAFFIC RULE ifExists? ruleName (COMMA ruleName)* - ; - exportSchemaConfiguration : EXPORT SCHEMA (CONFIGURATION | CONFIG) (FROM schemaName)? (COMMA? FILE EQ filePath)? ; diff --git a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4 b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4 index c9c6575ad8552..6100550a40619 100644 --- a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4 +++ b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/antlr4/org/apache/shardingsphere/distsql/parser/autogen/CommonDistSQLStatement.g4 @@ -48,6 +48,7 @@ execute | showTrafficRules | dropTrafficRule | createTrafficRule + | alterTrafficRule | exportSchemaConfiguration ) SEMI? ; diff --git a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java index 5cb4e3c4ee44a..7ee4d870204a3 100644 --- a/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java +++ b/shardingsphere-distsql/shardingsphere-distsql-parser/src/main/java/org/apache/shardingsphere/distsql/parser/core/common/CommonDistSQLStatementVisitor.java @@ -26,6 +26,7 @@ import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterDefaultSingleTableRuleContext; import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterResourceContext; import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterSQLParserRuleContext; +import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterTrafficRuleContext; import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.AlterTransactionRuleContext; import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.CacheOptionContext; import org.apache.shardingsphere.distsql.parser.autogen.CommonDistSQLStatementParser.ClearHintContext; @@ -89,6 +90,7 @@ import org.apache.shardingsphere.distsql.parser.statement.rdl.alter.AlterResourceStatement; import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AddResourceStatement; import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterDefaultSingleTableRuleStatement; +import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement; import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateDefaultSingleTableRuleStatement; import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateTrafficRuleStatement; import org.apache.shardingsphere.distsql.parser.statement.rdl.drop.DropDefaultSingleTableRuleStatement; @@ -353,6 +355,11 @@ public ASTNode visitCreateTrafficRule(final CreateTrafficRuleContext ctx) { return new CreateTrafficRuleStatement(ctx.trafficRuleDefinition().stream().map(each -> (TrafficRuleSegment) visit(each)).collect(Collectors.toCollection(LinkedList::new))); } + @Override + public ASTNode visitAlterTrafficRule(final AlterTrafficRuleContext ctx) { + return new AlterTrafficRuleStatement(ctx.trafficRuleDefinition().stream().map(each -> (TrafficRuleSegment) visit(each)).collect(Collectors.toCollection(LinkedList::new))); + } + @Override public ASTNode visitShowTrafficRules(final ShowTrafficRulesContext ctx) { ShowTrafficRulesStatement result = new ShowTrafficRulesStatement(); @@ -364,7 +371,7 @@ public ASTNode visitShowTrafficRules(final ShowTrafficRulesContext ctx) { @Override public ASTNode visitTrafficRuleDefinition(final TrafficRuleDefinitionContext ctx) { - return new TrafficRuleSegment(getIdentifierValue(ctx.ruleName()), buildLabels(ctx.labelDefinition()), + return new TrafficRuleSegment(getIdentifierValue(ctx.ruleName()), buildLabels(ctx.labelDefinition()), (AlgorithmSegment) visit(ctx.trafficAlgorithmDefinition().algorithmDefinition()), (AlgorithmSegment) visit(ctx.loadBanlanceDefinition().algorithmDefinition())); } diff --git a/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java b/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java new file mode 100644 index 0000000000000..af9304825a009 --- /dev/null +++ b/shardingsphere-distsql/shardingsphere-distsql-statement/src/main/java/org/apache/shardingsphere/distsql/parser/statement/rdl/create/AlterTrafficRuleStatement.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.distsql.parser.statement.rdl.create; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment; +import org.apache.shardingsphere.distsql.parser.statement.ral.common.AlterDistSQLStatement; + +import java.util.Collection; + +/** + * Alter traffic rule statement. + */ +@RequiredArgsConstructor +@Getter +public final class AlterTrafficRuleStatement extends AlterDistSQLStatement { + + private final Collection segments; +} diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java index 6964b685df58a..8bad342b65dd5 100644 --- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java +++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/distsql/exception/rule/RequiredRuleMissedException.java @@ -34,6 +34,10 @@ public RequiredRuleMissedException(final String ruleType, final String schemaNam super(1112, String.format("%s rule does not exist in schema `%s`.", ruleType, schemaName)); } + public RequiredRuleMissedException(final String ruleType, final Collection ruleNames) { + super(1112, String.format("%s rules `%s` do not exist.", ruleType, ruleNames)); + } + public RequiredRuleMissedException(final String ruleType, final String schemaName, final String ruleName) { super(1112, String.format("%s rule `%s` do not exist in schema `%s`.", ruleType, ruleName, schemaName)); } diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java index 1ca401550607c..3a98a2e4ae060 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterStatementExecutorFactory.java @@ -20,8 +20,10 @@ import org.apache.shardingsphere.distsql.parser.statement.ral.common.AlterDistSQLStatement; import org.apache.shardingsphere.distsql.parser.statement.ral.common.alter.AlterSQLParserRuleStatement; import org.apache.shardingsphere.distsql.parser.statement.ral.common.alter.AlterTransactionRuleStatement; +import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement; import org.apache.shardingsphere.proxy.backend.session.ConnectionSession; import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterSQLParserRuleExecutor; +import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTrafficRuleExecutor; import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTransactionRuleExecutor; import java.sql.SQLException; @@ -46,6 +48,9 @@ public static AlterStatementExecutor newInstance(final AlterDistSQLStatement sql if (sqlStatement instanceof AlterSQLParserRuleStatement) { return new AlterSQLParserRuleExecutor((AlterSQLParserRuleStatement) sqlStatement); } + if (sqlStatement instanceof AlterTrafficRuleStatement) { + return new AlterTrafficRuleExecutor((AlterTrafficRuleStatement) sqlStatement); + } throw new UnsupportedOperationException(sqlStatement.getClass().getCanonicalName()); } } diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java new file mode 100644 index 0000000000000..7841842910877 --- /dev/null +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/excutor/AlterTrafficRuleExecutor.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor; + +import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment; +import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement; +import org.apache.shardingsphere.infra.distsql.exception.DistSQLException; +import org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException; +import org.apache.shardingsphere.infra.distsql.exception.rule.RequiredRuleMissedException; +import org.apache.shardingsphere.mode.metadata.MetaDataContexts; +import org.apache.shardingsphere.mode.metadata.persist.MetaDataPersistService; +import org.apache.shardingsphere.proxy.backend.context.ProxyContext; +import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader; +import org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader; +import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.AlterStatementExecutor; +import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert.TrafficRuleConverter; +import org.apache.shardingsphere.spi.typed.TypedSPIRegistry; +import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration; +import org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration; +import org.apache.shardingsphere.traffic.spi.TrafficAlgorithm; +import org.apache.shardingsphere.traffic.spi.TrafficLoadBalanceAlgorithm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Alter traffic rule handler. + */ +@RequiredArgsConstructor +public final class AlterTrafficRuleExecutor implements AlterStatementExecutor { + + private final AlterTrafficRuleStatement sqlStatement; + + @Override + public ResponseHeader execute() throws DistSQLException { + Optional currentConfiguration = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getGlobalRuleMetaData() + .findRuleConfiguration(TrafficRuleConfiguration.class).stream().findAny(); + check(sqlStatement, currentConfiguration); + TrafficRuleConfiguration toBeAlteredConfiguration = TrafficRuleConverter.convert(sqlStatement.getSegments()); + updateToRepository(toBeAlteredConfiguration, currentConfiguration.get()); + return new UpdateResponseHeader(sqlStatement); + } + + private void check(final AlterTrafficRuleStatement sqlStatement, final Optional currentConfiguration) throws DistSQLException { + DistSQLException.predictionThrow(currentConfiguration.isPresent(), new RequiredRuleMissedException("Traffic")); + Collection currentRuleNames = currentConfiguration.get().getTrafficStrategies().stream().map(TrafficStrategyConfiguration::getName).collect(Collectors.toSet()); + Set notExistRuleNames = sqlStatement.getSegments().stream().map(TrafficRuleSegment::getName).filter(each -> !currentRuleNames.contains(each)).collect(Collectors.toSet()); + DistSQLException.predictionThrow(notExistRuleNames.isEmpty(), new RequiredRuleMissedException("Traffic", notExistRuleNames)); + Collection invalidAlgorithmNames = getInvalidAlgorithmNames(sqlStatement.getSegments()); + DistSQLException.predictionThrow(invalidAlgorithmNames.isEmpty(), new InvalidAlgorithmConfigurationException("traffic", invalidAlgorithmNames)); + } + + private Collection getInvalidAlgorithmNames(final Collection segments) { + Collection result = new ArrayList<>(segments.size()); + sqlStatement.getSegments().forEach(each -> { + if (!TypedSPIRegistry.findRegisteredService(TrafficAlgorithm.class, each.getAlgorithm().getName(), new Properties()).isPresent()) { + result.add(each.getAlgorithm().getName()); + } + if (!TypedSPIRegistry.findRegisteredService(TrafficLoadBalanceAlgorithm.class, each.getLoadBalancer().getName(), new Properties()).isPresent()) { + result.add(each.getLoadBalancer().getName()); + } + }); + return result; + } + + private void updateToRepository(final TrafficRuleConfiguration toBeAlteredConfiguration, final TrafficRuleConfiguration currentConfiguration) { + currentConfiguration.getTrafficStrategies().addAll(toBeAlteredConfiguration.getTrafficStrategies()); + currentConfiguration.getTrafficAlgorithms().putAll(toBeAlteredConfiguration.getTrafficAlgorithms()); + currentConfiguration.getLoadBalancers().putAll(toBeAlteredConfiguration.getLoadBalancers()); + MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts(); + Optional metaDataPersistService = metaDataContexts.getMetaDataPersistService(); + metaDataPersistService.ifPresent(op -> op.getGlobalRuleService().persist(metaDataContexts.getGlobalRuleMetaData().getConfigurations(), true)); + } +} diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java new file mode 100644 index 0000000000000..32624bc668ae8 --- /dev/null +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/convert/TrafficRuleConverter.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert; + +import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment; +import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment; +import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration; +import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration; +import org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration; + +import java.util.Collection; + +/** + * Traffic rule converter. + */ +public final class TrafficRuleConverter { + + /** + * Convert traffic rule segment to traffic rule configuration. + * + * @param segments traffic rule segments + * @return traffic rule configuration + */ + public static TrafficRuleConfiguration convert(final Collection segments) { + TrafficRuleConfiguration result = new TrafficRuleConfiguration(); + segments.forEach(each -> setConfigurationData(result, each)); + return result; + } + + private static void setConfigurationData(final TrafficRuleConfiguration result, final TrafficRuleSegment each) { + ShardingSphereAlgorithmConfiguration trafficAlgorithm = createAlgorithmConfiguration(each.getAlgorithm()); + ShardingSphereAlgorithmConfiguration loadBalancer = createAlgorithmConfiguration(each.getLoadBalancer()); + String trafficAlgorithmName = createAlgorithmName(each.getName(), trafficAlgorithm); + String loadBalancerName = createAlgorithmName(each.getName(), loadBalancer); + TrafficStrategyConfiguration trafficStrategy = createTrafficStrategy(each, trafficAlgorithmName, loadBalancerName); + result.getTrafficStrategies().add(trafficStrategy); + result.getTrafficAlgorithms().put(trafficAlgorithmName, trafficAlgorithm); + result.getLoadBalancers().put(loadBalancerName, loadBalancer); + } + + private static ShardingSphereAlgorithmConfiguration createAlgorithmConfiguration(final AlgorithmSegment segment) { + return new ShardingSphereAlgorithmConfiguration(segment.getName(), segment.getProps()); + } + + private static TrafficStrategyConfiguration createTrafficStrategy(final TrafficRuleSegment trafficRuleSegment, final String trafficAlgorithmName, final String loadBalancerName) { + return new TrafficStrategyConfiguration(trafficRuleSegment.getName(), trafficRuleSegment.getLabels(), trafficAlgorithmName, loadBalancerName); + } + + private static String createAlgorithmName(final String ruleName, final ShardingSphereAlgorithmConfiguration algorithm) { + return String.format("%s_%s", ruleName, algorithm.getType()).toLowerCase(); + } +} diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java index ee388f4ba6cbc..ac633ff70075b 100644 --- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/create/CreateTrafficRuleHandler.java @@ -18,11 +18,9 @@ package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.create; import lombok.RequiredArgsConstructor; -import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment; import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment; import org.apache.shardingsphere.distsql.parser.statement.rdl.create.CreateTrafficRuleStatement; import org.apache.shardingsphere.infra.config.RuleConfiguration; -import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration; import org.apache.shardingsphere.infra.distsql.exception.DistSQLException; import org.apache.shardingsphere.infra.distsql.exception.rule.DuplicateRuleException; import org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException; @@ -32,6 +30,7 @@ import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader; import org.apache.shardingsphere.proxy.backend.response.header.update.UpdateResponseHeader; import org.apache.shardingsphere.proxy.backend.text.TextProtocolBackendHandler; +import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.convert.TrafficRuleConverter; import org.apache.shardingsphere.spi.typed.TypedSPIRegistry; import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration; import org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration; @@ -58,7 +57,7 @@ public ResponseHeader execute() throws DistSQLException { Optional trafficRuleConfiguration = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getGlobalRuleMetaData() .findRuleConfiguration(TrafficRuleConfiguration.class).stream().findAny(); check(sqlStatement, trafficRuleConfiguration); - TrafficRuleConfiguration toBeCreatedConfiguration = createTrafficRuleConfiguration(sqlStatement); + TrafficRuleConfiguration toBeCreatedConfiguration = TrafficRuleConverter.convert(sqlStatement.getSegments()); updateToRepository(toBeCreatedConfiguration, trafficRuleConfiguration); return new UpdateResponseHeader(sqlStatement); } @@ -86,31 +85,6 @@ private Collection getInvalidAlgorithmNames(final Collection setConfigurationData(result, each)); - return result; - } - - private void setConfigurationData(final TrafficRuleConfiguration result, final TrafficRuleSegment each) { - ShardingSphereAlgorithmConfiguration trafficAlgorithm = createAlgorithmConfiguration(each.getAlgorithm()); - ShardingSphereAlgorithmConfiguration loadBalancer = createAlgorithmConfiguration(each.getLoadBalancer()); - String trafficAlgorithmName = createAlgorithmName(each.getName(), trafficAlgorithm); - String loadBalancerName = createAlgorithmName(each.getName(), loadBalancer); - TrafficStrategyConfiguration trafficStrategy = createTrafficStrategy(each, trafficAlgorithmName, loadBalancerName); - result.getTrafficStrategies().add(trafficStrategy); - result.getTrafficAlgorithms().put(trafficAlgorithmName, trafficAlgorithm); - result.getLoadBalancers().put(loadBalancerName, loadBalancer); - } - - private ShardingSphereAlgorithmConfiguration createAlgorithmConfiguration(final AlgorithmSegment segment) { - return new ShardingSphereAlgorithmConfiguration(segment.getName(), segment.getProps()); - } - - private TrafficStrategyConfiguration createTrafficStrategy(final TrafficRuleSegment trafficRuleSegment, final String trafficAlgorithmName, final String loadBalancerName) { - return new TrafficStrategyConfiguration(trafficRuleSegment.getName(), trafficRuleSegment.getLabels(), trafficAlgorithmName, loadBalancerName); - } - private void updateToRepository(final TrafficRuleConfiguration toBeCreatedRuleConfiguration, final Optional currentRuleConfiguration) { MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts(); Collection globalRuleConfigurations = metaDataContexts.getGlobalRuleMetaData().getConfigurations(); @@ -124,8 +98,4 @@ private void updateToRepository(final TrafficRuleConfiguration toBeCreatedRuleCo Optional metaDataPersistService = metaDataContexts.getMetaDataPersistService(); metaDataPersistService.ifPresent(op -> op.getGlobalRuleService().persist(globalRuleConfigurations, true)); } - - private String createAlgorithmName(final String ruleName, final ShardingSphereAlgorithmConfiguration algorithm) { - return String.format("%s_%s", ruleName, algorithm.getType()).toLowerCase(); - } } diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java new file mode 100644 index 0000000000000..e998475337ede --- /dev/null +++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/distsql/ral/common/alter/AlterTrafficRuleHandlerTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter; + +import org.apache.shardingsphere.distsql.parser.segment.AlgorithmSegment; +import org.apache.shardingsphere.distsql.parser.segment.TrafficRuleSegment; +import org.apache.shardingsphere.distsql.parser.statement.rdl.create.AlterTrafficRuleStatement; +import org.apache.shardingsphere.infra.config.RuleConfiguration; +import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration; +import org.apache.shardingsphere.infra.distsql.exception.DistSQLException; +import org.apache.shardingsphere.infra.distsql.exception.rule.InvalidAlgorithmConfigurationException; +import org.apache.shardingsphere.infra.distsql.exception.rule.RequiredRuleMissedException; +import org.apache.shardingsphere.mode.manager.ContextManager; +import org.apache.shardingsphere.proxy.backend.context.ProxyContext; +import org.apache.shardingsphere.proxy.backend.text.distsql.ral.common.alter.excutor.AlterTrafficRuleExecutor; +import org.apache.shardingsphere.spi.ShardingSphereServiceLoader; +import org.apache.shardingsphere.traffic.api.config.TrafficRuleConfiguration; +import org.apache.shardingsphere.traffic.api.config.TrafficStrategyConfiguration; +import org.apache.shardingsphere.traffic.spi.TrafficAlgorithm; +import org.apache.shardingsphere.traffic.spi.TrafficLoadBalanceAlgorithm; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.Properties; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AlterTrafficRuleHandlerTest { + + static { + ShardingSphereServiceLoader.register(TrafficAlgorithm.class); + ShardingSphereServiceLoader.register(TrafficLoadBalanceAlgorithm.class); + } + + @Test(expected = RequiredRuleMissedException.class) + public void assertCheckWithEmptyRule() throws DistSQLException { + ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); + when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(new LinkedList<>()); + ProxyContext.getInstance().init(contextManager); + TrafficRuleSegment trafficRuleSegment = new TrafficRuleSegment("input_rule_name", Arrays.asList("olap", "order_by"), + new AlgorithmSegment("invalid", new Properties()), new AlgorithmSegment("invalid", new Properties())); + new AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute(); + } + + @Test(expected = InvalidAlgorithmConfigurationException.class) + public void assertCheckWithInvalidAlgorithmType() throws DistSQLException { + ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); + when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule()); + ProxyContext.getInstance().init(contextManager); + TrafficRuleSegment trafficRuleSegment = new TrafficRuleSegment("rule_name_1", Arrays.asList("olap", "order_by"), + new AlgorithmSegment("invalid", new Properties()), new AlgorithmSegment("invalid", new Properties())); + new AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute(); + } + + @Test(expected = RequiredRuleMissedException.class) + public void assertCheckWithNotExistRuleName() throws DistSQLException { + ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); + when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule()); + ProxyContext.getInstance().init(contextManager); + TrafficRuleSegment trafficRuleSegment = new TrafficRuleSegment("rule_name_3", Arrays.asList("olap", "order_by"), + new AlgorithmSegment("TEST", new Properties()), new AlgorithmSegment("TEST", new Properties())); + new AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute(); + } + + @Test + public void assertCheckSuccess() throws DistSQLException { + ContextManager contextManager = mock(ContextManager.class, RETURNS_DEEP_STUBS); + when(contextManager.getMetaDataContexts().getGlobalRuleMetaData().findRuleConfiguration(any())).thenReturn(createTrafficRule()); + ProxyContext.getInstance().init(contextManager); + TrafficRuleSegment trafficRuleSegment = new TrafficRuleSegment("rule_name_1", Arrays.asList("olap", "order_by"), + new AlgorithmSegment("TEST", new Properties()), new AlgorithmSegment("TEST", new Properties())); + new AlterTrafficRuleExecutor(getSQLStatement(trafficRuleSegment)).execute(); + } + + private Collection createTrafficRule() { + TrafficRuleConfiguration trafficRuleConfiguration = new TrafficRuleConfiguration(); + trafficRuleConfiguration.getTrafficStrategies().add(new TrafficStrategyConfiguration("rule_name_1", Arrays.asList("olap", "order_by"), "algorithm_1", "load_balancer_1")); + trafficRuleConfiguration.getTrafficStrategies().add(new TrafficStrategyConfiguration("rule_name_2", Collections.singletonList("oltp"), "algorithm_2", "load_balancer_2")); + Properties algorithmProperties = new Properties(); + algorithmProperties.put("sql", "select * from t_order"); + trafficRuleConfiguration.getTrafficAlgorithms().put("algorithm_1", new ShardingSphereAlgorithmConfiguration("SQL_MATCH", algorithmProperties)); + trafficRuleConfiguration.getTrafficAlgorithms().put("algorithm_2", new ShardingSphereAlgorithmConfiguration("SQL_HINT", new Properties())); + trafficRuleConfiguration.getLoadBalancers().put("load_balancer_1", new ShardingSphereAlgorithmConfiguration("RANDOM", new Properties())); + trafficRuleConfiguration.getLoadBalancers().put("load_balancer_2", new ShardingSphereAlgorithmConfiguration("ROBIN", new Properties())); + return Collections.singletonList(trafficRuleConfiguration); + } + + private AlterTrafficRuleStatement getSQLStatement(final TrafficRuleSegment... segments) { + return new AlterTrafficRuleStatement(Arrays.asList(segments)); + } +}