diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/RuleItemChangedEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/RuleItemChangedEvent.java new file mode 100644 index 0000000000000..42aefc77aee10 --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/RuleItemChangedEvent.java @@ -0,0 +1,33 @@ +/* + * 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.mode.event.dispatch.rule; + +import org.apache.shardingsphere.mode.event.dispatch.DispatchEvent; + +/** + * Rule item changed event. + */ +public interface RuleItemChangedEvent extends DispatchEvent { + + /** + * Get rule item type. + * + * @return rule item type + */ + String getType(); +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterNamedRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterNamedRuleItemEvent.java new file mode 100644 index 0000000000000..237c00e0b3748 --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterNamedRuleItemEvent.java @@ -0,0 +1,39 @@ +/* + * 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.mode.event.dispatch.rule.alter; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Alter named rule item event. + */ +@RequiredArgsConstructor +@Getter +public final class AlterNamedRuleItemEvent implements AlterRuleItemEvent { + + private final String databaseName; + + private final String itemName; + + private final String activeVersionKey; + + private final String activeVersion; + + private final String type; +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterRuleItemEvent.java new file mode 100644 index 0000000000000..55e4780a6c4a0 --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterRuleItemEvent.java @@ -0,0 +1,47 @@ +/* + * 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.mode.event.dispatch.rule.alter; + +import org.apache.shardingsphere.mode.event.dispatch.rule.RuleItemChangedEvent; + +/** + * Alter rule item event. + */ +public interface AlterRuleItemEvent extends RuleItemChangedEvent { + + /** + * Get database name. + * + * @return database name + */ + String getDatabaseName(); + + /** + * Get active version key. + * + * @return active version key + */ + String getActiveVersionKey(); + + /** + * Get active version. + * + * @return active version + */ + String getActiveVersion(); +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterUniqueRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterUniqueRuleItemEvent.java new file mode 100644 index 0000000000000..5bda761cae676 --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/alter/AlterUniqueRuleItemEvent.java @@ -0,0 +1,37 @@ +/* + * 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.mode.event.dispatch.rule.alter; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Alter unique rule item event. + */ +@RequiredArgsConstructor +@Getter +public final class AlterUniqueRuleItemEvent implements AlterRuleItemEvent { + + private final String databaseName; + + private final String activeVersionKey; + + private final String activeVersion; + + private final String type; +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropNamedRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropNamedRuleItemEvent.java new file mode 100644 index 0000000000000..6783a26c75e67 --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropNamedRuleItemEvent.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.mode.event.dispatch.rule.drop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Drop named rule item event. + */ +@RequiredArgsConstructor +@Getter +public final class DropNamedRuleItemEvent implements DropRuleItemEvent { + + private final String databaseName; + + private final String itemName; + + private final String type; +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropRuleItemEvent.java new file mode 100644 index 0000000000000..7a0413f92bd7b --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropRuleItemEvent.java @@ -0,0 +1,33 @@ +/* + * 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.mode.event.dispatch.rule.drop; + +import org.apache.shardingsphere.mode.event.dispatch.rule.RuleItemChangedEvent; + +/** + * Drop rule item event. + */ +public interface DropRuleItemEvent extends RuleItemChangedEvent { + + /** + * Get database name. + * + * @return database name + */ + String getDatabaseName(); +} diff --git a/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropUniqueRuleItemEvent.java b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropUniqueRuleItemEvent.java new file mode 100644 index 0000000000000..561be2372c69b --- /dev/null +++ b/mode/api/src/main/java/org/apache/shardingsphere/mode/event/dispatch/rule/drop/DropUniqueRuleItemEvent.java @@ -0,0 +1,33 @@ +/* + * 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.mode.event.dispatch.rule.drop; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Drop unique rule item event. + */ +@RequiredArgsConstructor +@Getter +public final class DropUniqueRuleItemEvent implements DropRuleItemEvent { + + private final String databaseName; + + private final String type; +} diff --git a/mode/core/src/main/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilder.java b/mode/core/src/main/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilder.java new file mode 100644 index 0000000000000..11c39e6f454ee --- /dev/null +++ b/mode/core/src/main/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilder.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.mode.event.dispatch.builder; + +import com.google.common.base.Strings; +import org.apache.shardingsphere.mode.event.dispatch.DispatchEvent; +import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader; +import org.apache.shardingsphere.mode.event.DataChangedEvent; +import org.apache.shardingsphere.mode.event.DataChangedEvent.Type; +import org.apache.shardingsphere.mode.event.dispatch.rule.RuleItemChangedEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.path.rule.RuleNodePath; +import org.apache.shardingsphere.mode.path.rule.item.NamedRuleItemNodePath; +import org.apache.shardingsphere.mode.path.rule.item.UniqueRuleItemNodePath; +import org.apache.shardingsphere.mode.spi.RuleNodePathProvider; + +import java.util.Map.Entry; +import java.util.Optional; + +/** + * Rule configuration changed event builder. + */ +public final class RuleConfigurationChangedEventBuilder { + + /** + * Build rule changed event. + * + * @param databaseName database name + * @param event data changed event + * @return built event + */ + public Optional build(final String databaseName, final DataChangedEvent event) { + for (RuleNodePathProvider each : ShardingSphereServiceLoader.getServiceInstances(RuleNodePathProvider.class)) { + Optional result = build(each.getRuleNodePath(), databaseName, event); + if (result.isPresent()) { + return result; + } + } + return Optional.empty(); + } + + private Optional build(final RuleNodePath ruleNodePath, final String databaseName, final DataChangedEvent event) { + if (!ruleNodePath.getRoot().isValidatedPath(event.getKey()) || Type.DELETED != event.getType() && Strings.isNullOrEmpty(event.getValue())) { + return Optional.empty(); + } + for (Entry entry : ruleNodePath.getNamedItems().entrySet()) { + Optional itemName; + if (Type.ADDED == event.getType() || Type.UPDATED == event.getType()) { + itemName = entry.getValue().getNameByActiveVersion(event.getKey()); + } else { + itemName = entry.getValue().getNameByItemPath(event.getKey()); + } + if (itemName.isPresent()) { + return Optional.of(create(databaseName, itemName.get(), event, ruleNodePath.getRoot().getRuleType() + "." + entry.getKey())); + } + } + for (Entry entry : ruleNodePath.getUniqueItems().entrySet()) { + if (entry.getValue().isActiveVersionPath(event.getKey())) { + return Optional.of(create(databaseName, event, ruleNodePath.getRoot().getRuleType() + "." + entry.getKey())); + } + } + return Optional.empty(); + } + + private RuleItemChangedEvent create(final String databaseName, final String itemName, final DataChangedEvent event, final String type) { + return Type.ADDED == event.getType() || Type.UPDATED == event.getType() + ? new AlterNamedRuleItemEvent(databaseName, itemName, event.getKey(), event.getValue(), type) + : new DropNamedRuleItemEvent(databaseName, itemName, type); + } + + private RuleItemChangedEvent create(final String databaseName, final DataChangedEvent event, final String type) { + return Type.ADDED == event.getType() || Type.UPDATED == event.getType() + ? new AlterUniqueRuleItemEvent(databaseName, event.getKey(), event.getValue(), type) + : new DropUniqueRuleItemEvent(databaseName, type); + } +} diff --git a/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/manager/RuleItemManager.java b/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/manager/RuleItemManager.java index 08877b0526282..6d3adafe72378 100644 --- a/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/manager/RuleItemManager.java +++ b/mode/core/src/main/java/org/apache/shardingsphere/mode/metadata/manager/RuleItemManager.java @@ -18,26 +18,21 @@ package org.apache.shardingsphere.mode.metadata.manager; import com.google.common.base.Preconditions; -import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.infra.config.rule.RuleConfiguration; import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader; import org.apache.shardingsphere.metadata.persist.MetaDataPersistService; -import org.apache.shardingsphere.mode.event.DataChangedEvent.Type; import org.apache.shardingsphere.mode.metadata.MetaDataContexts; -import org.apache.shardingsphere.mode.spi.PersistRepository; -import org.apache.shardingsphere.mode.spi.RuleItemConfigurationChangedProcessor; import org.apache.shardingsphere.mode.spi.item.AlterRuleItem; import org.apache.shardingsphere.mode.spi.item.DropRuleItem; -import org.apache.shardingsphere.mode.spi.item.RuleItemChanged; +import org.apache.shardingsphere.mode.spi.PersistRepository; +import org.apache.shardingsphere.mode.spi.RuleItemConfigurationChangedProcessor; import java.sql.SQLException; -import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; /** * Rule item manager. */ -@Slf4j public class RuleItemManager { private final AtomicReference metaDataContexts; @@ -46,61 +41,47 @@ public class RuleItemManager { private final MetaDataPersistService metaDataPersistService; - private final RuleItemChangedBuilder ruleItemChangedBuilder; - public RuleItemManager(final AtomicReference metaDataContexts, final PersistRepository repository, final DatabaseRuleConfigurationManager ruleConfigManager) { this.metaDataContexts = metaDataContexts; this.ruleConfigManager = ruleConfigManager; metaDataPersistService = new MetaDataPersistService(repository); - ruleItemChangedBuilder = new RuleItemChangedBuilder(); } /** * Alter with rule item. * - * @param databaseName database name - * @param activeVersionKey active version key - * @param activeVersion active version - * @param changeType change type + * @param alterRuleItem alter rule item + * @throws SQLException SQL Exception */ - public void alterRuleItem(final String databaseName, final String activeVersionKey, final String activeVersion, final Type changeType) { - Optional ruleItemChanged = ruleItemChangedBuilder.build(databaseName, activeVersionKey, activeVersion, changeType); - if (!ruleItemChanged.isPresent()) { - return; - } - RuleItemConfigurationChangedProcessor processor = TypedSPILoader.getService(RuleItemConfigurationChangedProcessor.class, ruleItemChanged.get().getType()); - if (ruleItemChanged.get() instanceof AlterRuleItem) { - alter(databaseName, activeVersionKey, activeVersion, (AlterRuleItem) ruleItemChanged.get(), processor); - } else if (ruleItemChanged.get() instanceof DropRuleItem) { - drop(databaseName, (DropRuleItem) ruleItemChanged.get(), processor); - } - } - - private void alter(final String databaseName, final String activeVersionKey, final String activeVersion, final AlterRuleItem alterRuleItem, final RuleItemConfigurationChangedProcessor processor) { - Preconditions.checkArgument(activeVersion.equals(metaDataPersistService.getMetaDataVersionPersistService() - .getActiveVersionByFullPath(activeVersionKey)), "Invalid active version: {} of key: {}", activeVersion, activeVersionKey); - String yamlContent = metaDataPersistService.getMetaDataVersionPersistService().getVersionPathByActiveVersion(activeVersionKey, activeVersion); + public void alterRuleItem(final AlterRuleItem alterRuleItem) throws SQLException { + Preconditions.checkArgument(alterRuleItem.getActiveVersion().equals(metaDataPersistService.getMetaDataVersionPersistService() + .getActiveVersionByFullPath(alterRuleItem.getActiveVersionKey())), "Invalid active version: {} of key: {}", + alterRuleItem.getActiveVersion(), alterRuleItem.getActiveVersionKey()); + RuleItemConfigurationChangedProcessor processor = TypedSPILoader.getService(RuleItemConfigurationChangedProcessor.class, alterRuleItem.getType()); + String yamlContent = metaDataPersistService.getMetaDataVersionPersistService() + .getVersionPathByActiveVersion(alterRuleItem.getActiveVersionKey(), alterRuleItem.getActiveVersion()); + String databaseName = alterRuleItem.getDatabaseName(); RuleConfiguration currentRuleConfig = processor.findRuleConfiguration(metaDataContexts.get().getMetaData().getDatabase(databaseName)); synchronized (this) { processor.changeRuleItemConfiguration(alterRuleItem, currentRuleConfig, processor.swapRuleItemConfiguration(alterRuleItem, yamlContent)); - try { - ruleConfigManager.alterRuleConfiguration(databaseName, currentRuleConfig); - } catch (final SQLException ex) { - log.error("Alter rule configuration failed, databaseName:{}, key:{}, version:{}", databaseName, activeVersionKey, activeVersion, ex); - } + ruleConfigManager.alterRuleConfiguration(databaseName, currentRuleConfig); } } - private void drop(final String databaseName, final DropRuleItem dropRuleItem, final RuleItemConfigurationChangedProcessor processor) { + /** + * Drop with rule item. + * + * @param dropRuleItem drop rule item + * @throws SQLException SQL Exception + */ + public void dropRuleItem(final DropRuleItem dropRuleItem) throws SQLException { + String databaseName = dropRuleItem.getDatabaseName(); Preconditions.checkState(metaDataContexts.get().getMetaData().containsDatabase(databaseName), "No database '%s' exists.", databaseName); + RuleItemConfigurationChangedProcessor processor = TypedSPILoader.getService(RuleItemConfigurationChangedProcessor.class, dropRuleItem.getType()); RuleConfiguration currentRuleConfig = processor.findRuleConfiguration(metaDataContexts.get().getMetaData().getDatabase(databaseName)); synchronized (this) { processor.dropRuleItemConfiguration(dropRuleItem, currentRuleConfig); - try { - ruleConfigManager.dropRuleConfiguration(databaseName, currentRuleConfig); - } catch (final SQLException ex) { - log.error("Drop rule configuration failed, databaseName:{}, type:{}", databaseName, dropRuleItem.getType(), ex); - } + ruleConfigManager.dropRuleConfiguration(databaseName, currentRuleConfig); } } } diff --git a/mode/core/src/test/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilderTest.java b/mode/core/src/test/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilderTest.java new file mode 100644 index 0000000000000..bd4de594750d2 --- /dev/null +++ b/mode/core/src/test/java/org/apache/shardingsphere/mode/event/dispatch/builder/RuleConfigurationChangedEventBuilderTest.java @@ -0,0 +1,125 @@ +/* + * 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.mode.event.dispatch.builder; + +import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader; +import org.apache.shardingsphere.mode.event.DataChangedEvent; +import org.apache.shardingsphere.mode.event.DataChangedEvent.Type; +import org.apache.shardingsphere.mode.event.dispatch.DispatchEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.path.rule.RuleNodePath; +import org.apache.shardingsphere.mode.spi.RuleNodePathProvider; +import org.apache.shardingsphere.test.mock.AutoMockExtension; +import org.apache.shardingsphere.test.mock.StaticMockSettings; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Stream; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(AutoMockExtension.class) +@StaticMockSettings(ShardingSphereServiceLoader.class) +class RuleConfigurationChangedEventBuilderTest { + + @Test + void assertBuildWithoutRuleNodePathProvider() { + when(ShardingSphereServiceLoader.getServiceInstances(RuleNodePathProvider.class)).thenReturn(Collections.emptyList()); + assertFalse(new RuleConfigurationChangedEventBuilder().build("foo_db", new DataChangedEvent("k", "v", Type.IGNORED)).isPresent()); + } + + @ParameterizedTest(name = "{0}") + @ArgumentsSource(TestCaseArgumentsProvider.class) + void assertBuild(final String name, final String eventKey, final String eventValue, final Type type, final boolean isEventPresent, final Class dispatchEventClass) { + RuleNodePathProvider ruleNodePathProvider = mock(RuleNodePathProvider.class, RETURNS_DEEP_STUBS); + when(ruleNodePathProvider.getRuleNodePath()).thenReturn(new RuleNodePath("fixture", Collections.singleton("named"), Collections.singleton("unique"))); + when(ShardingSphereServiceLoader.getServiceInstances(RuleNodePathProvider.class)).thenReturn(Collections.singleton(ruleNodePathProvider)); + Optional actual = new RuleConfigurationChangedEventBuilder().build("foo_db", new DataChangedEvent(eventKey, eventValue, type)); + assertThat(actual.isPresent(), is(isEventPresent)); + if (actual.isPresent()) { + if (dispatchEventClass == AlterNamedRuleItemEvent.class) { + assertDispatchEvent((AlterNamedRuleItemEvent) actual.get()); + } else if (dispatchEventClass == DropNamedRuleItemEvent.class) { + assertDispatchEvent((DropNamedRuleItemEvent) actual.get()); + } else if (dispatchEventClass == AlterUniqueRuleItemEvent.class) { + assertDispatchEvent((AlterUniqueRuleItemEvent) actual.get()); + } else if (dispatchEventClass == DropUniqueRuleItemEvent.class) { + assertDispatchEvent((DropUniqueRuleItemEvent) actual.get()); + } else { + fail("No such event type."); + } + } + } + + private void assertDispatchEvent(final AlterNamedRuleItemEvent actual) { + assertThat(actual.getDatabaseName(), is("foo_db")); + assertThat(actual.getItemName(), is("xxx")); + assertThat(actual.getType(), is("fixture.named")); + } + + private void assertDispatchEvent(final DropNamedRuleItemEvent actual) { + assertThat(actual.getDatabaseName(), is("foo_db")); + assertThat(actual.getItemName(), is("xxx")); + assertThat(actual.getType(), is("fixture.named")); + } + + private void assertDispatchEvent(final AlterUniqueRuleItemEvent actual) { + assertThat(actual.getDatabaseName(), is("foo_db")); + assertThat(actual.getActiveVersionKey(), is("/metadata/fixture/rules/fixture/unique/active_version")); + assertThat(actual.getActiveVersion(), is("foo")); + assertThat(actual.getType(), is("fixture.unique")); + } + + private void assertDispatchEvent(final DropUniqueRuleItemEvent actual) { + assertThat(actual.getDatabaseName(), is("foo_db")); + assertThat(actual.getType(), is("fixture.unique")); + } + + private static class TestCaseArgumentsProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(final ExtensionContext extensionContext) { + return Stream.of( + Arguments.of("InvalidPath", "/metadata/invalid/rules/fixture", "foo", Type.ADDED, false, null), + Arguments.of("AddEventWithEmptyValue", "/metadata/fixture/rules/fixture/versions/0", "", Type.ADDED, false, null), + Arguments.of("PathNotFound", "/metadata/fixture/rules/fixture/versions/0", "foo", Type.ADDED, false, null), + Arguments.of("AddEventWithNamedRuleItemNodePath", "/metadata/fixture/rules/fixture/named/xxx/active_version", "foo", Type.ADDED, true, AlterNamedRuleItemEvent.class), + Arguments.of("UpdateEventWithNamedRuleItemNodePath", "/metadata/fixture/rules/fixture/named/xxx/active_version", "foo", Type.UPDATED, true, AlterNamedRuleItemEvent.class), + Arguments.of("DeleteEventWithNamedRuleItemNodePath", "/metadata/fixture/rules/fixture/named/xxx", "foo", Type.DELETED, true, DropNamedRuleItemEvent.class), + Arguments.of("AddEventWithUniqueRuleItemNodePath", "/metadata/fixture/rules/fixture/unique/active_version", "foo", Type.ADDED, true, AlterUniqueRuleItemEvent.class), + Arguments.of("UpdateEventWithUniqueRuleItemNodePath", "/metadata/fixture/rules/fixture/unique/active_version", "foo", Type.UPDATED, true, AlterUniqueRuleItemEvent.class), + Arguments.of("DeleteEventWithUniqueRuleItemNodePath", "/metadata/fixture/rules/fixture/unique/active_version", "foo", Type.DELETED, true, DropUniqueRuleItemEvent.class)); + } + } +} diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/DataChangedEventListenerRegistry.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/DataChangedEventListenerRegistry.java index 3bfed6eff42d7..7daeb327d3471 100644 --- a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/DataChangedEventListenerRegistry.java +++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/DataChangedEventListenerRegistry.java @@ -24,7 +24,6 @@ import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.builder.DispatchEventBuilder; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.listener.type.DatabaseMetaDataChangedListener; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.listener.type.GlobalMetaDataChangedListener; -import org.apache.shardingsphere.mode.metadata.manager.RuleItemManager; import org.apache.shardingsphere.mode.repository.cluster.ClusterPersistRepository; import java.util.Collection; @@ -40,13 +39,10 @@ public final class DataChangedEventListenerRegistry { private final Collection databaseNames; - private final RuleItemManager ruleItemManager; - public DataChangedEventListenerRegistry(final ContextManager contextManager, final Collection databaseNames) { repository = (ClusterPersistRepository) contextManager.getPersistServiceFacade().getRepository(); eventBusContext = contextManager.getComputeNodeInstanceContext().getEventBusContext(); this.databaseNames = databaseNames; - ruleItemManager = contextManager.getMetaDataContextManager().getRuleItemManager(); } /** @@ -58,7 +54,7 @@ public void register() { } private void registerDatabaseListeners(final String databaseName) { - repository.watch(DatabaseMetaDataNode.getDatabaseNamePath(databaseName), new DatabaseMetaDataChangedListener(eventBusContext, ruleItemManager)); + repository.watch(DatabaseMetaDataNode.getDatabaseNamePath(databaseName), new DatabaseMetaDataChangedListener(eventBusContext)); } private void registerGlobalListeners(final DispatchEventBuilder builder) { diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListener.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListener.java index 8cdbfa1809a2d..9fa7a4f77b374 100644 --- a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListener.java +++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListener.java @@ -21,9 +21,9 @@ import org.apache.shardingsphere.infra.util.eventbus.EventBusContext; import org.apache.shardingsphere.metadata.persist.node.DatabaseMetaDataNode; import org.apache.shardingsphere.mode.event.DataChangedEvent; -import org.apache.shardingsphere.mode.event.dispatch.DispatchEvent; import org.apache.shardingsphere.mode.event.dispatch.builder.MetaDataChangedEventBuilder; -import org.apache.shardingsphere.mode.metadata.manager.RuleItemManager; +import org.apache.shardingsphere.mode.event.dispatch.builder.RuleConfigurationChangedEventBuilder; +import org.apache.shardingsphere.mode.event.dispatch.DispatchEvent; import org.apache.shardingsphere.mode.repository.cluster.listener.DataChangedEventListener; import java.util.Optional; @@ -36,24 +36,18 @@ public final class DatabaseMetaDataChangedListener implements DataChangedEventLi private final EventBusContext eventBusContext; - private final RuleItemManager ruleItemManager; - @Override public void onChange(final DataChangedEvent event) { - handleDataChangedEvent(event); + createDispatchEvent(event).ifPresent(eventBusContext::post); } - private void handleDataChangedEvent(final DataChangedEvent event) { + private Optional createDispatchEvent(final DataChangedEvent event) { String key = event.getKey(); Optional databaseName = DatabaseMetaDataNode.getDatabaseNameBySchemaNode(key); if (!databaseName.isPresent()) { - return; + return Optional.empty(); } Optional metaDataChangedEvent = new MetaDataChangedEventBuilder().build(databaseName.get(), event); - if (metaDataChangedEvent.isPresent()) { - eventBusContext.post(metaDataChangedEvent.get()); - } else { - ruleItemManager.alterRuleItem(databaseName.get(), event.getKey(), event.getValue(), event.getType()); - } + return metaDataChangedEvent.isPresent() ? metaDataChangedEvent : new RuleConfigurationChangedEventBuilder().build(databaseName.get(), event); } } diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/ClusterDispatchEventSubscriberRegistry.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/ClusterDispatchEventSubscriberRegistry.java index 78f9260fb24b0..efe9292425a27 100644 --- a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/ClusterDispatchEventSubscriberRegistry.java +++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/ClusterDispatchEventSubscriberRegistry.java @@ -29,6 +29,7 @@ import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.ProcessListChangedSubscriber; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.PropertiesEventSubscriber; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.QualifiedDataSourceSubscriber; +import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.RuleItemChangedSubscriber; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.StateChangedSubscriber; import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.type.StorageUnitEventSubscriber; @@ -44,7 +45,7 @@ public final class ClusterDispatchEventSubscriberRegistry { private final Collection subscribers; public ClusterDispatchEventSubscriberRegistry(final ContextManager contextManager) { - subscribers = Arrays.asList( + subscribers = Arrays.asList(new RuleItemChangedSubscriber(contextManager), new MetaDataChangedSubscriber(contextManager), new ListenerAssistedSubscriber(contextManager), new StateChangedSubscriber(contextManager), diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/ListenerAssistedSubscriber.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/ListenerAssistedSubscriber.java index 26e2ea21c381c..c2d5b80768fd5 100644 --- a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/ListenerAssistedSubscriber.java +++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/ListenerAssistedSubscriber.java @@ -53,8 +53,7 @@ public ListenerAssistedSubscriber(final ContextManager contextManager) { */ @Subscribe public synchronized void renew(final CreateDatabaseListenerAssistedEvent event) { - repository.watch(DatabaseMetaDataNode.getDatabaseNamePath(event.getDatabaseName()), new DatabaseMetaDataChangedListener(contextManager.getComputeNodeInstanceContext().getEventBusContext(), - contextManager.getMetaDataContextManager().getRuleItemManager())); + repository.watch(DatabaseMetaDataNode.getDatabaseNamePath(event.getDatabaseName()), new DatabaseMetaDataChangedListener(contextManager.getComputeNodeInstanceContext().getEventBusContext())); contextManager.getMetaDataContextManager().getSchemaMetaDataManager().addDatabase(event.getDatabaseName()); contextManager.getPersistServiceFacade().getListenerAssistedPersistService().deleteDatabaseNameListenerAssisted(event.getDatabaseName()); refreshStatisticsData(); diff --git a/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriber.java b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriber.java new file mode 100644 index 0000000000000..9db8351b9dd3a --- /dev/null +++ b/mode/type/cluster/core/src/main/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriber.java @@ -0,0 +1,93 @@ +/* + * 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.mode.manager.cluster.event.dispatch.subscriber.type; + +import com.google.common.eventbus.Subscribe; +import lombok.RequiredArgsConstructor; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropUniqueRuleItemEvent; +import org.apache.shardingsphere.mode.manager.ContextManager; +import org.apache.shardingsphere.mode.manager.cluster.event.dispatch.subscriber.DispatchEventSubscriber; +import org.apache.shardingsphere.mode.metadata.manager.RuleItemManager; +import org.apache.shardingsphere.mode.spi.item.AlterNamedRuleItem; +import org.apache.shardingsphere.mode.spi.item.AlterRuleItem; +import org.apache.shardingsphere.mode.spi.item.AlterUniqueRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropNamedRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropUniqueRuleItem; + +import java.sql.SQLException; + +/** + * Rule item changed subscriber. + */ +@RequiredArgsConstructor +public final class RuleItemChangedSubscriber implements DispatchEventSubscriber { + + private final RuleItemManager ruleItemManager; + + public RuleItemChangedSubscriber(final ContextManager contextManager) { + ruleItemManager = contextManager.getMetaDataContextManager().getRuleItemManager(); + } + + /** + * Renew with alter rule item. + * + * @param event alter rule item event + * @throws SQLException SQL Exception + */ + @Subscribe + public void renew(final AlterRuleItemEvent event) throws SQLException { + // TODO remove the event and this subscriber + ruleItemManager.alterRuleItem(convertToAlterRuleItem(event)); + } + + /** + * Renew with drop rule item. + * + * @param event drop rule item event + * @throws SQLException SQL Exception + */ + @Subscribe + public void renew(final DropRuleItemEvent event) throws SQLException { + // TODO remove the event and this subscriber + ruleItemManager.dropRuleItem(convertToDropRuleItem(event)); + } + + private AlterRuleItem convertToAlterRuleItem(final AlterRuleItemEvent event) { + if (event instanceof AlterNamedRuleItemEvent) { + AlterNamedRuleItemEvent alterNamedRuleItemEvent = (AlterNamedRuleItemEvent) event; + return new AlterNamedRuleItem(alterNamedRuleItemEvent.getDatabaseName(), alterNamedRuleItemEvent.getItemName(), event.getActiveVersionKey(), event.getActiveVersion(), event.getType()); + } + AlterUniqueRuleItemEvent alterUniqueRuleItemEvent = (AlterUniqueRuleItemEvent) event; + return new AlterUniqueRuleItem(alterUniqueRuleItemEvent.getDatabaseName(), alterUniqueRuleItemEvent.getActiveVersionKey(), event.getActiveVersion(), event.getType()); + } + + private DropRuleItem convertToDropRuleItem(final DropRuleItemEvent event) { + if (event instanceof DropNamedRuleItemEvent) { + DropNamedRuleItemEvent dropNamedRuleItemEvent = (DropNamedRuleItemEvent) event; + return new DropNamedRuleItem(dropNamedRuleItemEvent.getDatabaseName(), dropNamedRuleItemEvent.getItemName(), event.getType()); + } + DropUniqueRuleItemEvent dropUniqueRuleItemEvent = (DropUniqueRuleItemEvent) event; + return new DropUniqueRuleItem(dropUniqueRuleItemEvent.getDatabaseName(), event.getType()); + } +} diff --git a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListenerTest.java b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListenerTest.java index d396a02320a1e..d1cdabd4faa51 100644 --- a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListenerTest.java +++ b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/listener/type/DatabaseMetaDataChangedListenerTest.java @@ -20,7 +20,6 @@ import org.apache.shardingsphere.infra.util.eventbus.EventBusContext; import org.apache.shardingsphere.mode.event.DataChangedEvent; import org.apache.shardingsphere.mode.event.DataChangedEvent.Type; -import org.apache.shardingsphere.mode.metadata.manager.RuleItemManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -39,12 +38,9 @@ class DatabaseMetaDataChangedListenerTest { @Mock private EventBusContext eventBusContext; - @Mock - private RuleItemManager ruleItemManager; - @BeforeEach void setUp() { - listener = new DatabaseMetaDataChangedListener(eventBusContext, ruleItemManager); + listener = new DatabaseMetaDataChangedListener(eventBusContext); } @Test diff --git a/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriberTest.java b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriberTest.java new file mode 100644 index 0000000000000..5f04a35b00a69 --- /dev/null +++ b/mode/type/cluster/core/src/test/java/org/apache/shardingsphere/mode/manager/cluster/event/dispatch/subscriber/type/RuleItemChangedSubscriberTest.java @@ -0,0 +1,66 @@ +/* + * 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.mode.manager.cluster.event.dispatch.subscriber.type; + +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.alter.AlterRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropNamedRuleItemEvent; +import org.apache.shardingsphere.mode.event.dispatch.rule.drop.DropRuleItemEvent; +import org.apache.shardingsphere.mode.manager.ContextManager; +import org.apache.shardingsphere.mode.spi.item.AlterRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropRuleItem; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.sql.SQLException; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class RuleItemChangedSubscriberTest { + + private RuleItemChangedSubscriber subscriber; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private ContextManager contextManager; + + @BeforeEach + void setUp() { + subscriber = new RuleItemChangedSubscriber(contextManager); + } + + @Test + void assertRenewWithAlterRuleItemEvent() throws SQLException { + AlterRuleItemEvent event = mock(AlterNamedRuleItemEvent.class); + subscriber.renew(event); + verify(contextManager.getMetaDataContextManager().getRuleItemManager()).alterRuleItem(any(AlterRuleItem.class)); + } + + @Test + void assertRenewWithDropRuleItemEvent() throws SQLException { + DropRuleItemEvent event = mock(DropNamedRuleItemEvent.class); + subscriber.renew(event); + verify(contextManager.getMetaDataContextManager().getRuleItemManager()).dropRuleItem(any(DropRuleItem.class)); + } +} diff --git a/mode/type/standalone/core/src/main/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistService.java b/mode/type/standalone/core/src/main/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistService.java index 59e61d04f2ef1..7d067d5e4ce60 100644 --- a/mode/type/standalone/core/src/main/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistService.java +++ b/mode/type/standalone/core/src/main/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistService.java @@ -38,10 +38,14 @@ import org.apache.shardingsphere.mode.metadata.MetaDataContextManager; import org.apache.shardingsphere.mode.metadata.MetaDataContexts; import org.apache.shardingsphere.mode.metadata.MetaDataContextsFactory; +import org.apache.shardingsphere.mode.metadata.manager.RuleItemChangedBuilder; import org.apache.shardingsphere.mode.metadata.manager.SwitchingResource; import org.apache.shardingsphere.mode.metadata.refresher.util.TableRefreshUtils; import org.apache.shardingsphere.mode.persist.service.MetaDataManagerPersistService; +import org.apache.shardingsphere.mode.spi.item.AlterRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropRuleItem; import org.apache.shardingsphere.mode.spi.PersistRepository; +import org.apache.shardingsphere.mode.spi.item.RuleItemChanged; import org.apache.shardingsphere.single.config.SingleRuleConfiguration; import java.sql.SQLException; @@ -63,9 +67,12 @@ public final class StandaloneMetaDataManagerPersistService implements MetaDataMa private final MetaDataContextManager metaDataContextManager; + private final RuleItemChangedBuilder ruleItemChangedBuilder; + public StandaloneMetaDataManagerPersistService(final PersistRepository repository, final MetaDataContextManager metaDataContextManager) { metaDataPersistService = new MetaDataPersistService(repository); this.metaDataContextManager = metaDataContextManager; + ruleItemChangedBuilder = new RuleItemChangedBuilder(); } @Override @@ -285,11 +292,19 @@ public void alterRuleConfiguration(final String databaseName, final RuleConfigur .persist(metaDataContextManager.getMetaDataContexts().get().getMetaData().getDatabase(databaseName).getName(), Collections.singleton(toBeAlteredRuleConfig)); metaDataPersistService.getMetaDataVersionPersistService().switchActiveVersion(metaDataVersions); for (MetaDataVersion each : metaDataVersions) { - metaDataContextManager.getRuleItemManager().alterRuleItem(databaseName, each.getActiveVersionNodePath(), each.getNextActiveVersion(), Type.UPDATED); + // TODO double check here, when ruleItemEvent not existed or not AlterRuleItemEvent @haoran + Optional ruleItemChanged = buildAlterRuleItemChanged(databaseName, each, Type.UPDATED); + if (ruleItemChanged.isPresent() && ruleItemChanged.get() instanceof AlterRuleItem) { + metaDataContextManager.getRuleItemManager().alterRuleItem((AlterRuleItem) ruleItemChanged.get()); + } } clearServiceCache(); } + private Optional buildAlterRuleItemChanged(final String databaseName, final MetaDataVersion metaDataVersion, final Type type) { + return ruleItemChangedBuilder.build(databaseName, metaDataVersion.getActiveVersionNodePath(), metaDataVersion.getNextActiveVersion(), type); + } + @Override public void removeRuleConfigurationItem(final String databaseName, final RuleConfiguration toBeRemovedRuleConfig) throws SQLException { if (null == toBeRemovedRuleConfig) { @@ -297,7 +312,11 @@ public void removeRuleConfigurationItem(final String databaseName, final RuleCon } Collection metaDataVersions = metaDataPersistService.getDatabaseRulePersistService().delete(databaseName, Collections.singleton(toBeRemovedRuleConfig)); for (MetaDataVersion metaDataVersion : metaDataVersions) { - metaDataContextManager.getRuleItemManager().alterRuleItem(databaseName, metaDataVersion.getActiveVersionNodePath(), metaDataVersion.getNextActiveVersion(), Type.DELETED); + Optional ruleItemChanged = buildAlterRuleItemChanged(databaseName, metaDataVersion, Type.DELETED); + // TODO double check here, when ruleItemEvent not existed or not AlterRuleItemEvent @haoran + if (ruleItemChanged.isPresent() && ruleItemChanged.get() instanceof DropRuleItem) { + metaDataContextManager.getRuleItemManager().dropRuleItem((DropRuleItem) ruleItemChanged.get()); + } } clearServiceCache(); } diff --git a/mode/type/standalone/core/src/test/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistServiceTest.java b/mode/type/standalone/core/src/test/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistServiceTest.java index 2469b29646b9e..d86ffedcd0dc6 100644 --- a/mode/type/standalone/core/src/test/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistServiceTest.java +++ b/mode/type/standalone/core/src/test/java/org/apache/shardingsphere/mode/manager/standalone/persist/service/StandaloneMetaDataManagerPersistServiceTest.java @@ -31,7 +31,10 @@ import org.apache.shardingsphere.metadata.persist.MetaDataPersistService; import org.apache.shardingsphere.metadata.persist.service.metadata.DatabaseMetaDataPersistFacade; import org.apache.shardingsphere.mode.metadata.MetaDataContextManager; +import org.apache.shardingsphere.mode.metadata.manager.RuleItemChangedBuilder; import org.apache.shardingsphere.mode.spi.PersistRepository; +import org.apache.shardingsphere.mode.spi.item.AlterRuleItem; +import org.apache.shardingsphere.mode.spi.item.DropRuleItem; import org.apache.shardingsphere.single.config.SingleRuleConfiguration; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -46,6 +49,7 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedList; +import java.util.Optional; import java.util.Properties; import static org.mockito.ArgumentMatchers.any; @@ -168,9 +172,13 @@ void assertAlterRuleConfiguration() throws SQLException { RuleConfiguration ruleConfig = mock(RuleConfiguration.class, RETURNS_DEEP_STUBS); Collection metaDataVersion = Collections.singleton(mock(MetaDataVersion.class)); when(metaDataPersistService.getDatabaseRulePersistService().persist("foo_db", Collections.singleton(ruleConfig))).thenReturn(metaDataVersion); + AlterRuleItem alterRuleItem = mock(AlterRuleItem.class); + RuleItemChangedBuilder ruleItemChangedBuilder = mock(RuleItemChangedBuilder.class); + when(ruleItemChangedBuilder.build(eq("foo_db"), any(), any(), any())).thenReturn(Optional.of(alterRuleItem)); + setRuleConfigurationEventBuilder(ruleItemChangedBuilder); metaDataManagerPersistService.alterRuleConfiguration("foo_db", ruleConfig); verify(metaDataPersistService.getMetaDataVersionPersistService()).switchActiveVersion(metaDataVersion); - verify(metaDataContextManager.getRuleItemManager()).alterRuleItem(eq("foo_db"), any(), any(), any()); + verify(metaDataContextManager.getRuleItemManager()).alterRuleItem(any(AlterRuleItem.class)); } @Test @@ -184,8 +192,12 @@ void assertRemoveRuleConfigurationItem() throws SQLException { RuleConfiguration ruleConfig = mock(RuleConfiguration.class, RETURNS_DEEP_STUBS); Collection metaDataVersion = Collections.singleton(mock(MetaDataVersion.class)); when(metaDataPersistService.getDatabaseRulePersistService().delete("foo_db", Collections.singleton(ruleConfig))).thenReturn(metaDataVersion); + RuleItemChangedBuilder ruleItemChangedBuilder = mock(RuleItemChangedBuilder.class); + DropRuleItem dropRuleItem = mock(DropRuleItem.class); + when(ruleItemChangedBuilder.build(eq("foo_db"), any(), any(), any())).thenReturn(Optional.of(dropRuleItem)); + setRuleConfigurationEventBuilder(ruleItemChangedBuilder); metaDataManagerPersistService.removeRuleConfigurationItem("foo_db", ruleConfig); - verify(metaDataContextManager.getRuleItemManager()).alterRuleItem(eq("foo_db"), any(), any(), any()); + verify(metaDataContextManager.getRuleItemManager()).dropRuleItem(any(DropRuleItem.class)); } @Test @@ -222,4 +234,9 @@ void assertDropTables() { metaDataManagerPersistService.dropTables("foo_db", "foo_schema", Collections.singleton("foo_tbl")); verify(metaDataPersistService.getDatabaseMetaDataFacade().getTable()).drop("foo_db", "foo_schema", "foo_tbl"); } + + @SneakyThrows(ReflectiveOperationException.class) + private void setRuleConfigurationEventBuilder(final RuleItemChangedBuilder ruleItemChangedBuilder) { + Plugins.getMemberAccessor().set(StandaloneMetaDataManagerPersistService.class.getDeclaredField("ruleItemChangedBuilder"), metaDataManagerPersistService, ruleItemChangedBuilder); + } }