Skip to content

Commit

Permalink
Add RetryableException interface
Browse files Browse the repository at this point in the history
This interface is meant to indicate what exceptions are retryable.
  • Loading branch information
injectives committed May 12, 2022
1 parent 2b9a8f0 commit 40f7ced
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* <p>
* Error code: Neo.ClientError.Security.AuthorizationExpired
*/
public class AuthorizationExpiredException extends SecurityException
public class AuthorizationExpiredException extends SecurityException implements RetryableException
{
public static final String DESCRIPTION = "Authorization information kept on the server has expired, this connection is no longer valid.";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* 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 org.neo4j.driver.exceptions;

/**
* A marker interface indicating if a given exception is considered to be retryable.
*/
public interface RetryableException
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@

/**
* An <em>ServiceUnavailableException</em> indicates that the driver cannot communicate with the cluster.
*
* @since 1.1
*/
public class ServiceUnavailableException extends Neo4jException
public class ServiceUnavailableException extends Neo4jException implements RetryableException
{
public ServiceUnavailableException( String message )
{
Expand All @@ -31,6 +32,6 @@ public ServiceUnavailableException( String message )

public ServiceUnavailableException( String message, Throwable throwable )
{
super( message, throwable);
super( message, throwable );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
package org.neo4j.driver.exceptions;

/**
* A <em>SessionExpiredException</em> indicates that the session can no longer satisfy the criteria under which it
* was acquired, e.g. a server no longer accepts write requests. A new session needs to be acquired from the driver
* and all actions taken on the expired session must be replayed.
* A <em>SessionExpiredException</em> indicates that the session can no longer satisfy the criteria under which it was acquired, e.g. a server no longer accepts
* write requests. A new session needs to be acquired from the driver and all actions taken on the expired session must be replayed.
*
* @since 1.1
*/
public class SessionExpiredException extends Neo4jException
public class SessionExpiredException extends Neo4jException implements RetryableException
{
public SessionExpiredException( String message)
public SessionExpiredException( String message )
{
super( message );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
package org.neo4j.driver.exceptions;

/**
* A <em>TransientException</em> signals a temporary fault that may be worked around by retrying.
* The error code provided can be used to determine further detail for the problem.
* A <em>TransientException</em> signals a temporary fault that may be worked around by retrying. The error code provided can be used to determine further
* detail for the problem.
*
* @since 1.0
*/
public class TransientException extends Neo4jException
public class TransientException extends Neo4jException implements RetryableException
{
public TransientException( String code, String message )
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,11 @@

import org.neo4j.driver.Logger;
import org.neo4j.driver.Logging;
import org.neo4j.driver.exceptions.AuthorizationExpiredException;
import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.exceptions.Neo4jException;
import org.neo4j.driver.exceptions.ServiceUnavailableException;
import org.neo4j.driver.exceptions.SessionExpiredException;
import org.neo4j.driver.exceptions.TransientException;
import org.neo4j.driver.exceptions.RetryableException;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.internal.util.Futures;
import org.neo4j.driver.util.Experimental;

import static java.util.concurrent.TimeUnit.SECONDS;

Expand Down Expand Up @@ -148,14 +144,7 @@ public <T> Publisher<T> retryRx( Publisher<T> work )

protected boolean canRetryOn( Throwable error )
{
return isRetryable( error );
}

@Experimental
public static boolean isRetryable( Throwable error )
{
return error instanceof SessionExpiredException || error instanceof ServiceUnavailableException || error instanceof AuthorizationExpiredException ||
isTransientError( error );
return error instanceof RetryableException;
}

/**
Expand Down Expand Up @@ -351,25 +340,6 @@ private void verifyAfterConstruction()
}
}

private static boolean isTransientError( Throwable error )
{
if ( error instanceof TransientException )
{
String code = ((TransientException) error).code();
// Retries should not happen when transaction was explicitly terminated by the user.
// Termination of transaction might result in two different error codes depending on where it was
// terminated. These are really client errors but classification on the server is not entirely correct and
// they are classified as transient.
if ( "Neo.TransientError.Transaction.Terminated".equals( code ) ||
"Neo.TransientError.Transaction.LockClientStopped".equals( code ) )
{
return false;
}
return true;
}
return false;
}

private static List<Throwable> recordError( Throwable error, List<Throwable> errors )
{
if ( errors == null )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,20 @@ else if ( code.equalsIgnoreCase( "Neo.ClientError.Security.TokenExpired" ) )
}
}
case "TransientError":
return new TransientException( code, message );
// Since 5.0 these 2 errors have been moved to ClientError class.
// This mapping is required if driver is connection to earlier server versions.
if ( "Neo.TransientError.Transaction.Terminated".equals( code ) )
{
return new ClientException( "Neo.ClientError.Transaction.Terminated", message );
}
else if ( "Neo.TransientError.Transaction.LockClientStopped".equals( code ) )
{
return new ClientException( "Neo.ClientError.Transaction.LockClientStopped", message );
}
else
{
return new TransientException( code, message );
}
default:
return new DatabaseException( code, message );
}
Expand Down

0 comments on commit 40f7ced

Please sign in to comment.