我尝试在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中运行,但看起来,不同的线程已经分离了内存。
我在这里做错了什么?
答案 0 :(得分:0)
你确定你只是从所有线程运行一个neo4j实例吗?否则,几个neo4j实例将锁定存储文件。 Neo4j是线程安全的,但是没有在同一个商店中执行多个嵌入式实例,为了进行扩展,您使用高可用性设置,请参阅http://docs.neo4j.org/chunked/snapshot/ha.html
答案 1 :(得分:0)
我花了一些时间来解决问题,最后找到了解决方案。
Vert.x中的Verticle创建严格隔离的环境。这导致我的工厂的第二个版本(参见上面的代码)被初始化。第二家工厂试图初始化第二个Neo4j实例。
解决方案是将Neo4j代码分离为专用存储Verticle并编写通过事件总线访问该Verticle的测试代码。