How to handle NotFoundException elegantly in Neo4j 2.0?

不想你离开。 提交于 2019-12-24 15:54:30

问题


We were wishfully thinking that with Neo4j 2.0, concurrently querying and deleting nodes will no longer throw NotFoundException. Our previous system using Neo4j 1.9.3 was full of checks to handle this exception(very ugly code). Is there any better way to handle NotFoundException(if not eliminate) in neo4j 2.0 or, in the pipeline?

Stack Trace:

org.neo4j.graphdb.NotFoundException: Node 2432 not found
    at org.neo4j.kernel.impl.core.NodeManager.getNodeForProxy(NodeManager.java:425)
    at org.neo4j.kernel.impl.api.state.OldTxStateBridgeImpl.deleteNode(OldTxStateBridgeImpl.java:111)
    at org.neo4j.kernel.impl.api.state.TxStateImpl.nodeDoDelete(TxStateImpl.java:250)
    at org.neo4j.kernel.impl.api.StateHandlingStatementOperations.nodeDelete(StateHandlingStatementOperations.java:100)
    at org.neo4j.kernel.impl.api.ConstraintEnforcingEntityOperations.nodeDelete(ConstraintEnforcingEntityOperations.java:140)
    at org.neo4j.kernel.impl.api.LockingStatementOperations.nodeDelete(LockingStatementOperations.java:196)
    at org.neo4j.kernel.impl.api.OperationsFacade.nodeDelete(OperationsFacade.java:428)
    at org.neo4j.cypher.internal.spi.v2_0.TransactionBoundExecutionContext$NodeOperations.delete(TransactionBoundExecutionContext.scala:132)
    at org.neo4j.cypher.internal.spi.v2_0.TransactionBoundExecutionContext$NodeOperations.delete(TransactionBoundExecutionContext.scala:130)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.DelegatingOperations.delete(DelegatingQueryContext.scala:92)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext$ExceptionTranslatingOperations.org$neo4j$cypher$internal$compiler$v2_0$spi$ExceptionTranslatingQueryContext$ExceptionTranslatingOperations$$super$delete(ExceptionTranslatingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext$ExceptionTranslatingOperations$$anonfun$delete$1.apply$mcV$sp(ExceptionTranslatingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext$ExceptionTranslatingOperations$$anonfun$delete$1.apply(ExceptionTranslatingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext$ExceptionTranslatingOperations$$anonfun$delete$1.apply(ExceptionTranslatingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext.org$neo4j$cypher$internal$compiler$v2_0$spi$ExceptionTranslatingQueryContext$$translateException(ExceptionTranslatingQueryContext.scala:149)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.ExceptionTranslatingQueryContext$ExceptionTranslatingOperations.delete(ExceptionTranslatingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.spi.UpdateCountingQueryContext$CountingOps.delete(UpdateCountingQueryContext.scala:118)
    at org.neo4j.cypher.internal.compiler.v2_0.mutation.DeleteEntityAction.org$neo4j$cypher$internal$compiler$v2_0$mutation$DeleteEntityAction$$delete(DeleteEntityAction.scala:50)
    at org.neo4j.cypher.internal.compiler.v2_0.mutation.DeleteEntityAction.exec(DeleteEntityAction.scala:36)
    at org.neo4j.cypher.internal.compiler.v2_0.pipes.ExecuteUpdateCommandsPipe.org$neo4j$cypher$internal$compiler$v2_0$pipes$ExecuteUpdateCommandsPipe$$exec(ExecuteUpdateCommandsPipe.scala:56)
    at org.neo4j.cypher.internal.compiler.v2_0.pipes.ExecuteUpdateCommandsPipe$$anonfun$org$neo4j$cypher$internal$compiler$v2_0$pipes$ExecuteUpdateCommandsPipe$$executeMutationCommands$1$$anonfun$apply$2.apply(ExecuteUpdateCommandsPipe.scala:45)
    at org.neo4j.cypher.internal.compiler.v2_0.pipes.ExecuteUpdateCommandsPipe$$anonfun$org$neo4j$cypher$internal$compiler$v2_0$pipes$ExecuteUpdateCommandsPipe$$executeMutationCommands$1$$anonfun$apply$2.apply(ExecuteUpdateCommandsPipe.scala:45)
    at scala.collection.Iterator$$anon$13.hasNext(Iterator.scala:371)
    at scala.collection.Iterator$$anon$13.hasNext(Iterator.scala:371)
    at org.neo4j.cypher.internal.compiler.v2_0.pipes.EmptyResultPipe.internalCreateResults(EmptyResultPipe.scala:28)
    at org.neo4j.cypher.internal.compiler.v2_0.pipes.PipeWithSource.createResults(Pipe.scala:71)
    at org.neo4j.cypher.internal.compiler.v2_0.executionplan.ExecutionPlanBuilder.org$neo4j$cypher$internal$compiler$v2_0$executionplan$ExecutionPlanBuilder$$prepareStateAndResult(ExecutionPlanBuilder.scala:149)
    at org.neo4j.cypher.internal.compiler.v2_0.executionplan.ExecutionPlanBuilder$$anonfun$3.apply(ExecutionPlanBuilder.scala:136)
    at org.neo4j.cypher.internal.compiler.v2_0.executionplan.ExecutionPlanBuilder$$anonfun$3.apply(ExecutionPlanBuilder.scala:135)
    at org.neo4j.cypher.internal.compiler.v2_0.executionplan.ExecutionPlanBuilder$$anon$6.execute(ExecutionPlanBuilder.scala:50)
    at org.neo4j.cypher.internal.ExecutionPlanWrapperForV2_0.execute(CypherCompiler.scala:93)
    at org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:61)
    at org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:55)
    at org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:65)
    at net.ahm.graph.ConcurrDeleteLab$1.run(ConcurrDeleteLab.java:65)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744

Source code to simulate the issue:

package net.ahm.graph;

import java.io.File;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.cypher.javacompat.ExecutionResult;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.graphdb.schema.Schema;
import org.neo4j.kernel.impl.util.FileUtils;
import org.neo4j.kernel.impl.util.StringLogger;

public class ConcurrDeleteLab {
    private static final Logger LOG = Logger.getLogger(CypherLab.class);
    private final static int CONCURRENCY = 4;

    public static void main(String[] args) throws Exception {
        FileUtils.deleteRecursively(new File("graphdb"));
        final GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder("graphdb")
                .setConfig(GraphDatabaseSettings.use_memory_mapped_buffers, "true").setConfig(GraphDatabaseSettings.cache_type, "strong")
                .newGraphDatabase();
        registerShutdownHook(graphDb);
        LOG.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> NUMBER OF PARALLEL CYPHERS: " + CONCURRENCY);
        LOG.info(">>>> STARTED GRAPHDB");
        createIndex("Entity", "name", graphDb);
        try (Transaction tx = graphDb.beginTx()) {
            for (int i = 0; i < 100000; i++) {
                Node child = graphDb.createNode(DynamicLabel.label("Entity"));
                child.setProperty("name", "entity" + i);
            }
            tx.success();
        }
        LOG.info(">>>> CREATED NODES");
        final ExecutionEngine engine = new ExecutionEngine(graphDb, StringLogger.SYSTEM);
        for (int i = 0; i < 4; i++) {
            try (Transaction tx = graphDb.beginTx()) {
                ExecutionResult result = engine.execute("match (n:Entity) return n.name");
                for (Map<String, Object> row : result) {
                    assert ((String) row.get("n.name") != null);
                }
                tx.success();
            }
        }
        LOG.info(">>>> WARMED UP");
        ExecutorService es = Executors.newFixedThreadPool(CONCURRENCY);
        final CountDownLatch cdl = new CountDownLatch(CONCURRENCY);
        for (int i = 0; i < CONCURRENCY; i++) {
            if (i % 2 == 0) {
                es.execute(new Runnable() {
                    @Override
                    public void run() {
                        try (Transaction tx = graphDb.beginTx()) {
                            long time = System.currentTimeMillis();
                            engine.execute("match (n:Entity) delete n");
                            LOG.info(">>>> CYPHER TOOK: " + (System.currentTimeMillis() - time) + " m-secs");
                            tx.success();
                        } catch (Throwable t) {
                            LOG.error(t);
                            t.printStackTrace();
                        } finally {
                            cdl.countDown();
                        }
                    }
                });
            } else {
                es.execute(new Runnable() {
                    @Override
                    public void run() {
                        try (Transaction tx = graphDb.beginTx()) {
                            long time = System.currentTimeMillis();
                            ExecutionResult result = engine.execute("match (n:Entity) return n.name");
                            LOG.info(">>>> CYPHER TOOK: " + (System.currentTimeMillis() - time) + " m-secs");
                            int count = 0;
                            time = System.currentTimeMillis();
                            for (Map<String, Object> row : result) {
                                assert ((String) row.get("n.name") != null);
                                count++;
                            }
                            LOG.info(">>>> GETTING RESULTS TOOK: " + (System.currentTimeMillis() - time) + " m-secs");
                            tx.success();
                            LOG.info(">>>> CYPHER RETURNED ROWS: " + count);
                        } catch (Throwable t) {
                            LOG.error(t);
                            t.printStackTrace();
                        } finally {
                            cdl.countDown();
                        }
                    }
                });
            }
        }
        cdl.await();
        es.shutdown();
    }

    private static void createIndex(String label, String propertyName, GraphDatabaseService graphDb) {
        IndexDefinition indexDefinition;
        try (Transaction tx = graphDb.beginTx()) {
            Schema schema = graphDb.schema();
            indexDefinition = schema.indexFor(DynamicLabel.label(label)).on(propertyName).create();
            tx.success();
        }
        try (Transaction tx = graphDb.beginTx()) {
            Schema schema = graphDb.schema();
            schema.awaitIndexOnline(indexDefinition, 10, TimeUnit.SECONDS);
            tx.success();
        }
    }

    private static void registerShutdownHook(final GraphDatabaseService graphDb) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                LOG.info("### GRAPHDB SHUTDOWNHOOK INVOKED !!!");
                graphDb.shutdown();
            }
        });
    }

}

回答1:


It seems there is currently not a better option. This issue was reported here in 2012: https://github.com/neo4j/neo4j/issues/37



来源:https://stackoverflow.com/questions/21385630/how-to-handle-notfoundexception-elegantly-in-neo4j-2-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!