Vert.x和Neo4j在多线程黄瓜环境中

时间:2012-07-17 09:41:49

标签: java cucumber jruby neo4j vert.x

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

在某些测试场景结束时,我想检查是否已将certian数据放入数据库库中。因为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;
    }
  }

}

此工厂应确保仅初始化每个path的实例。但是如果函数getOrCreateDatabase第二次访问,则内部数据库HashMap仍为空。这导致代码在同一数据上初始化第二个Neo4j实例,该实例失败并带有

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

它们都在同一个JVM中运行,但看起来,不同的线程已经分离了内存。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我花了一些时间来解决问题,最后找到了解决方案。

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

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