Skip to content

Commit

Permalink
Unflake IndexStatisticsTest
Browse files Browse the repository at this point in the history
There is an optimization in the node.setProperty that does not send an
index update if the old and now values are equal. This was not
compensated for in the test.
  • Loading branch information
klaren committed Jan 22, 2018
1 parent da2541a commit 010b124
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
Expand Up @@ -66,7 +66,7 @@ public IndexUpdater newUpdater( final IndexUpdateMode mode )
return new PopulatingIndexUpdater() return new PopulatingIndexUpdater()
{ {
@Override @Override
public void process( IndexEntryUpdate<?> update ) throws IOException, IndexEntryConflictException public void process( IndexEntryUpdate<?> update )
{ {
job.update( update ); job.update( update );
} }
Expand Down
Expand Up @@ -72,6 +72,31 @@
import static org.junit.runners.Parameterized.Parameter; import static org.junit.runners.Parameterized.Parameter;
import static org.junit.runners.Parameterized.Parameters; import static org.junit.runners.Parameterized.Parameters;


/**
* This test validates that we count the correct amount of index updates.
* <p>
* We build the index async with a node scan in the background and consume transactions to keep the index updated. Once
* the index is build and becomes online, we save the index size(number of entries) and begin tracking updates. These
* values can then then be used to determine when to resample the index for example.
*
* <pre>
* online
* index size | updates
* v
* |----------------T--------------> stream of transactions
* ^
* during | after
* observed
* </pre>
*
* Since we observe the index online event without strict synchronization, we cannot determine what transactions are
* before and after that event. This is illustrated in the drawing above where transaction {@code T} is counted as
* occurring during the population and not after, which is incorrect.
* <p>
* That is why we allow a difference of {@link IndexStatisticsTest#MISSED_UPDATES_TOLERANCE}, to exists. This threshold
* is the number of updates in the larges transaction and that should be the larges error since we check if the index is
* online between each transaction.
*/
@RunWith( Parameterized.class ) @RunWith( Parameterized.class )
public class IndexStatisticsTest public class IndexStatisticsTest
{ {
Expand Down Expand Up @@ -276,6 +301,27 @@ public void shouldProvideIndexStatisticsWhenIndexIsBuiltViaPopulationAndConcurre
assertCorrectIndexUpdates( updatesTracker.createdAfterPopulation(), indexUpdates( index ) ); assertCorrectIndexUpdates( updatesTracker.createdAfterPopulation(), indexUpdates( index ) );
} }


@Test
public void shouldProvideIndexStatisticsWhenIndexIsBuiltViaPopulationAndConcurrentAdditionsAndChangesAndDeletions() throws Exception
{
// given some initial data
long[] nodes = repeatCreateNamedPeopleFor( NAMES.length * CREATION_MULTIPLIER );
int initialNodes = nodes.length;

// when populating while creating
IndexDescriptor index = createIndex( "Person", "name" );
UpdatesTracker updatesTracker = executeCreationsDeletionsAndUpdates( nodes, index, CREATION_MULTIPLIER );
awaitIndexesOnline();

// then
int seenWhilePopulating = initialNodes + updatesTracker.createdDuringPopulation() - updatesTracker.deletedDuringPopulation();
double expectedSelectivity = UNIQUE_NAMES / seenWhilePopulating;
int expectedIndexUpdates = updatesTracker.deletedAfterPopulation() + updatesTracker.createdAfterPopulation() + updatesTracker.updatedAfterPopulation();
assertCorrectIndexSelectivity( expectedSelectivity, indexSelectivity( index ) );
assertCorrectIndexSize( seenWhilePopulating, indexSize( index ) );
assertCorrectIndexUpdates( expectedIndexUpdates, indexUpdates( index ) );
}

@Test @Test
public void shouldWorkWhileHavingHeavyConcurrentUpdates() throws Exception public void shouldWorkWhileHavingHeavyConcurrentUpdates() throws Exception
{ {
Expand Down Expand Up @@ -330,14 +376,16 @@ private void deleteNode( long nodeId ) throws KernelException
} }
} }


private boolean changeName( long nodeId, String propertyKeyName, Object newValue ) throws KernelException private boolean changeName( long nodeId, String propertyKeyName, Object newValue )
{ {
boolean changeIndexedNode = false; boolean changeIndexedNode = false;
try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
Node node = db.getNodeById( nodeId ); Node node = db.getNodeById( nodeId );
if ( node.hasProperty( propertyKeyName ) ) Object oldValue = node.getProperty( propertyKeyName );
if ( !oldValue.equals( newValue ) )
{ {
// Changes are only propagated when the value actually change
changeIndexedNode = true; changeIndexedNode = true;
} }
node.setProperty( propertyKeyName, newValue ); node.setProperty( propertyKeyName, newValue );
Expand Down Expand Up @@ -520,7 +568,7 @@ private NeoStores neoStores()


private void awaitIndexesOnline() private void awaitIndexesOnline()
{ {
try ( Transaction transaction = db.beginTx() ) try ( Transaction ignored = db.beginTx() )
{ {
db.schema().awaitIndexesOnline(3, TimeUnit.MINUTES ); db.schema().awaitIndexesOnline(3, TimeUnit.MINUTES );
} }
Expand Down Expand Up @@ -590,12 +638,12 @@ private UpdatesTracker internalExecuteCreationsDeletionsAndUpdates( long[] nodes
int randomIndex = random.nextInt( nodes.length ); int randomIndex = random.nextInt( nodes.length );
try try
{ {
if ( changeName( nodes[randomIndex], "name", NAMES[randomIndex % NAMES.length] ) ) if ( changeName( nodes[randomIndex], "name", NAMES[random.nextInt( NAMES.length )] ) )
{ {
updatesTracker.increaseUpdated( 1 ); updatesTracker.increaseUpdated( 1 );
} }
} }
catch ( EntityNotFoundException | NotFoundException ex ) catch ( NotFoundException ex )
{ {
// ignore // ignore
} }
Expand Down
Expand Up @@ -128,6 +128,9 @@ public String toString()
", createdDuringPopulation=" + createdDuringPopulation + ", createdDuringPopulation=" + createdDuringPopulation +
", updatedDuringPopulation=" + updatedDuringPopulation + ", updatedDuringPopulation=" + updatedDuringPopulation +
", deletedDuringPopulation=" + deletedDuringPopulation + ", deletedDuringPopulation=" + deletedDuringPopulation +
", createdAfterPopulation=" + createdAfterPopulation() +
", updatedAfterPopulation=" + updatedAfterPopulation() +
", deletedAfterPopulation=" + deletedAfterPopulation() +
", populationCompleted=" + populationCompleted + ", populationCompleted=" + populationCompleted +
'}'; '}';
} }
Expand Down

0 comments on commit 010b124

Please sign in to comment.