This is an automated email from the ASF dual-hosted git repository. sk0x50 pushed a commit to branch ignite-20368 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit a34aa22bfb965e9aa4e4a610da776744add15944 Author: Sergey Uttsel <utt...@gmail.com> AuthorDate: Fri Sep 29 11:43:48 2023 +0300 IGNITE-20447 Introduce Failure handling component (#2629) --- modules/failure-handler/build.gradle | 33 ++++++++++ .../ignite/internal/failure/FailureContext.java | 66 +++++++++++++++++++ .../ignite/internal/failure/FailureHandler.java | 34 ++++++++++ .../ignite/internal/failure/FailureProcessor.java | 75 ++++++++++++++++++++++ .../ignite/internal/failure/FailureType.java | 35 ++++++++++ .../internal/failure/FailureProcessorTest.java | 43 +++++++++++++ settings.gradle | 2 + 7 files changed, 288 insertions(+) diff --git a/modules/failure-handler/build.gradle b/modules/failure-handler/build.gradle new file mode 100644 index 0000000000..b6d8be625a --- /dev/null +++ b/modules/failure-handler/build.gradle @@ -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. + */ + +apply from: "$rootDir/buildscripts/java-core.gradle" +apply from: "$rootDir/buildscripts/publishing.gradle" +apply from: "$rootDir/buildscripts/java-junit5.gradle" +apply from: "$rootDir/buildscripts/java-integration-test.gradle" +apply from: "$rootDir/buildscripts/java-test-fixtures.gradle" + +dependencies { + implementation project(':ignite-core') + + testImplementation libs.mockito.core + testImplementation libs.mockito.junit + + testImplementation(testFixtures(project(':ignite-core'))) +} + +description = 'ignite-failure-handler' diff --git a/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureContext.java b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureContext.java new file mode 100644 index 0000000000..1100a6c216 --- /dev/null +++ b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureContext.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.ignite.internal.failure; + +import org.apache.ignite.internal.tostring.S; + +/** + * Failure context contains information about failure type and exception if applicable. + * This information could be used for appropriate handling of the failure. + */ +public class FailureContext { + /** Type. */ + private final FailureType type; + + /** Error. */ + private final Throwable err; + + /** + * Creates instance of {@link FailureContext}. + * + * @param type Failure type. + * @param err Exception. + */ + public FailureContext(FailureType type, Throwable err) { + this.type = type; + this.err = err; + } + + /** + * Gets the failure type. + * + * @return Failure type. + */ + public FailureType type() { + return type; + } + + /** + * Gets the exception. + * + * @return Exception or {@code null}. + */ + public Throwable error() { + return err; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(FailureContext.class, this); + } +} diff --git a/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureHandler.java b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureHandler.java new file mode 100644 index 0000000000..f56aba3130 --- /dev/null +++ b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureHandler.java @@ -0,0 +1,34 @@ +/* + * 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.ignite.internal.failure; + +/** + * Provides facility to handle failures. + */ +public interface FailureHandler { + /** + * Handles failure occurred on {@code ignite} instance. + * Failure details is contained in {@code failureCtx}. + * Returns {@code true} if Ignite node must be invalidated by {@link FailureProcessor} after calling this method. + * + * @param nodeName Node name. + * @param failureCtx Failure context. + * @return Whether Ignite node must be invalidated or not. + */ + boolean onFailure(String nodeName, FailureContext failureCtx); +} diff --git a/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureProcessor.java b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureProcessor.java new file mode 100644 index 0000000000..16d4a6d9ad --- /dev/null +++ b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureProcessor.java @@ -0,0 +1,75 @@ +/* + * 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.ignite.internal.failure; + +import org.apache.ignite.internal.manager.IgniteComponent; + +/** + * General failure processing API. + */ +public class FailureProcessor implements IgniteComponent { + /** Handler. */ + private final FailureHandler handler; + + /** Node name. */ + private final String nodeName; + + /** + * Creates a new instance of a failure processor. + * + * @param nodeName Node name. + * @param handler Handler. + */ + public FailureProcessor(String nodeName, FailureHandler handler) { + this.nodeName = nodeName; + this.handler = handler; + } + + /** {@inheritDoc} */ + @Override + public void start() { + + } + + /** {@inheritDoc} */ + @Override + public void stop() { + + } + + /** + * Processes failure accordingly to configured {@link FailureHandler}. + * + * @param failureCtx Failure context. + * @return {@code True} If this very call led to Ignite node invalidation. + */ + public boolean process(FailureContext failureCtx) { + return process(failureCtx, handler); + } + + /** + * Processes failure accordingly to given failure handler. + * + * @param failureCtx Failure context. + * @param handler Failure handler. + * @return {@code True} If this very call led to Ignite node invalidation. + */ + private boolean process(FailureContext failureCtx, FailureHandler handler) { + return handler.onFailure(nodeName, failureCtx); + } +} diff --git a/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureType.java b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureType.java new file mode 100644 index 0000000000..0ef9a689ad --- /dev/null +++ b/modules/failure-handler/src/main/java/org/apache/ignite/internal/failure/FailureType.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.ignite.internal.failure; + +/** + * Types of failures. + */ +public enum FailureType { + /** System worker termination. */ + SYSTEM_WORKER_TERMINATION, + + /** System worker has not updated its heartbeat for a long time. */ + SYSTEM_WORKER_BLOCKED, + + /** Critical error - error which leads to the system's inoperability. */ + CRITICAL_ERROR, + + /** System-critical operation has been timed out. */ + SYSTEM_CRITICAL_OPERATION_TIMEOUT +} diff --git a/modules/failure-handler/src/test/java/org/apache/ignite/internal/failure/FailureProcessorTest.java b/modules/failure-handler/src/test/java/org/apache/ignite/internal/failure/FailureProcessorTest.java new file mode 100644 index 0000000000..83ae8d971b --- /dev/null +++ b/modules/failure-handler/src/test/java/org/apache/ignite/internal/failure/FailureProcessorTest.java @@ -0,0 +1,43 @@ +/* + * 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.ignite.internal.failure; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link FailureProcessor}. + */ +class FailureProcessorTest extends BaseIgniteAbstractTest { + @Test + void testFailureProcessing() { + FailureHandler handler = mock(FailureHandler.class); + + FailureProcessor failureProcessor = new FailureProcessor("node_name", handler); + + failureProcessor.process(new FailureContext(FailureType.CRITICAL_ERROR, null)); + + verify(handler, times(1)).onFailure(anyString(), any()); + } +} diff --git a/settings.gradle b/settings.gradle index f1ddc8e07a..3f75076229 100644 --- a/settings.gradle +++ b/settings.gradle @@ -78,6 +78,7 @@ include(":ignite-file-transfer") include(":ignite-system-view") include(":ignite-system-view-api") include(":ignite-error-code-annotation-processor") +include(':ignite-failure-handler') project(":ignite-examples").projectDir = file('examples') project(":ignite-dev-utilities").projectDir = file('dev-utilities') @@ -141,6 +142,7 @@ project(":ignite-file-transfer").projectDir = file('modules/file-transfer') project(":ignite-system-view").projectDir = file('modules/system-view') project(":ignite-system-view-api").projectDir = file('modules/system-view-api') project(":ignite-error-code-annotation-processor").projectDir = file('modules/error-code-annotation-processor') +project(":ignite-failure-handler").projectDir = file('modules/failure-handler') ext.isCiServer = System.getenv().containsKey("IGNITE_CI")