This is an automated email from the ASF dual-hosted git repository.
rpuch pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new c02f925e799 IGNITE-28235 Only log cause of broken watch notification
chain once (#7787)
c02f925e799 is described below
commit c02f925e7991746af8479492adf71f8459ee0ff2
Author: Roman Puchkovskiy <[email protected]>
AuthorDate: Mon Mar 16 14:32:16 2026 +0400
IGNITE-28235 Only log cause of broken watch notification chain once (#7787)
---
.../testframework/log4j2/LogInspector.java | 8 +-
.../metastorage/impl/ItBrokenWatchLoggingTest.java | 91 ++++++++++++++++++++++
.../metastorage/server/UpdateEntriesEvent.java | 12 +--
3 files changed, 99 insertions(+), 12 deletions(-)
diff --git
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/log4j2/LogInspector.java
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/log4j2/LogInspector.java
index ae31fcf69fb..5359a17b7ac 100755
---
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/log4j2/LogInspector.java
+++
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/log4j2/LogInspector.java
@@ -87,6 +87,12 @@ import org.apache.logging.log4j.core.config.Property;
* </p>
*/
public class LogInspector {
+ // TODO: https://issues.apache.org/jira/browse/IGNITE-28236 - instead of a
magic constant, pass null or use specific static factories.
+ /**
+ * Magic 'logger name' that makes the inspector catch events from all
loggers when passed as a logger name.
+ */
+ public static final String ALL_LOGGERS = "all-loggers";
+
/** Logger name. */
private final String loggerName;
@@ -391,7 +397,7 @@ public class LogInspector {
@Override
public void append(LogEvent event) {
- if (!loggerName.equals(event.getLoggerName())) {
+ if (!ALL_LOGGERS.equals(loggerName) &&
!loggerName.equals(event.getLoggerName())) {
return;
}
diff --git
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItBrokenWatchLoggingTest.java
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItBrokenWatchLoggingTest.java
new file mode 100644
index 00000000000..005dc525730
--- /dev/null
+++
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItBrokenWatchLoggingTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.metastorage.impl;
+
+import static java.util.UUID.randomUUID;
+import static java.util.concurrent.CompletableFuture.failedFuture;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
+import static
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
+import static org.apache.ignite.internal.util.ExceptionUtils.hasCause;
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.internal.ClusterPerTestIntegrationTest;
+import org.apache.ignite.internal.ConfigOverride;
+import org.apache.ignite.internal.lang.ByteArray;
+import org.apache.ignite.internal.metastorage.MetaStorageManager;
+import
org.apache.ignite.internal.testframework.failure.FailureManagerExtension;
+import
org.apache.ignite.internal.testframework.failure.MuteFailureManagerLogging;
+import org.apache.ignite.internal.testframework.log4j2.LogInspector;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(FailureManagerExtension.class)
+@MuteFailureManagerLogging
+@ConfigOverride(name = "ignite.failureHandler.handler.type", value = "noop")
+class ItBrokenWatchLoggingTest extends ClusterPerTestIntegrationTest {
+ @Override
+ protected int initialNodes() {
+ return 1;
+ }
+
+ @Test
+ void brokenWatchChainLogsOriginalExceptionJustOnce() throws Exception {
+ MetaStorageManager metaStorageManager =
unwrapIgniteImpl(cluster.node(0)).metaStorageManager();
+
+ registerWatchBreakingNotifications(metaStorageManager);
+
+ AtomicInteger logCount = new AtomicInteger();
+
+ LogInspector logInspector = new LogInspector(
+ LogInspector.ALL_LOGGERS,
+ evt -> hasCause(evt.getThrown(), BreakingException.class),
+ logCount::incrementAndGet
+ );
+ logInspector.start();
+
+ try {
+ await("Must observe at least one logging event")
+ .until(logCount::get, greaterThan(0));
+
+ //noinspection deprecation
+ assertFalse(
+ waitForCondition(() -> logCount.get() > 1,
SECONDS.toMillis(2)),
+ () -> "Must not observe more than one logging event, but
observed " + logCount.get()
+ );
+ } finally {
+ logInspector.stop();
+ }
+ }
+
+ private static void registerWatchBreakingNotifications(MetaStorageManager
metaStorageManager) {
+ BreakingException exception = new BreakingException("Oops " +
randomUUID());
+ metaStorageManager.registerPrefixWatch(new ByteArray(""), event ->
failedFuture(exception));
+ }
+
+ private static class BreakingException extends RuntimeException {
+ private static final long serialVersionUID = -8004315686224616385L;
+
+ private BreakingException(String message) {
+ super(message);
+ }
+ }
+}
diff --git
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/UpdateEntriesEvent.java
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/UpdateEntriesEvent.java
index 32ad8640299..5418979132b 100644
---
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/UpdateEntriesEvent.java
+++
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/UpdateEntriesEvent.java
@@ -19,16 +19,12 @@ package org.apache.ignite.internal.metastorage.server;
import java.util.List;
import org.apache.ignite.internal.hlc.HybridTimestamp;
-import org.apache.ignite.internal.logger.IgniteLogger;
-import org.apache.ignite.internal.logger.Loggers;
import org.apache.ignite.internal.metastorage.Entry;
import org.apache.ignite.internal.tostring.IgniteToStringInclude;
import org.apache.ignite.internal.tostring.S;
/** Notifier of {@link WatchProcessor} about updating metastorage {@link Entry
entries}. */
public class UpdateEntriesEvent implements NotifyWatchProcessorEvent {
- private static final IgniteLogger LOG =
Loggers.forClass(UpdateEntriesEvent.class);
-
@IgniteToStringInclude
private final List<Entry> updatedEntries;
@@ -50,13 +46,7 @@ public class UpdateEntriesEvent implements
NotifyWatchProcessorEvent {
@Override
public void notify(WatchProcessor watchProcessor) {
- watchProcessor.notifyWatches(updatedEntries.get(0).revision(),
updatedEntries, timestamp)
- .whenComplete((res, err) -> {
- if (err != null) {
- // TODO:
https://issues.apache.org/jira/browse/IGNITE-26731
- LOG.error("Notify watches failed.", err);
- }
- });
+ watchProcessor.notifyWatches(updatedEntries.get(0).revision(),
updatedEntries, timestamp);
}
@Override