From 9e193e76d7883d21e443db5a9dca9e83efa2feb3 Mon Sep 17 00:00:00 2001 From: Liang Zhang Date: Mon, 4 Nov 2024 00:32:45 +0800 Subject: [PATCH] Refactor ShadowRule (#33520) * Add ShadowDataSourceMappingsFinder * Add ShadowDataSourceMappingsFinder * Add ShadowDataSourceMappingsFinder * Add ShadowDataSourceMappingsFinder --- .../shadow/spi/hint/HintShadowAlgorithm.java | 4 +- ...wDMLStatementDataSourceMappingsFinder.java | 20 ++--- .../shadow/rule/ShadowRule.java | 81 +++++++++---------- .../shadow/rule/ShadowRuleTest.java | 65 +++++---------- .../DistSQLShadowAlgorithmFixture.java | 2 +- 5 files changed, 72 insertions(+), 100 deletions(-) diff --git a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/spi/hint/HintShadowAlgorithm.java b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/spi/hint/HintShadowAlgorithm.java index e77aaeb464d08..1cdd3f0feaad9 100644 --- a/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/spi/hint/HintShadowAlgorithm.java +++ b/features/shadow/api/src/main/java/org/apache/shardingsphere/shadow/spi/hint/HintShadowAlgorithm.java @@ -31,9 +31,9 @@ public interface HintShadowAlgorithm> extends ShadowAlgo /** * Is need shadow. * - * @param relatedShadowTables related shadow tables + * @param shadowTableNames shadow table names * @param hintShadowValue hint value of shadow * @return is need shadow or not */ - boolean isShadow(Collection relatedShadowTables, PreciseHintShadowValue hintShadowValue); + boolean isShadow(Collection shadowTableNames, PreciseHintShadowValue hintShadowValue); } diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/finder/dml/AbstractShadowDMLStatementDataSourceMappingsFinder.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/finder/dml/AbstractShadowDMLStatementDataSourceMappingsFinder.java index b3de1fe7d03bf..0af9b1c0a80b2 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/finder/dml/AbstractShadowDMLStatementDataSourceMappingsFinder.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/route/engine/finder/dml/AbstractShadowDMLStatementDataSourceMappingsFinder.java @@ -71,12 +71,12 @@ private Map getTableAliasAndNameMappings(final Collection find(final ShadowRule rule) { - Collection relatedShadowTables = rule.getRelatedShadowTables(tableAliasAndNameMappings.values()); - if (relatedShadowTables.isEmpty() && isMatchDefaultAlgorithm(rule)) { + Collection shadowTables = rule.filterShadowTables(tableAliasAndNameMappings.values()); + if (shadowTables.isEmpty() && isMatchDefaultAlgorithm(rule)) { return rule.getAllShadowDataSourceMappings(); } - Map result = findBySQLHints(rule, relatedShadowTables); - return result.isEmpty() ? findByShadowColumn(rule, relatedShadowTables) : result; + Map result = findBySQLHints(rule, shadowTables); + return result.isEmpty() ? findByShadowColumn(rule, shadowTables) : result; } @SuppressWarnings("unchecked") @@ -93,7 +93,7 @@ private Map findBySQLHints(final ShadowRule rule, final Collecti Map result = new LinkedHashMap<>(); for (String each : relatedShadowTables) { if (isContainsShadowInSQLHints(rule, each, new ShadowDetermineCondition(each, operationType))) { - result.putAll(rule.getRelatedShadowDataSourceMappings(each)); + result.putAll(rule.getShadowDataSourceMappings(each)); return result; } } @@ -101,7 +101,7 @@ private Map findBySQLHints(final ShadowRule rule, final Collecti } private boolean isContainsShadowInSQLHints(final ShadowRule rule, final String tableName, final ShadowDetermineCondition shadowCondition) { - for (HintShadowAlgorithm> each : rule.getRelatedHintShadowAlgorithms(tableName)) { + for (HintShadowAlgorithm> each : rule.getHintShadowAlgorithms(tableName)) { if (HintShadowAlgorithmDeterminer.isShadow(each, shadowCondition, rule, isShadow)) { return true; } @@ -111,9 +111,9 @@ private boolean isContainsShadowInSQLHints(final ShadowRule rule, final String t private Map findByShadowColumn(final ShadowRule rule, final Collection relatedShadowTables) { for (String each : relatedShadowTables) { - Collection relatedShadowColumnNames = rule.getRelatedShadowColumnNames(operationType, each); - if (!relatedShadowColumnNames.isEmpty() && isMatchAnyColumnShadowAlgorithms(rule, each, relatedShadowColumnNames)) { - return rule.getRelatedShadowDataSourceMappings(each); + Collection shadowColumnNames = rule.getShadowColumnNames(operationType, each); + if (!shadowColumnNames.isEmpty() && isMatchAnyColumnShadowAlgorithms(rule, each, shadowColumnNames)) { + return rule.getShadowDataSourceMappings(each); } } return Collections.emptyMap(); @@ -129,7 +129,7 @@ private boolean isMatchAnyColumnShadowAlgorithms(final ShadowRule rule, final St } private boolean isMatchAnyColumnShadowAlgorithms(final ShadowRule rule, final String shadowTable, final String shadowColumn) { - Collection>> columnShadowAlgorithms = rule.getRelatedColumnShadowAlgorithms(operationType, shadowTable, shadowColumn); + Collection>> columnShadowAlgorithms = rule.getShadowAlgorithms(operationType, shadowTable, shadowColumn); if (columnShadowAlgorithms.isEmpty()) { return false; } diff --git a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java index a89f7bfd0b47b..7146fae748448 100644 --- a/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java +++ b/features/shadow/core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java @@ -43,18 +43,19 @@ /** * Databases shadow rule. */ -@Getter public final class ShadowRule implements DatabaseRule { + @Getter private final ShadowRuleConfiguration configuration; - private final Collection hintShadowAlgorithmNames = new LinkedList<>(); + private final Map shadowDataSourceRules = new LinkedHashMap<>(); - private final Map shadowDataSourceMappings = new LinkedHashMap<>(); + private final Map shadowTableRules = new LinkedHashMap<>(); + @Getter private final Map shadowAlgorithms = new LinkedHashMap<>(); - private final Map shadowTableRules = new LinkedHashMap<>(); + private final Collection hintShadowAlgorithmNames = new LinkedList<>(); private final ShadowAlgorithm defaultShadowAlgorithm; @@ -63,21 +64,21 @@ public final class ShadowRule implements DatabaseRule { public ShadowRule(final ShadowRuleConfiguration ruleConfig) { configuration = ruleConfig; - initShadowDataSourceMappings(ruleConfig.getDataSources()); - initShadowAlgorithmConfigurations(ruleConfig.getShadowAlgorithms()); + initDataSourceRules(ruleConfig.getDataSources()); + initShadowAlgorithms(ruleConfig.getShadowAlgorithms()); defaultShadowAlgorithm = shadowAlgorithms.get(ruleConfig.getDefaultShadowAlgorithmName()); if (defaultShadowAlgorithm instanceof HintShadowAlgorithm) { hintShadowAlgorithmNames.add(ruleConfig.getDefaultShadowAlgorithmName()); } - initShadowTableRules(ruleConfig.getTables()); - attributes = new RuleAttributes(new ShadowDataSourceMapperRuleAttribute(shadowDataSourceMappings)); + initTableRules(ruleConfig.getTables()); + attributes = new RuleAttributes(new ShadowDataSourceMapperRuleAttribute(shadowDataSourceRules)); } - private void initShadowDataSourceMappings(final Collection dataSources) { - dataSources.forEach(each -> shadowDataSourceMappings.put(each.getName(), new ShadowDataSourceRule(each.getProductionDataSourceName(), each.getShadowDataSourceName()))); + private void initDataSourceRules(final Collection dataSources) { + dataSources.forEach(each -> shadowDataSourceRules.put(each.getName(), new ShadowDataSourceRule(each.getProductionDataSourceName(), each.getShadowDataSourceName()))); } - private void initShadowAlgorithmConfigurations(final Map shadowAlgorithmConfigs) { + private void initShadowAlgorithms(final Map shadowAlgorithmConfigs) { shadowAlgorithmConfigs.forEach((key, value) -> { ShadowAlgorithm algorithm = TypedSPILoader.getService(ShadowAlgorithm.class, value.getType(), value.getProps()); if (algorithm instanceof HintShadowAlgorithm) { @@ -87,7 +88,7 @@ private void initShadowAlgorithmConfigurations(final Map tables) { + private void initTableRules(final Map tables) { tables.forEach((key, value) -> shadowTableRules.put(key, new ShadowTableRule(key, value.getDataSourceNames(), value.getShadowAlgorithmNames(), shadowAlgorithms))); } @@ -102,13 +103,13 @@ public Optional getDefaultShadowAlgorithm() { } /** - * Get related shadow tables. + * Filter shadow tables. * - * @param tableNames table names - * @return related shadow tables + * @param tableNames to be filtered table names + * @return filtered shadow tables */ @HighFrequencyInvocation - public Collection getRelatedShadowTables(final Collection tableNames) { + public Collection filterShadowTables(final Collection tableNames) { Collection result = new LinkedList<>(); for (String each : tableNames) { if (shadowTableRules.containsKey(each)) { @@ -144,14 +145,14 @@ public Collection>> getAllHintShadowAlgorithms } /** - * Get related hint shadow algorithms by table name. + * Get hint shadow algorithms by table name. * * @param tableName table name * @return hint shadow algorithms */ @HighFrequencyInvocation @SuppressWarnings("unchecked") - public Collection>> getRelatedHintShadowAlgorithms(final String tableName) { + public Collection>> getHintShadowAlgorithms(final String tableName) { Collection>> result = new LinkedList<>(); Collection hintShadowAlgorithmNames = shadowTableRules.get(tableName).getHintShadowAlgorithmNames(); for (String each : hintShadowAlgorithmNames) { @@ -161,20 +162,19 @@ public Collection>> getRelatedHintShadowAlgori } /** - * Get related column shadow algorithms by table name. + * Get shadow algorithms. * * @param shadowOperationType shadow operation type * @param tableName table name - * @param shadowColumn shadow column - * @return column shadow algorithms + * @param shadowColumnName shadow column name + * @return shadow algorithms */ @HighFrequencyInvocation @SuppressWarnings("unchecked") - public Collection>> getRelatedColumnShadowAlgorithms(final ShadowOperationType shadowOperationType, final String tableName, final String shadowColumn) { + public Collection>> getShadowAlgorithms(final ShadowOperationType shadowOperationType, final String tableName, final String shadowColumnName) { Collection>> result = new LinkedList<>(); - Map> columnShadowAlgorithmNames = shadowTableRules.get(tableName).getColumnShadowAlgorithmNames(); - for (ShadowAlgorithmNameRule each : columnShadowAlgorithmNames.getOrDefault(shadowOperationType, Collections.emptyList())) { - if (shadowColumn.equals(each.getShadowColumnName())) { + for (ShadowAlgorithmNameRule each : shadowTableRules.get(tableName).getColumnShadowAlgorithmNames().getOrDefault(shadowOperationType, Collections.emptyList())) { + if (shadowColumnName.equals(each.getShadowColumnName())) { result.add((ColumnShadowAlgorithm>) shadowAlgorithms.get(each.getShadowAlgorithmName())); } } @@ -182,17 +182,16 @@ public Collection>> getRelatedColumnShadowAl } /** - * Get related shadow column names. + * Get shadow column names. * * @param shadowOperationType shadow operation type * @param tableName table name - * @return related shadow column names + * @return got shadow column names */ @HighFrequencyInvocation - public Collection getRelatedShadowColumnNames(final ShadowOperationType shadowOperationType, final String tableName) { + public Collection getShadowColumnNames(final ShadowOperationType shadowOperationType, final String tableName) { Collection result = new LinkedList<>(); - Map> columnShadowAlgorithmNames = shadowTableRules.get(tableName).getColumnShadowAlgorithmNames(); - for (ShadowAlgorithmNameRule each : columnShadowAlgorithmNames.getOrDefault(shadowOperationType, Collections.emptyList())) { + for (ShadowAlgorithmNameRule each : shadowTableRules.get(tableName).getColumnShadowAlgorithmNames().getOrDefault(shadowOperationType, Collections.emptyList())) { result.add(each.getShadowColumnName()); } return result; @@ -202,13 +201,13 @@ public Collection getRelatedShadowColumnNames(final ShadowOperationType * Get shadow data source mappings. * * @param tableName table name - * @return shadow data source rules + * @return shadow data source mappings */ @HighFrequencyInvocation - public Map getRelatedShadowDataSourceMappings(final String tableName) { - Map result = new LinkedHashMap<>(); + public Map getShadowDataSourceMappings(final String tableName) { + Map result = new LinkedHashMap<>(shadowDataSourceRules.size(), 1F); for (String each : shadowTableRules.get(tableName).getShadowDataSources()) { - ShadowDataSourceRule dataSourceRule = shadowDataSourceMappings.get(each); + ShadowDataSourceRule dataSourceRule = shadowDataSourceRules.get(each); result.put(dataSourceRule.getProductionDataSource(), dataSourceRule.getShadowDataSource()); } return result; @@ -221,10 +220,10 @@ public Map getRelatedShadowDataSourceMappings(final String table */ @HighFrequencyInvocation public Map getAllShadowDataSourceMappings() { - Map result = new LinkedHashMap<>(); - for (Entry entry : shadowDataSourceMappings.entrySet()) { - ShadowDataSourceRule rule = entry.getValue(); - result.put(rule.getProductionDataSource(), rule.getShadowDataSource()); + Map result = new LinkedHashMap<>(shadowDataSourceRules.size(), 1F); + for (Entry entry : shadowDataSourceRules.entrySet()) { + ShadowDataSourceRule dataSourceRule = entry.getValue(); + result.put(dataSourceRule.getProductionDataSource(), dataSourceRule.getShadowDataSource()); } return result; } @@ -232,12 +231,12 @@ public Map getAllShadowDataSourceMappings() { /** * Find production data source name. * - * @param actualDataSourceName actual data source name + * @param logicDataSourceName logic data source name * @return found production data source name */ @HighFrequencyInvocation - public Optional findProductionDataSourceName(final String actualDataSourceName) { - ShadowDataSourceRule dataSourceRule = shadowDataSourceMappings.get(actualDataSourceName); + public Optional findProductionDataSourceName(final String logicDataSourceName) { + ShadowDataSourceRule dataSourceRule = shadowDataSourceRules.get(logicDataSourceName); return null == dataSourceRule ? Optional.empty() : Optional.of(dataSourceRule.getProductionDataSource()); } } diff --git a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java index af711a818dd87..0f382566b08a2 100644 --- a/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java +++ b/features/shadow/core/src/test/java/org/apache/shardingsphere/shadow/rule/ShadowRuleTest.java @@ -58,14 +58,14 @@ private ShadowRuleConfiguration createRuleConfiguration() { } private Collection createDataSources() { - return Arrays.asList(new ShadowDataSourceConfiguration("shadow_ds_0", "ds0", "ds0_shadow"), - new ShadowDataSourceConfiguration("shadow_ds_1", "ds1", "ds1_shadow")); + return Arrays.asList(new ShadowDataSourceConfiguration("foo_ds_0", "prod_ds_0", "shadow_ds_0"), + new ShadowDataSourceConfiguration("foo_ds_1", "prod_ds_1", "shadow_ds_1")); } private Map createTables() { Map result = new LinkedHashMap<>(); - result.put("foo_tbl", new ShadowTableConfiguration(Collections.singleton("shadow_ds_0"), createShadowAlgorithmNames("foo_tbl"))); - result.put("bar_tbl", new ShadowTableConfiguration(Collections.singleton("shadow_ds_1"), createShadowAlgorithmNames("bar_tbl"))); + result.put("foo_tbl", new ShadowTableConfiguration(Collections.singleton("foo_ds_0"), createShadowAlgorithmNames("foo_tbl"))); + result.put("bar_tbl", new ShadowTableConfiguration(Collections.singleton("foo_ds_1"), createShadowAlgorithmNames("bar_tbl"))); return result; } @@ -93,43 +93,14 @@ private Map createShadowAlgorithms() { return result; } - @Test - void assertNewShadowRulSuccessByShadowRuleConfiguration() { - assertShadowDataSourceMappings(rule.getShadowDataSourceMappings()); - assertShadowTableRules(rule.getShadowTableRules()); - } - - private void assertShadowDataSourceMappings(final Map shadowDataSourceMappings) { - assertThat(shadowDataSourceMappings.size(), is(2)); - assertThat(shadowDataSourceMappings.get("shadow_ds_0").getProductionDataSource(), is("ds0")); - assertThat(shadowDataSourceMappings.get("shadow_ds_0").getShadowDataSource(), is("ds0_shadow")); - assertThat(shadowDataSourceMappings.get("shadow_ds_1").getProductionDataSource(), is("ds1")); - assertThat(shadowDataSourceMappings.get("shadow_ds_1").getShadowDataSource(), is("ds1_shadow")); - } - - private void assertShadowTableRules(final Map shadowTableRules) { - assertThat(shadowTableRules.size(), is(2)); - shadowTableRules.forEach(this::assertShadowTableRule); - } - - private void assertShadowTableRule(final String tableName, final ShadowTableRule shadowTableRule) { - if ("foo_tbl".equals(tableName)) { - assertThat(shadowTableRule.getHintShadowAlgorithmNames().size(), is(1)); - assertThat(shadowTableRule.getColumnShadowAlgorithmNames().size(), is(2)); - } else { - assertThat(shadowTableRule.getHintShadowAlgorithmNames().size(), is(1)); - assertThat(shadowTableRule.getColumnShadowAlgorithmNames().size(), is(1)); - } - } - @Test void assertGetDefaultShadowAlgorithm() { assertFalse(rule.getDefaultShadowAlgorithm().isPresent()); } @Test - void assertGetRelatedShadowTables() { - assertThat(rule.getRelatedShadowTables(Arrays.asList("foo_tbl", "no_tbl")), is(Collections.singletonList("foo_tbl"))); + void assertFilterShadowTables() { + assertThat(rule.filterShadowTables(Arrays.asList("foo_tbl", "no_tbl")), is(Collections.singletonList("foo_tbl"))); } @Test @@ -143,38 +114,40 @@ void assertGetAllHintShadowAlgorithms() { } @Test - void assertGetRelatedHintShadowAlgorithms() { - assertThat(rule.getRelatedHintShadowAlgorithms("foo_tbl").size(), is(1)); + void assertGetHintShadowAlgorithms() { + assertThat(rule.getHintShadowAlgorithms("foo_tbl").size(), is(1)); } @Test - void assertGetRelatedColumnShadowAlgorithms() { - assertThat(rule.getRelatedColumnShadowAlgorithms(ShadowOperationType.INSERT, "foo_tbl", "foo_id").size(), is(1)); + void assertGetShadowAlgorithms() { + assertThat(rule.getShadowAlgorithms(ShadowOperationType.INSERT, "foo_tbl", "foo_id").size(), is(1)); } @Test - void assertGetRelatedShadowColumnNames() { - assertThat(rule.getRelatedShadowColumnNames(ShadowOperationType.INSERT, "foo_tbl").size(), is(1)); + void assertGetShadowColumnNames() { + assertThat(rule.getShadowColumnNames(ShadowOperationType.INSERT, "foo_tbl").size(), is(1)); } @Test - void assertGetRelatedShadowDataSourceMappings() { - assertThat(rule.getRelatedShadowDataSourceMappings("foo_tbl").size(), is(1)); + void assertGetShadowDataSourceMappings() { + assertThat(rule.getShadowDataSourceMappings("foo_tbl"), is(Collections.singletonMap("prod_ds_0", "shadow_ds_0"))); } @Test void assertGetAllShadowDataSourceMappings() { assertThat(rule.getAllShadowDataSourceMappings().size(), is(2)); + assertThat(rule.getAllShadowDataSourceMappings().get("prod_ds_0"), is("shadow_ds_0")); + assertThat(rule.getAllShadowDataSourceMappings().get("prod_ds_1"), is("shadow_ds_1")); } @Test void assertFindProductionDataSourceNameSuccess() { - assertThat(rule.findProductionDataSourceName("shadow_ds_0"), is(Optional.of("ds0"))); - assertThat(rule.findProductionDataSourceName("shadow_ds_1"), is(Optional.of("ds1"))); + assertThat(rule.findProductionDataSourceName("foo_ds_0"), is(Optional.of("prod_ds_0"))); + assertThat(rule.findProductionDataSourceName("foo_ds_1"), is(Optional.of("prod_ds_1"))); } @Test void assertFindProductionDataSourceNameFailed() { - assertFalse(rule.findProductionDataSourceName("shadow_ds_2").isPresent()); + assertFalse(rule.findProductionDataSourceName("foo_ds_2").isPresent()); } } diff --git a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/fixture/DistSQLShadowAlgorithmFixture.java b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/fixture/DistSQLShadowAlgorithmFixture.java index ee0ad6e190325..9ded25848996a 100644 --- a/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/fixture/DistSQLShadowAlgorithmFixture.java +++ b/features/shadow/distsql/handler/src/test/java/org/apache/shardingsphere/shadow/distsql/fixture/DistSQLShadowAlgorithmFixture.java @@ -25,7 +25,7 @@ public final class DistSQLShadowAlgorithmFixture implements HintShadowAlgorithm { @Override - public boolean isShadow(final Collection relatedShadowTables, final PreciseHintShadowValue hintShadowValue) { + public boolean isShadow(final Collection shadowTableNames, final PreciseHintShadowValue hintShadowValue) { return false; }