From 652d8355399e2036bb4a0bb401b824d5ee66511c Mon Sep 17 00:00:00 2001 From: Tim Farber-Newman Date: Thu, 9 Jan 2025 12:03:47 -0600 Subject: [PATCH] Swap to creating a new listener and directly dispatching the ISS notification to it in DefaultAppNotifier Signed-off-by: Tim Farber-Newman --- .../main/java/com/hedera/node/app/Hedera.java | 6 +- .../node/app/HederaInjectionComponent.java | 4 +- .../node/app/platform/PlatformModule.java | 6 +- ...istener.java => FatalIssListenerImpl.java} | 8 +- .../builder/PlatformComponentBuilder.java | 3 +- .../components/DefaultAppNotifier.java | 9 +- .../state/iss/internal/DefaultIssHandler.java | 10 +- ...IssListener.java => FatalIssListener.java} | 5 +- .../components/DefaultAppNotifierTest.java | 155 ++++++++++++++++++ .../platform/test/state/IssHandlerTests.java | 54 ++---- 10 files changed, 196 insertions(+), 64 deletions(-) rename hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/{IssDetectedListener.java => FatalIssListenerImpl.java} (81%) rename platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/{AsyncIssListener.java => FatalIssListener.java} (76%) create mode 100644 platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/components/DefaultAppNotifierTest.java diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java index 9c54a35f83d8..823f6278b7ca 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/Hedera.java @@ -146,7 +146,7 @@ import com.swirlds.platform.system.SwirldMain; import com.swirlds.platform.system.address.AddressBook; import com.swirlds.platform.system.events.Event; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; +import com.swirlds.platform.system.state.notifications.FatalIssListener; import com.swirlds.platform.system.state.notifications.StateHashedListener; import com.swirlds.platform.system.status.PlatformStatus; import com.swirlds.platform.system.transaction.Transaction; @@ -1004,7 +1004,7 @@ private void initializeDagger(@NonNull final State state, @NonNull final InitTri notifications.unregister(PlatformStatusChangeListener.class, this); notifications.unregister(ReconnectCompleteListener.class, daggerApp.reconnectListener()); notifications.unregister(StateWriteToDiskCompleteListener.class, daggerApp.stateWriteToDiskListener()); - notifications.unregister(AsyncIssListener.class, daggerApp.asyncIssListener()); + notifications.unregister(FatalIssListener.class, daggerApp.fatalIssListener()); if (blockStreamEnabled) { notifications.unregister(StateHashedListener.class, daggerApp.blockStreamManager()); } @@ -1058,7 +1058,7 @@ private void initializeDagger(@NonNull final State state, @NonNull final InitTri notifications.register(PlatformStatusChangeListener.class, this); notifications.register(ReconnectCompleteListener.class, daggerApp.reconnectListener()); notifications.register(StateWriteToDiskCompleteListener.class, daggerApp.stateWriteToDiskListener()); - notifications.register(AsyncIssListener.class, daggerApp.asyncIssListener()); + notifications.register(FatalIssListener.class, daggerApp.fatalIssListener()); if (blockStreamEnabled) { notifications.register(StateHashedListener.class, daggerApp.blockStreamManager()); daggerApp diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/HederaInjectionComponent.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/HederaInjectionComponent.java index 8ea5bc9d9074..9cc4b3b455a1 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/HederaInjectionComponent.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/HederaInjectionComponent.java @@ -66,7 +66,7 @@ import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener; import com.swirlds.platform.system.InitTrigger; import com.swirlds.platform.system.Platform; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; +import com.swirlds.platform.system.state.notifications.FatalIssListener; import com.swirlds.state.State; import com.swirlds.state.lifecycle.StartupNetworks; import com.swirlds.state.lifecycle.info.NetworkInfo; @@ -147,7 +147,7 @@ public interface HederaInjectionComponent { SubmissionManager submissionManager(); - AsyncIssListener asyncIssListener(); + FatalIssListener fatalIssListener(); @Component.Builder interface Builder { diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/platform/PlatformModule.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/platform/PlatformModule.java index de852035938c..50fa2e7fb1d3 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/platform/PlatformModule.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/platform/PlatformModule.java @@ -17,14 +17,14 @@ package com.hedera.node.app.platform; import com.hedera.node.app.annotations.CommonExecutor; -import com.hedera.node.app.state.listeners.IssDetectedListener; +import com.hedera.node.app.state.listeners.FatalIssListenerImpl; import com.hedera.node.app.state.listeners.ReconnectListener; import com.hedera.node.app.state.listeners.WriteStateToDiskListener; import com.swirlds.common.stream.Signer; import com.swirlds.platform.listeners.ReconnectCompleteListener; import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener; import com.swirlds.platform.system.Platform; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; +import com.swirlds.platform.system.state.notifications.FatalIssListener; import dagger.Binds; import dagger.Module; import dagger.Provides; @@ -73,5 +73,5 @@ static IntSupplier provideFrontendThrottleSplit(@NonNull final Platform platform @Binds @Singleton - AsyncIssListener bindAsyncIssListener(IssDetectedListener listener); + FatalIssListener bindFatalIssListener(FatalIssListenerImpl listener); } diff --git a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/IssDetectedListener.java b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/FatalIssListenerImpl.java similarity index 81% rename from hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/IssDetectedListener.java rename to hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/FatalIssListenerImpl.java index fd7a2bdb3c09..47b62ecfe631 100644 --- a/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/IssDetectedListener.java +++ b/hedera-node/hedera-app/src/main/java/com/hedera/node/app/state/listeners/FatalIssListenerImpl.java @@ -16,7 +16,7 @@ package com.hedera.node.app.state.listeners; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; +import com.swirlds.platform.system.state.notifications.FatalIssListener; import com.swirlds.platform.system.state.notifications.IssNotification; import javax.inject.Inject; import javax.inject.Singleton; @@ -24,12 +24,12 @@ import org.apache.logging.log4j.Logger; @Singleton -public class IssDetectedListener implements AsyncIssListener { +public class FatalIssListenerImpl implements FatalIssListener { - private static final Logger log = LogManager.getLogger(IssDetectedListener.class); + private static final Logger log = LogManager.getLogger(FatalIssListenerImpl.class); @Inject - public IssDetectedListener() { + public FatalIssListenerImpl() { // no-op } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java index 3ca42a79b23a..2647672872eb 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformComponentBuilder.java @@ -932,8 +932,7 @@ public IssHandler buildIssHandler() { // halt without needing to be stopped here. This should eventually be cleaned up. }, SystemExitUtils::handleFatalError, - blocks.issScratchpad(), - blocks.notificationEngine()); + blocks.issScratchpad()); } return issHandler; } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/DefaultAppNotifier.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/DefaultAppNotifier.java index 7665e5f88591..9fdcbf5985fe 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/DefaultAppNotifier.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/components/DefaultAppNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Hedera Hashgraph, LLC + * Copyright (C) 2024-2025 Hedera Hashgraph, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,10 @@ import com.swirlds.platform.listeners.ReconnectCompleteNotification; import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener; import com.swirlds.platform.listeners.StateWriteToDiskCompleteNotification; +import com.swirlds.platform.system.state.notifications.FatalIssListener; import com.swirlds.platform.system.state.notifications.IssListener; import com.swirlds.platform.system.state.notifications.IssNotification; +import com.swirlds.platform.system.state.notifications.IssNotification.IssType; import com.swirlds.platform.system.state.notifications.NewSignedStateListener; import com.swirlds.platform.system.state.notifications.StateHashedListener; import com.swirlds.platform.system.state.notifications.StateHashedNotification; @@ -84,5 +86,10 @@ public void sendLatestCompleteStateNotification( @Override public void sendIssNotification(@NonNull final IssNotification notification) { notificationEngine.dispatch(IssListener.class, notification); + + if (IssType.CATASTROPHIC_ISS == notification.getIssType() || IssType.SELF_ISS == notification.getIssType()) { + // Forward notification to application + notificationEngine.dispatch(FatalIssListener.class, notification); + } } } diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/internal/DefaultIssHandler.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/internal/DefaultIssHandler.java index e19e909dd853..ae0bc6a82ed8 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/internal/DefaultIssHandler.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/state/iss/internal/DefaultIssHandler.java @@ -18,14 +18,12 @@ import com.swirlds.common.context.PlatformContext; import com.swirlds.common.merkle.utility.SerializableLong; -import com.swirlds.common.notification.NotificationEngine; import com.swirlds.platform.components.common.output.FatalErrorConsumer; import com.swirlds.platform.config.StateConfig; import com.swirlds.platform.scratchpad.Scratchpad; import com.swirlds.platform.state.iss.IssHandler; import com.swirlds.platform.state.iss.IssScratchpad; import com.swirlds.platform.system.SystemExitCode; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; import com.swirlds.platform.system.state.notifications.IssNotification; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Objects; @@ -39,7 +37,6 @@ public class DefaultIssHandler implements IssHandler { private final Consumer haltRequestedConsumer; private final FatalErrorConsumer fatalErrorConsumer; private final Scratchpad issScratchpad; - private final NotificationEngine notificationEngine; private boolean halted; @@ -55,13 +52,11 @@ public DefaultIssHandler( @NonNull final PlatformContext platformContext, @NonNull final Consumer haltRequestedConsumer, @NonNull final FatalErrorConsumer fatalErrorConsumer, - @NonNull final Scratchpad issScratchpad, - @NonNull final NotificationEngine notificationEngine) { + @NonNull final Scratchpad issScratchpad) { this.haltRequestedConsumer = Objects.requireNonNull(haltRequestedConsumer); this.fatalErrorConsumer = Objects.requireNonNull(fatalErrorConsumer); this.stateConfig = platformContext.getConfiguration().getConfigData(StateConfig.class); this.issScratchpad = Objects.requireNonNull(issScratchpad); - this.notificationEngine = Objects.requireNonNull(notificationEngine); } /** @@ -123,9 +118,6 @@ private void selfIssObserved(@NonNull final IssNotification notification) { return; } - // For self-ISS events, forward the notification asynchronously to the app - notificationEngine.dispatch(AsyncIssListener.class, notification); - updateIssRoundInScratchpad(notification.getRound()); if (stateConfig.haltOnAnyIss()) { diff --git a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/AsyncIssListener.java b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/FatalIssListener.java similarity index 76% rename from platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/AsyncIssListener.java rename to platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/FatalIssListener.java index 63ec71339482..c82809cafb06 100644 --- a/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/AsyncIssListener.java +++ b/platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/system/state/notifications/FatalIssListener.java @@ -22,7 +22,8 @@ import com.swirlds.common.notification.Listener; /** - * Async listener for ISS events. If you require ordered, synchronous dispatch use {@link IssListener}. + * Listener for fatal ISS events (i.e. of type SELF or CATASTROPHIC). This listener is unordered and asynchronous. + * If you require ordered and synchronous dispatch that includes all ISS events, then use {@link IssListener}. */ @DispatchModel(mode = DispatchMode.ASYNC, order = DispatchOrder.UNORDERED) -public interface AsyncIssListener extends Listener {} +public interface FatalIssListener extends Listener {} diff --git a/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/components/DefaultAppNotifierTest.java b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/components/DefaultAppNotifierTest.java new file mode 100644 index 000000000000..5c2fc1267309 --- /dev/null +++ b/platform-sdk/swirlds-platform-core/src/test/java/com/swirlds/platform/components/DefaultAppNotifierTest.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2025 Hedera Hashgraph, LLC + * + * Licensed 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 com.swirlds.platform.components; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import com.swirlds.common.crypto.DigestType; +import com.swirlds.common.crypto.Hash; +import com.swirlds.common.notification.NotificationEngine; +import com.swirlds.common.notification.NotificationResult; +import com.swirlds.common.threading.futures.StandardFuture.CompletionCallback; +import com.swirlds.platform.components.appcomm.CompleteStateNotificationWithCleanup; +import com.swirlds.platform.listeners.PlatformStatusChangeListener; +import com.swirlds.platform.listeners.PlatformStatusChangeNotification; +import com.swirlds.platform.listeners.ReconnectCompleteListener; +import com.swirlds.platform.listeners.ReconnectCompleteNotification; +import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener; +import com.swirlds.platform.listeners.StateWriteToDiskCompleteNotification; +import com.swirlds.platform.system.SwirldState; +import com.swirlds.platform.system.state.notifications.FatalIssListener; +import com.swirlds.platform.system.state.notifications.IssListener; +import com.swirlds.platform.system.state.notifications.IssNotification; +import com.swirlds.platform.system.state.notifications.IssNotification.IssType; +import com.swirlds.platform.system.state.notifications.NewSignedStateListener; +import com.swirlds.platform.system.state.notifications.NewSignedStateNotification; +import com.swirlds.platform.system.state.notifications.StateHashedListener; +import com.swirlds.platform.system.state.notifications.StateHashedNotification; +import com.swirlds.platform.system.status.PlatformStatus; +import java.time.Instant; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; + +public class DefaultAppNotifierTest { + + NotificationEngine notificationEngine; + AppNotifier notifier; + + @BeforeEach + void beforeEach() { + notificationEngine = mock(NotificationEngine.class); + notifier = new DefaultAppNotifier(notificationEngine); + } + + @Test + void testStateWrittenToDiskNotificationSent() { + final StateWriteToDiskCompleteNotification notification = + new StateWriteToDiskCompleteNotification(100, Instant.now(), false); + + assertDoesNotThrow(() -> notifier.sendStateWrittenToDiskNotification(notification)); + verify(notificationEngine, times(1)).dispatch(StateWriteToDiskCompleteListener.class, notification); + verifyNoMoreInteractions(notificationEngine); + } + + @Test + void testStateHashNotificationSent() { + final StateHashedNotification notification = new StateHashedNotification(100L, new Hash(DigestType.SHA_384)); + + assertDoesNotThrow(() -> notifier.sendStateHashedNotification(notification)); + verify(notificationEngine, times(1)).dispatch(StateHashedListener.class, notification); + verifyNoMoreInteractions(notificationEngine); + } + + @Test + void testReconnectCompleteNotificationSent() { + final SwirldState state = mock(SwirldState.class); + final ReconnectCompleteNotification notification = + new ReconnectCompleteNotification(100L, Instant.now(), state); + + assertDoesNotThrow(() -> notifier.sendReconnectCompleteNotification(notification)); + verify(notificationEngine, times(1)).dispatch(ReconnectCompleteListener.class, notification); + verifyNoMoreInteractions(notificationEngine); + } + + @Test + void testPlatformStatusChangeNotificationSent() { + final PlatformStatus status = PlatformStatus.ACTIVE; + final ArgumentCaptor captor = + ArgumentCaptor.forClass(PlatformStatusChangeNotification.class); + + assertDoesNotThrow(() -> notifier.sendPlatformStatusChangeNotification(status)); + verify(notificationEngine, times(1)).dispatch(eq(PlatformStatusChangeListener.class), captor.capture()); + verifyNoMoreInteractions(notificationEngine); + + final PlatformStatusChangeNotification notification = captor.getValue(); + assertNotNull(notification); + assertEquals(status, notification.getNewStatus()); + } + + @Test + void testLatestCompleteStateNotificationSent() { + final SwirldState state = mock(SwirldState.class); + final CompletionCallback> cleanup = + mock(CompletionCallback.class); + final NewSignedStateNotification signedStateNotification = + new NewSignedStateNotification(state, 100L, Instant.now()); + final CompleteStateNotificationWithCleanup notificationWithCleanup = + new CompleteStateNotificationWithCleanup(signedStateNotification, cleanup); + + assertDoesNotThrow(() -> notifier.sendLatestCompleteStateNotification(notificationWithCleanup)); + verify(notificationEngine, times(1)).dispatch(NewSignedStateListener.class, signedStateNotification, cleanup); + verifyNoMoreInteractions(notificationEngine); + } + + public static List issTypes() { + return List.of( + Arguments.of(IssType.CATASTROPHIC_ISS, true), + Arguments.of(IssType.SELF_ISS, true), + Arguments.of(IssType.OTHER_ISS, false)); + } + + @ParameterizedTest + @MethodSource("issTypes") + void testIssNotificationSent(final IssType type, final boolean isFatal) { + final IssNotification notification = new IssNotification(100L, type); + + assertDoesNotThrow(() -> notifier.sendIssNotification(notification)); + + // verify the ISS notification is always sent to the IssListener + verify(notificationEngine, times(1)).dispatch(IssListener.class, notification); + + if (isFatal) { + // if the ISS event is considered fatal to the local node, verify the event is also sent to the + // FatalIssListener + verify(notificationEngine, times(1)).dispatch(FatalIssListener.class, notification); + } + + verifyNoMoreInteractions(notificationEngine); + } +} diff --git a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java index ae2c0512aa96..fd2755bfe8a5 100644 --- a/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java +++ b/platform-sdk/swirlds-unit-tests/core/swirlds-platform-test/src/test/java/com/swirlds/platform/test/state/IssHandlerTests.java @@ -19,14 +19,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import com.swirlds.common.context.PlatformContext; import com.swirlds.common.merkle.utility.SerializableLong; -import com.swirlds.common.notification.NotificationEngine; import com.swirlds.common.test.fixtures.platform.TestPlatformContextBuilder; import com.swirlds.config.api.Configuration; import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder; @@ -36,26 +31,17 @@ import com.swirlds.platform.state.iss.IssHandler; import com.swirlds.platform.state.iss.IssScratchpad; import com.swirlds.platform.state.iss.internal.DefaultIssHandler; -import com.swirlds.platform.system.state.notifications.AsyncIssListener; import com.swirlds.platform.system.state.notifications.IssNotification; import com.swirlds.platform.system.state.notifications.IssNotification.IssType; import com.swirlds.platform.test.fixtures.SimpleScratchpad; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("IssHandler Tests") class IssHandlerTests { - NotificationEngine notificationEngine; - - @BeforeEach - void beforeEach() { - notificationEngine = mock(NotificationEngine.class); - } - @Test @DisplayName("Other ISS Always Freeze") void otherIssAlwaysFreeze() { @@ -75,8 +61,8 @@ void otherIssAlwaysFreeze() { final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); handler.issObserved(new IssNotification(1234L, IssType.OTHER_ISS)); @@ -91,7 +77,6 @@ void otherIssAlwaysFreeze() { // Another node ISSed, we will not record that on the scratchpad. assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); - verifyNoInteractions(notificationEngine); } @Test @@ -112,8 +97,8 @@ void otherIssNoAction() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); handler.issObserved(new IssNotification(1234L, IssType.OTHER_ISS)); @@ -121,7 +106,6 @@ void otherIssNoAction() { assertEquals(0, shutdownCount.get(), "unexpected shutdown count"); assertNull(simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND)); - verifyNoInteractions(notificationEngine); } @Test @@ -143,8 +127,8 @@ void selfIssAutomatedRecovery() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); final IssNotification notification = new IssNotification(1234L, IssType.SELF_ISS); handler.issObserved(notification); @@ -155,7 +139,6 @@ void selfIssAutomatedRecovery() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verify(notificationEngine, times(1)).dispatch(AsyncIssListener.class, notification); } @Test @@ -177,8 +160,8 @@ void selfIssNoAction() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); final IssNotification notification = new IssNotification(1234L, IssType.SELF_ISS); handler.issObserved(notification); @@ -189,7 +172,6 @@ void selfIssNoAction() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verify(notificationEngine, times(1)).dispatch(AsyncIssListener.class, notification); } @Test @@ -211,8 +193,8 @@ void selfIssAlwaysFreeze() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); final IssNotification notification = new IssNotification(1234L, IssType.SELF_ISS); handler.issObserved(notification); @@ -229,7 +211,6 @@ void selfIssAlwaysFreeze() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verify(notificationEngine, times(1)).dispatch(AsyncIssListener.class, notification); } @Test @@ -251,8 +232,8 @@ void catastrophicIssNoAction() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); handler.issObserved(new IssNotification(1234L, IssType.CATASTROPHIC_ISS)); @@ -262,7 +243,6 @@ void catastrophicIssNoAction() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verifyNoInteractions(notificationEngine); } @Test @@ -284,8 +264,8 @@ void catastrophicIssAlwaysFreeze() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); handler.issObserved(new IssNotification(1234L, IssType.CATASTROPHIC_ISS)); @@ -301,7 +281,6 @@ void catastrophicIssAlwaysFreeze() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verifyNoInteractions(notificationEngine); } @Test @@ -323,8 +302,8 @@ void catastrophicIssFreezeOnCatastrophic() { final FatalErrorConsumer fatalErrorConsumer = (msg, t, code) -> shutdownCount.getAndIncrement(); final Scratchpad simpleScratchpad = new SimpleScratchpad<>(); - final IssHandler handler = new DefaultIssHandler( - platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad, notificationEngine); + final IssHandler handler = + new DefaultIssHandler(platformContext, haltRequestedConsumer, fatalErrorConsumer, simpleScratchpad); handler.issObserved(new IssNotification(1234L, IssType.CATASTROPHIC_ISS)); @@ -340,6 +319,5 @@ void catastrophicIssFreezeOnCatastrophic() { final SerializableLong issRound = simpleScratchpad.get(IssScratchpad.LAST_ISS_ROUND); assertNotNull(issRound); assertEquals(1234L, issRound.getValue()); - verifyNoInteractions(notificationEngine); } }