0

我尝试在 JRuby 环境中运行黄瓜测试。我将 cucumber rake 任务配置为在另一个线程中但在同一个 JVM 中启动嵌入式 Vert.x 应用程序服务器。在应用程序启动期间,会初始化 Neo4j 的嵌入式实例。所以最后,Cucumber、Vert.x 和 Neo4j 都在同一个 JVM 中运行(tada!)。

在一些测试场景结束时,我想检查某些数据是否已放入数据库库中。而且由于 Neo4j 文档说...

EmbeddedGraphDatabase 实例可以在多个线程之间共享。但是请注意,您不能创建指向同一个数据库的多个实例。

...我尝试获取已经初始化的 Neo4j 实例并将其用于这些检查。为了实现这一点,我编写了以下工厂。

public class ConcurrentGraphDatabaseFactory {

  private static HashMap<String, GraphDatabaseService> databases = new HashMap<String, GraphDatabaseService>();

  public static synchronized GraphDatabaseService getOrCreateDatabase(String path, String autoIndexFields) {
    System.out.println("databases: " + databases.toString());
    if (databases.containsKey(path)) {
      return databases.get(path);
    } else {
      final GraphDatabaseService database = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(path).
        setConfig(GraphDatabaseSettings.node_keys_indexable, autoIndexFields).
        setConfig(GraphDatabaseSettings.node_auto_indexing, GraphDatabaseSetting.TRUE).
        newGraphDatabase();

      Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
          database.shutdown();
        }
      });

      databases.put(path, database);
      return database;
    }
  }

}

该工厂应确保仅对实例 perpath进行初始化。但是如果getOrCreateDatabase第二次访问该函数,内部数据库HashMap仍然是空的。这会导致代码在相同数据上初始化第二个 Neo4j 实例,但失败并显示

NativeException: java.lang.IllegalStateException: Unable to lock store

它都在同一个 JVM 中运行,但似乎不同的线程具有分离的内存。

我在这里做错了什么?

4

2 回答 2

0

你确定你只从所有线程运行一个 neo4j 实例吗?否则,几个 neo4j 实例将争夺锁定存储文件。Neo4j 是线程安全的,但不在同一个存储中执行多个嵌入式实例,为了扩展它,您使用高可用性设置,请参阅http://docs.neo4j.org/chunked/snapshot/ha.html

于 2012-07-17T15:47:33.133 回答
0

我花了一些时间解决这个问题,终于找到了解决方案。

Vert.x 中的 Verticle 创建了严格隔离的环境。这会导致我的工厂的第二个版本(参见上面的代码)被初始化。第二个工厂尝试初始化第二个 Neo4j 实例。

解决方案是将 Neo4j 代码分离到一个专用存储 Verticle 中,并编写通过事件总线访问该 Verticle 的测试代码。

于 2012-07-26T08:25:09.820 回答