All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.helpers.TransactionTemplate Maven / Gradle / Ivy

/*
 * Copyright (c) 2002-2016 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.helpers;

import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import org.neo4j.function.Predicates;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.TransactionFailureException;
import org.neo4j.graphdb.TransactionTerminatedException;
import org.neo4j.graphdb.TransientFailureException;

import static org.neo4j.function.Predicates.any;

/**
 * Neo4j transaction template that automates the retry-on-exception logic. It uses the builder
 * pattern for configuration, with copy-semantics, so you can iteratively build up instances for
 * different scenarios.
 * 

* First instantiate and configure the template using the fluent API methods, and then * invoke execute which will begin/commit transactions in a loop for the specified number of times. *

* By default all exceptions (except Errors and TransactionTerminatedException) cause a retry, * and the monitor does nothing, but these can be overridden with custom behavior. * A bit more narrow and typical exception to retry on is {@link TransientFailureException}, * which aims to represent exceptions that are most likely to succeed after a retry. */ public class TransactionTemplate { public interface Monitor { void failure( Throwable ex ); void failed( Throwable ex ); void retrying(); class Adapter implements Monitor { @Override public void failure( Throwable ex ) { } @Override public void failed( Throwable ex ) { } @Override public void retrying() { } } } private final GraphDatabaseService gds; private final Monitor monitor; private final int retries; private final long backoff; private final Predicate retryPredicate; public TransactionTemplate() { this( null, new Monitor.Adapter(), 0, 0, any( Predicates.instanceOf( Error.class ), Predicates.instanceOf( TransactionTerminatedException.class ) ).negate() ); } public TransactionTemplate( GraphDatabaseService gds, Monitor monitor, int retries, long backoff, Predicate retryPredicate ) { this.gds = gds; this.monitor = monitor; this.retries = retries; this.backoff = backoff; this.retryPredicate = retryPredicate; } public TransactionTemplate with( GraphDatabaseService gds ) { return new TransactionTemplate( gds, monitor, retries, backoff, retryPredicate ); } public TransactionTemplate retries( int retries ) { return new TransactionTemplate( gds, monitor, retries, backoff, retryPredicate ); } public TransactionTemplate backoff( long backoff, TimeUnit unit ) { return new TransactionTemplate( gds, monitor, retries, unit.toMillis( backoff ), retryPredicate ); } public TransactionTemplate monitor( Monitor monitor ) { return new TransactionTemplate( gds, monitor, retries, backoff, retryPredicate ); } public TransactionTemplate retryOn( Predicate retryPredicate ) { return new TransactionTemplate( gds, monitor, retries, backoff, retryPredicate ); } public void execute( final Consumer txConsumer ) { execute( transaction -> { txConsumer.accept( transaction ); return null; } ); } public T execute( Function txFunction ) throws TransactionFailureException { Throwable txEx = null; for ( int i = 0; i < retries; i++ ) { try ( Transaction tx = gds.beginTx() ) { T result = txFunction.apply( tx ); tx.success(); return result; } catch ( Throwable ex ) { monitor.failure( ex ); txEx = ex; if ( !retryPredicate.test( ex ) ) { break; } } if ( i < retries - 1 ) { try { Thread.sleep( backoff ); } catch ( InterruptedException e ) { throw new TransactionFailureException( "Interrupted", e ); } monitor.retrying(); } } if ( txEx instanceof TransactionFailureException ) { throw ((TransactionFailureException) txEx); } else if ( txEx instanceof Error ) { throw ((Error) txEx); } else if ( txEx instanceof RuntimeException ) { throw ((RuntimeException) txEx); } else { throw new TransactionFailureException( "Failed", txEx ); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy