diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/ClusterIndexProcedureIT.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/ClusterIndexProcedureIT.java index 4009d3cdae213..74be699994470 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/ClusterIndexProcedureIT.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/scenarios/ClusterIndexProcedureIT.java @@ -29,10 +29,9 @@ import java.util.Iterator; import java.util.concurrent.TimeUnit; -import org.neo4j.causalclustering.core.CoreGraphDatabase; import org.neo4j.causalclustering.discovery.Cluster; +import org.neo4j.causalclustering.discovery.ClusterMember; import org.neo4j.causalclustering.discovery.CoreClusterMember; -import org.neo4j.causalclustering.discovery.ReadReplica; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; @@ -44,7 +43,6 @@ import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; -import org.neo4j.kernel.impl.factory.GraphDatabaseFacade; import org.neo4j.kernel.internal.GraphDatabaseAPI; import org.neo4j.test.causalclustering.ClusterRule; @@ -52,6 +50,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.neo4j.causalclustering.discovery.Cluster.dataMatchesEventually; +import static org.neo4j.graphdb.schema.ConstraintType.NODE_KEY; +import static org.neo4j.graphdb.schema.ConstraintType.UNIQUENESS; public class ClusterIndexProcedureIT { @@ -73,104 +74,99 @@ public void setup() throws Exception @Test public void createIndexProcedureMustPropagate() throws Exception { - // given + // create an index cluster.coreTx( ( db, tx ) -> { - Node person = db.createNode( Label.label( "Person" ) ); - person.setProperty( "name", "Bo Burnham" ); + db.execute( "CALL db.createIndex( \":Person(name)\", \"lucene+native-1.0\")" ).close(); tx.success(); } ); - // when + // node created just to be able to use dataMatchesEventually as a barrier CoreClusterMember leader = cluster.coreTx( ( db, tx ) -> { - db.execute( "CALL db.createIndex( \":Person(name)\", \"lucene+native-1.0\")" ).close(); + Node person = db.createNode( Label.label( "Person" ) ); + person.setProperty( "name", "Bo Burnham" ); tx.success(); } ); - awaitIndexOnline( leader ); - // then - Cluster.dataMatchesEventually( leader, cluster.coreMembers() ); - Cluster.dataMatchesEventually( leader, cluster.readReplicas() ); - for ( CoreClusterMember core : cluster.coreMembers() ) - { - verifyIndexes( core.database() ); - } - for ( ReadReplica readReplica : cluster.readReplicas() ) - { - verifyIndexes( readReplica.database() ); - } + // node creation is guaranteed to happen after index creation + dataMatchesEventually( leader, cluster.coreMembers() ); + dataMatchesEventually( leader, cluster.readReplicas() ); + + // now the indexes must exist, so we wait for them to come online + cluster.coreMembers().forEach( this::awaitIndexOnline ); + cluster.readReplicas().forEach( this::awaitIndexOnline ); + + // verify indexes + cluster.coreMembers().forEach( core -> verifyIndexes( core.database() ) ); + cluster.readReplicas().forEach( rr -> verifyIndexes( rr.database() ) ); } @Test public void createUniquePropertyConstraintMustPropagate() throws Exception { - // given - cluster.coreTx( ( db, tx ) -> + // create a constraint + CoreClusterMember leader = cluster.coreTx( ( db, tx ) -> { - Node person = db.createNode( Label.label( "Person" ) ); - person.setProperty( "name", "Bo Burnham" ); + db.execute( "CALL db.createUniquePropertyConstraint( \":Person(name)\", \"lucene+native-1.0\")" ).close(); tx.success(); } ); - // when - CoreClusterMember leader = cluster.coreTx( ( db, tx ) -> + // node created just to be able to use dataMatchesEventually as a barrier + cluster.coreTx( ( db, tx ) -> { - db.execute( "CALL db.createUniquePropertyConstraint( \":Person(name)\", \"lucene+native-1.0\")" ).close(); + Node person = db.createNode( Label.label( "Person" ) ); + person.setProperty( "name", "Bo Burnham" ); tx.success(); } ); - // then - Cluster.dataMatchesEventually( leader, cluster.coreMembers() ); - Cluster.dataMatchesEventually( leader, cluster.readReplicas() ); - for ( CoreClusterMember core : cluster.coreMembers() ) - { - verifyIndexes( core.database() ); - verifyConstraints( core.database(), ConstraintType.UNIQUENESS ); - } - for ( ReadReplica readReplica : cluster.readReplicas() ) - { - verifyIndexes( readReplica.database() ); - verifyConstraints( readReplica.database(), ConstraintType.UNIQUENESS ); - } + // node creation is guaranteed to happen after constraint creation + dataMatchesEventually( leader, cluster.coreMembers() ); + dataMatchesEventually( leader, cluster.readReplicas() ); + + // verify indexes + cluster.coreMembers().forEach( core -> verifyIndexes( core.database() ) ); + cluster.readReplicas().forEach( rr -> verifyIndexes( rr.database() ) ); + + // verify constraints + cluster.coreMembers().forEach( core -> verifyConstraints( core.database(), UNIQUENESS ) ); + cluster.readReplicas().forEach( rr -> verifyConstraints( rr.database(), UNIQUENESS ) ); } @Test public void createNodeKeyConstraintMustPropagate() throws Exception { - // given - cluster.coreTx( ( db, tx ) -> + // create a node key + CoreClusterMember leader = cluster.coreTx( ( db, tx ) -> { - Node person = db.createNode( Label.label( "Person" ) ); - person.setProperty( "name", "Bo Burnham" ); + db.execute( "CALL db.createNodeKey( \":Person(name)\", \"lucene+native-1.0\")" ).close(); tx.success(); } ); - // when - CoreClusterMember leader = cluster.coreTx( ( db, tx ) -> + // node created just to be able to use dataMatchesEventually as a barrier + cluster.coreTx( ( db, tx ) -> { - db.execute( "CALL db.createNodeKey( \":Person(name)\", \"lucene+native-1.0\")" ).close(); + Node person = db.createNode( Label.label( "Person" ) ); + person.setProperty( "name", "Bo Burnham" ); tx.success(); } ); - // then - Cluster.dataMatchesEventually( leader, cluster.coreMembers() ); - Cluster.dataMatchesEventually( leader, cluster.readReplicas() ); - for ( CoreClusterMember core : cluster.coreMembers() ) - { - verifyIndexes( core.database() ); - verifyConstraints( core.database(), ConstraintType.NODE_KEY ); - } - for ( ReadReplica readReplica : cluster.readReplicas() ) - { - verifyIndexes( readReplica.database() ); - verifyConstraints( readReplica.database(), ConstraintType.NODE_KEY ); - } + // node creation is guaranteed to happen after constraint creation + dataMatchesEventually( leader, cluster.coreMembers() ); + dataMatchesEventually( leader, cluster.readReplicas() ); + + // verify indexes + cluster.coreMembers().forEach( core -> verifyIndexes( core.database() ) ); + cluster.readReplicas().forEach( rr -> verifyIndexes( rr.database() ) ); + + // verify node keys + cluster.coreMembers().forEach( core -> verifyConstraints( core.database(), NODE_KEY ) ); + cluster.readReplicas().forEach( rr -> verifyConstraints( rr.database(), NODE_KEY ) ); } - private void awaitIndexOnline( CoreClusterMember member ) + private void awaitIndexOnline( ClusterMember member ) { - CoreGraphDatabase db = member.database(); + GraphDatabaseAPI db = member.database(); try ( Transaction tx = db.beginTx() ) { db.schema().awaitIndexesOnline( 1, TimeUnit.MINUTES ); @@ -178,12 +174,12 @@ private void awaitIndexOnline( CoreClusterMember member ) } } - private void verifyIndexes( GraphDatabaseFacade database ) + private void verifyIndexes( GraphDatabaseAPI db ) { - try ( Transaction tx = database.beginTx() ) + try ( Transaction tx = db.beginTx() ) { // only one index - Iterator indexes = database.schema().getIndexes().iterator(); + Iterator indexes = db.schema().getIndexes().iterator(); assertTrue( "has one index", indexes.hasNext() ); IndexDefinition indexDefinition = indexes.next(); assertFalse( "not more than one index", indexes.hasNext() ); @@ -194,18 +190,18 @@ private void verifyIndexes( GraphDatabaseFacade database ) // with correct pattern and provider assertEquals( "correct label", "Person", label.name() ); assertEquals( "correct property", "name", property ); - assertCorrectProvider( database, label, property ); + assertCorrectProvider( db, label, property ); tx.success(); } } - private void verifyConstraints( GraphDatabaseFacade database, ConstraintType expectedConstraintType ) + private void verifyConstraints( GraphDatabaseAPI db, ConstraintType expectedConstraintType ) { - try ( Transaction tx = database.beginTx() ) + try ( Transaction tx = db.beginTx() ) { // only one index - Iterator constraints = database.schema().getConstraints().iterator(); + Iterator constraints = db.schema().getConstraints().iterator(); assertTrue( "has one index", constraints.hasNext() ); ConstraintDefinition constraint = constraints.next(); assertFalse( "not more than one index", constraints.hasNext() );