Search in sources :

Example 1 with Command

use of org.neo4j.internal.recordstorage.Command in project neo4j by neo4j.

the class DatabaseRecoveryIT method recoveryShouldFixPartiallyAppliedSchemaIndexUpdates.

@Test
void recoveryShouldFixPartiallyAppliedSchemaIndexUpdates() {
    Label label = Label.label("Foo");
    String property = "Bar";
    // cause failure during 'relationship.delete()' command application
    ClassGuardedAdversary adversary = new ClassGuardedAdversary(new CountingAdversary(1, true), Command.RelationshipCommand.class);
    adversary.disable();
    Path storeDir = directory.homePath();
    DatabaseManagementService managementService = AdversarialPageCacheGraphDatabaseFactory.create(storeDir, fileSystem, adversary).build();
    GraphDatabaseService db = managementService.database(DEFAULT_DATABASE_NAME);
    try {
        try (Transaction tx = db.beginTx()) {
            tx.schema().constraintFor(label).assertPropertyIsUnique(property).create();
            tx.commit();
        }
        long relationshipId = createRelationship(db);
        TransactionFailureException txFailure = null;
        try (Transaction tx = db.beginTx()) {
            Node node = tx.createNode(label);
            node.setProperty(property, "B");
            // this should fail because of the adversary
            tx.getRelationshipById(relationshipId).delete();
            adversary.enable();
            tx.commit();
        } catch (TransactionFailureException e) {
            txFailure = e;
        }
        assertNotNull(txFailure);
        adversary.disable();
        // heal the db so it is possible to inspect the data
        healthOf(db).healed();
        // now we can observe partially committed state: node is in the index and relationship still present
        try (Transaction tx = db.beginTx()) {
            assertNotNull(findNode(label, property, "B", tx));
            assertNotNull(tx.getRelationshipById(relationshipId));
            tx.commit();
        }
        // panic the db again to force recovery on the next startup
        healthOf(db).panic(txFailure.getCause());
        // restart the database, now with regular page cache
        managementService.shutdown();
        db = startDatabase(storeDir);
        // now we observe correct state: node is in the index and relationship is removed
        try (Transaction tx = db.beginTx()) {
            assertNotNull(findNode(label, property, "B", tx));
            assertRelationshipNotExist(tx, relationshipId);
            tx.commit();
        }
    } finally {
        managementService.shutdown();
    }
}
Also used : Path(java.nio.file.Path) GraphDatabaseService(org.neo4j.graphdb.GraphDatabaseService) CountingAdversary(org.neo4j.adversaries.CountingAdversary) TransactionFailureException(org.neo4j.graphdb.TransactionFailureException) ClassGuardedAdversary(org.neo4j.adversaries.ClassGuardedAdversary) Transaction(org.neo4j.graphdb.Transaction) Command(org.neo4j.internal.recordstorage.Command) Node(org.neo4j.graphdb.Node) Label(org.neo4j.graphdb.Label) DatabaseManagementService(org.neo4j.dbms.api.DatabaseManagementService) Test(org.junit.jupiter.api.Test)

Aggregations

Path (java.nio.file.Path)1 Test (org.junit.jupiter.api.Test)1 ClassGuardedAdversary (org.neo4j.adversaries.ClassGuardedAdversary)1 CountingAdversary (org.neo4j.adversaries.CountingAdversary)1 DatabaseManagementService (org.neo4j.dbms.api.DatabaseManagementService)1 GraphDatabaseService (org.neo4j.graphdb.GraphDatabaseService)1 Label (org.neo4j.graphdb.Label)1 Node (org.neo4j.graphdb.Node)1 Transaction (org.neo4j.graphdb.Transaction)1 TransactionFailureException (org.neo4j.graphdb.TransactionFailureException)1 Command (org.neo4j.internal.recordstorage.Command)1