diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/ClassicCoreSPI.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/ClassicCoreSPI.java index 1d46de7a64bfd..493d72fcf3ab4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/ClassicCoreSPI.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/ClassicCoreSPI.java @@ -28,7 +28,6 @@ import org.neo4j.graphdb.Result; import org.neo4j.graphdb.event.KernelEventHandler; import org.neo4j.graphdb.event.TransactionEventHandler; -import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.security.URLAccessValidationError; import org.neo4j.kernel.GraphDatabaseQueryService; import org.neo4j.kernel.api.KernelTransaction; @@ -54,7 +53,6 @@ class ClassicCoreSPI implements GraphDatabaseFacade.SPI private final DataSourceModule dataSource; private final Logger msgLog; private final CoreAPIAvailabilityGuard availability; - private final long defaultTransactionTimeout; public ClassicCoreSPI(PlatformModule platform, DataSourceModule dataSource, Logger msgLog, CoreAPIAvailabilityGuard availability ) { @@ -62,7 +60,6 @@ public ClassicCoreSPI(PlatformModule platform, DataSourceModule dataSource, Logg this.dataSource = dataSource; this.msgLog = msgLog; this.availability = availability; - defaultTransactionTimeout = platform.config.get( GraphDatabaseSettings.transaction_timeout ); } @Override @@ -167,12 +164,6 @@ public void shutdown() } } - @Override - public KernelTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode ) - { - return beginTransaction( type, accessMode, defaultTransactionTimeout ); - } - @Override public KernelTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacade.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacade.java index 4ff585cab4e6e..bcc70248443af 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacade.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacade.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; import org.neo4j.collection.primitive.PrimitiveLongCollections; import org.neo4j.collection.primitive.PrimitiveLongIterator; @@ -44,6 +43,7 @@ import org.neo4j.graphdb.TransactionTerminatedException; import org.neo4j.graphdb.event.KernelEventHandler; import org.neo4j.graphdb.event.TransactionEventHandler; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.index.IndexManager; import org.neo4j.graphdb.schema.Schema; import org.neo4j.graphdb.security.URLAccessValidationError; @@ -67,6 +67,7 @@ import org.neo4j.kernel.api.legacyindex.AutoIndexing; import org.neo4j.kernel.api.properties.Property; import org.neo4j.kernel.api.security.AccessMode; +import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.api.TokenAccess; import org.neo4j.kernel.impl.api.legacyindex.InternalAutoIndexing; import org.neo4j.kernel.impl.api.operations.KeyReadOperations; @@ -115,6 +116,7 @@ public class GraphDatabaseFacade implements GraphDatabaseAPI private NodeProxy.NodeActions nodeActions; private RelationshipProxy.RelationshipActions relActions; private SPI spi; + private long defaultTransactionTimeout; /** * This is what you need to implemenent to get your very own {@link GraphDatabaseFacade}. This SPI exists as a thin @@ -141,14 +143,6 @@ public interface SPI void shutdown(); - /** - * Begin a new kernel transaction. If a transaction is already associated to the current context - * (meaning, non-null is returned from {@link #currentTransaction()}), this should fail. - * - * @throws org.neo4j.graphdb.TransactionFailureException if unable to begin, or a transaction already exists. - */ - KernelTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode ); - /** * Begin a new kernel transaction with specified timeout in milliseconds. * If a transaction is already associated to the current context @@ -200,8 +194,9 @@ public GraphDatabaseFacade() /** * Create a new Core API facade, backed by the given SPI. */ - public void init( SPI spi ) + public void init( SPI spi, Config config ) { + defaultTransactionTimeout = config.get( GraphDatabaseSettings.transaction_timeout ); IndexProviderImpl idxProvider = new IndexProviderImpl( this, spi::currentStatement ); this.spi = spi; @@ -350,15 +345,17 @@ public Transaction beginTx( long timeout, TimeUnit unit ) return beginTransaction( KernelTransaction.Type.explicit, AccessMode.Static.FULL, timeout, unit ); } + @Override public InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode ) { - return beginTransaction( () -> spi.beginTransaction( type, accessMode ) ); + return beginTransactionInternal( type, accessMode, defaultTransactionTimeout ); } + @Override public InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout, TimeUnit unit ) { - return beginTransaction( () -> spi.beginTransaction( type, accessMode, unit.toMillis( timeout ) ) ); + return beginTransactionInternal( type, accessMode, unit.toMillis( timeout ) ); } @Override @@ -543,14 +540,15 @@ public ResourceIterator findNodes( final Label myLabel ) return allNodesWithLabel( myLabel ); } - private InternalTransaction beginTransaction( Supplier transactionSupplier ) + private InternalTransaction beginTransactionInternal( KernelTransaction.Type type, AccessMode accessMode, + long timeoutMillis ) { if ( spi.isInOpenTransaction() ) { // FIXME: perhaps we should check that the new type and access mode are compatible with the current tx return new PlaceboTransaction( spi::currentTransaction, spi::currentStatement ); } - return new TopLevelTransaction( transactionSupplier.get(), spi::currentStatement ); + return new TopLevelTransaction( spi.beginTransaction( type, accessMode, timeoutMillis ), spi::currentStatement ); } private ResourceIterator nodesByLabelAndProperty( Label myLabel, String key, Object value ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeFactory.java index 7107e55042ace..f1219959c4a63 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeFactory.java @@ -138,7 +138,8 @@ public GraphDatabaseFacade initFacade( File storeDir, Map params, CoreAPIAvailabilityGuard coreAPIAvailabilityGuard = edition.coreAPIAvailabilityGuard; // Start it - graphDatabaseFacade.init( new ClassicCoreSPI( platform, dataSource, msgLog, coreAPIAvailabilityGuard ) ); + graphDatabaseFacade.init( new ClassicCoreSPI( platform, dataSource, msgLog, coreAPIAvailabilityGuard ), + platform.config ); Throwable error = null; try diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDBFacadeSPI.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDBFacadeSPI.java index 1af5096a09ccf..710feef5e79c9 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDBFacadeSPI.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDBFacadeSPI.java @@ -195,12 +195,6 @@ public void shutdown() throw new UnsupportedOperationException(); } - @Override - public KernelTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode ) - { - throw new UnsupportedOperationException(); - } - @Override public KernelTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDSFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDSFactory.java index 4dbbb449fbbee..16e4f3734024b 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDSFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/ProcedureGDSFactory.java @@ -40,6 +40,7 @@ public class ProcedureGDSFactory implements ThrowingFunction { + private Config config; private final File storeDir; private final DependencyResolver resolver; private final Supplier storeId; @@ -55,6 +56,7 @@ public ProcedureGDSFactory( Config config, CoreAPIAvailabilityGuard availability, URLAccessRule urlAccessRule ) { + this.config = config; this.storeDir = storeDir; this.resolver = resolver; this.storeId = storeId; @@ -70,7 +72,7 @@ public GraphDatabaseService apply( CallableProcedure.Context context ) throws Pr Thread owningThread = context.get( CallableProcedure.Context.THREAD ); GraphDatabaseFacade facade = new GraphDatabaseFacade(); facade.init( new ProcedureGDBFacadeSPI( owningThread, transaction, queryExecutor, storeDir, resolver, - AutoIndexing.UNSUPPORTED, storeId, availability, urlValidator ) ); + AutoIndexing.UNSUPPORTED, storeId, availability, urlValidator ), config ); return facade; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/internal/GraphDatabaseAPI.java b/community/kernel/src/main/java/org/neo4j/kernel/internal/GraphDatabaseAPI.java index b14ac7b15fbaf..4626ab80422c7 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/internal/GraphDatabaseAPI.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/internal/GraphDatabaseAPI.java @@ -20,6 +20,7 @@ package org.neo4j.kernel.internal; import java.net.URL; +import java.util.concurrent.TimeUnit; import org.neo4j.graphdb.DependencyResolver; import org.neo4j.graphdb.GraphDatabaseService; @@ -53,5 +54,21 @@ public interface GraphDatabaseAPI extends GraphDatabaseService String getStoreDir(); + /** + * Begin internal transaction with specified type and access mode + * @param type transaction type + * @param accessMode transaction access mode + * @return internal transaction + */ InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode ); + + /** + * Begin internal transaction with specified type, access mode and timeout + * @param type transaction type + * @param accessMode transaction access mode + * @param timeout transaction timeout + * @param unit time unit of timeout argument + * @return internal transaction + */ + InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout, TimeUnit unit ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java index 27e045f4437c0..999d8ce9ace6d 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java @@ -28,9 +28,11 @@ import java.util.concurrent.TimeUnit; import org.neo4j.graphdb.DependencyResolver; +import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.kernel.GraphDatabaseQueryService; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.security.AccessMode; +import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import static org.mockito.Mockito.mock; @@ -45,6 +47,7 @@ public class GraphDatabaseFacadeTest private GraphDatabaseFacade graphDatabaseFacade = new GraphDatabaseFacade(); private GraphDatabaseQueryService queryService; private DependencyResolver dependencyResolver; + private Config defaultConfig; @Before public void setUp() @@ -55,9 +58,12 @@ public void setUp() when( spi.queryService() ).thenReturn( queryService ); when( queryService.getDependencyResolver() ).thenReturn( dependencyResolver ); - when( dependencyResolver.resolveDependency( ThreadToStatementContextBridge.class ) ).thenReturn( contextBridge ); + when( dependencyResolver.resolveDependency( ThreadToStatementContextBridge.class ) ) + .thenReturn( contextBridge ); - graphDatabaseFacade.init( spi ); + defaultConfig = Config.defaults(); + + graphDatabaseFacade.init( spi, defaultConfig ); } @Test @@ -73,7 +79,8 @@ public void beginTransaction() { graphDatabaseFacade.beginTx(); - verify( spi ).beginTransaction( KernelTransaction.Type.explicit, AccessMode.Static.FULL ); + long timeout = defaultConfig.get( GraphDatabaseSettings.transaction_timeout ); + verify( spi ).beginTransaction( KernelTransaction.Type.explicit, AccessMode.Static.FULL, timeout ); } @Test @@ -94,6 +101,7 @@ public void executeQueryStartDefaultTransaction() graphDatabaseFacade.execute( "create (n)" ); graphDatabaseFacade.execute( "create (n)", new HashMap<>() ); - verify( spi, times( 2 ) ).beginTransaction( KernelTransaction.Type.implicit, AccessMode.Static.FULL ); + long timeout = defaultConfig.get( GraphDatabaseSettings.transaction_timeout ); + verify( spi, times( 2 ) ).beginTransaction( KernelTransaction.Type.implicit, AccessMode.Static.FULL, timeout ); } } diff --git a/community/kernel/src/test/java/org/neo4j/test/rule/DatabaseRule.java b/community/kernel/src/test/java/org/neo4j/test/rule/DatabaseRule.java index 7f537041d6f74..8dc0a00f81f46 100644 --- a/community/kernel/src/test/java/org/neo4j/test/rule/DatabaseRule.java +++ b/community/kernel/src/test/java/org/neo4j/test/rule/DatabaseRule.java @@ -155,6 +155,13 @@ public InternalTransaction beginTransaction( KernelTransaction.Type type, Access return getGraphDatabaseAPI().beginTransaction( type, accessMode ); } + @Override + public InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout, + TimeUnit unit ) + { + return getGraphDatabaseAPI().beginTransaction( type, accessMode, timeout, unit ); + } + @Override public Transaction beginTx() { diff --git a/community/server/src/test/java/org/neo4j/server/rest/transactional/TransitionalPeriodTransactionMessContainerTest.java b/community/server/src/test/java/org/neo4j/server/rest/transactional/TransitionalPeriodTransactionMessContainerTest.java index c6fd70fbf522e..62b7b0cc971a2 100644 --- a/community/server/src/test/java/org/neo4j/server/rest/transactional/TransitionalPeriodTransactionMessContainerTest.java +++ b/community/server/src/test/java/org/neo4j/server/rest/transactional/TransitionalPeriodTransactionMessContainerTest.java @@ -62,13 +62,13 @@ public void setUp() @Test public void startTransactionWithCustomTimeout() throws Exception { - when( databaseFacade.beginTransaction( type, accessMode, 10, TimeUnit.SECONDS ) ).thenReturn( internalTransaction ); + when( databaseFacade.beginTransaction( type, accessMode, 10, TimeUnit.MILLISECONDS ) ).thenReturn( internalTransaction ); TransitionalPeriodTransactionMessContainer transactionMessContainer = new TransitionalPeriodTransactionMessContainer( databaseFacade ); transactionMessContainer.create( queryService, type, accessMode, 10, request ); - verify( databaseFacade ).beginTransaction( type, accessMode, 10, TimeUnit.SECONDS ); + verify( databaseFacade ).beginTransaction( type, accessMode, 10, TimeUnit.MILLISECONDS ); } @Test diff --git a/community/shell/src/main/java/org/neo4j/shell/kernel/ReadOnlyGraphDatabaseProxy.java b/community/shell/src/main/java/org/neo4j/shell/kernel/ReadOnlyGraphDatabaseProxy.java index 487a0ded133b8..fa8bcd656db73 100644 --- a/community/shell/src/main/java/org/neo4j/shell/kernel/ReadOnlyGraphDatabaseProxy.java +++ b/community/shell/src/main/java/org/neo4j/shell/kernel/ReadOnlyGraphDatabaseProxy.java @@ -98,6 +98,13 @@ public InternalTransaction beginTransaction( KernelTransaction.Type type, Access return actual.beginTransaction( type, accessMode ); } + @Override + public InternalTransaction beginTransaction( KernelTransaction.Type type, AccessMode accessMode, long timeout, + TimeUnit unit ) + { + return actual.beginTransaction( type, accessMode, timeout, unit ); + } + @Override public Transaction beginTx() {