diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java index c9288c54cd..b68dda0f3b 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/Rediscovery.java @@ -25,8 +25,21 @@ import org.neo4j.driver.internal.BoltServerAddress; import org.neo4j.driver.internal.spi.ConnectionPool; +/** + * Provides cluster composition lookup capabilities and initial router address resolution. + */ public interface Rediscovery { + /** + * Fetches cluster composition using the provided routing table. + *

+ * Implementation must be thread safe to be called with distinct routing tables concurrently. The routing table instance may be modified. + * + * @param routingTable the routing table for cluster composition lookup + * @param connectionPool the connection pool for connection acquisition + * @param bookmark the bookmark that is presented to the server + * @return cluster composition lookup result + */ CompletionStage lookupClusterComposition( RoutingTable routingTable, ConnectionPool connectionPool, Bookmark bookmark ); List resolve(); diff --git a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java index 4c95288389..bebc04741d 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java +++ b/driver/src/main/java/org/neo4j/driver/internal/cluster/RediscoveryImpl.java @@ -49,14 +49,13 @@ import static org.neo4j.driver.internal.util.Futures.completedWithNull; import static org.neo4j.driver.internal.util.Futures.failedFuture; -/** - * This class is used by all router tables to perform discovery. - * In other words, the methods in this class could be called by multiple threads concurrently. - */ public class RediscoveryImpl implements Rediscovery { private static final String NO_ROUTERS_AVAILABLE = "Could not perform discovery for database '%s'. No routing server available."; private static final String RECOVERABLE_ROUTING_ERROR = "Failed to update routing table with server '%s'."; + private static final String RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER = "Received a recoverable discovery error with server '%s', " + + "will continue discovery with other routing servers if available. " + + "Complete routing failures will be reported separately from this warning."; private final BoltServerAddress initialRouter; private final RoutingSettings settings; @@ -258,8 +257,9 @@ private ClusterComposition handleRoutingProcedureError( Throwable error, Routing // Retriable error happened during discovery. DiscoveryException discoveryError = new DiscoveryException( format( RECOVERABLE_ROUTING_ERROR, routerAddress ), error ); Futures.combineErrors( baseError, discoveryError ); // we record each failure here - logger.warn( format( "Received a recoverable discovery error with server '%s', will continue discovery with other routing servers if available.", - routerAddress ), discoveryError ); + String warningMessage = format( RECOVERABLE_DISCOVERY_ERROR_WITH_SERVER, routerAddress ); + logger.warn( warningMessage ); + logger.debug( warningMessage, discoveryError ); routingTable.forget( routerAddress ); return null; } diff --git a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java index 26656699ff..d8416f55ef 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/cluster/RediscoveryTest.java @@ -52,7 +52,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.startsWith; @@ -182,9 +181,14 @@ void shouldFailImmediatelyWhenClusterCompositionProviderReturnsFailure() ClusterComposition composition = await( rediscovery.lookupClusterComposition( table, pool, empty() ) ); assertEquals( validComposition, composition ); - ArgumentCaptor argument = ArgumentCaptor.forClass( DiscoveryException.class ); - verify( logger ).warn( anyString(), argument.capture() ); - assertThat( argument.getValue().getCause(), equalTo( protocolError ) ); + ArgumentCaptor warningMessageCaptor = ArgumentCaptor.forClass( String.class ); + ArgumentCaptor debugMessageCaptor = ArgumentCaptor.forClass( String.class ); + ArgumentCaptor debugThrowableCaptor = ArgumentCaptor.forClass( DiscoveryException.class ); + verify( logger ).warn( warningMessageCaptor.capture() ); + verify( logger ).debug( debugMessageCaptor.capture(), debugThrowableCaptor.capture() ); + assertNotNull( warningMessageCaptor.getValue() ); + assertEquals( warningMessageCaptor.getValue(), debugMessageCaptor.getValue() ); + assertThat( debugThrowableCaptor.getValue().getCause(), equalTo( protocolError ) ); } @Test