中止对neo4jrb的查询

时间:2018-04-12 19:50:23

标签: ruby neo4j neo4j.rb

我正在按照以下方式运行:

results = queries.map do |query|
  begin
    Neo4j::Session.query(query)
  rescue Faraday::TimeoutError
    nil
  end
end

经过几次迭代后,我得到一个未知的Faraday::TimeoutError: too many connection resets (due to Net::ReadTimeout - Net::ReadTimeout),Neo4j需要关闭再打开。

我相信这是因为查询本身没有中止 - 即连接超时但是Neo4j继续尝试运行我的查询。我实际上想要将它们计时,所以简单地增加超时窗口对我没有帮助。

我有一个侦察员,看起来我可以找到我的查询并通过Neo4j API中止它们,这将是我的下一步行动。

我的诊断是对的吗?如果是这样,是否有推荐的方法从neo4jrb管理查询(并中止它们)?

3 个答案:

答案 0 :(得分:1)

查询管理可以通过Cypher完成。您必须是管理员用户。

要列出所有查询,您可以使用CALL dbms.listQueries;

要终止查询,您可以使用CALL dbms.killQuery('ID-OF-QUERY-TO-KILL');,其中ID是从查询列表中获取的。

以前的语句必须作为原始查询执行;只要您可以手动输入查询,是否使用OGM并不重要。如果无法手动输入查询,并且无法在框架中执行此操作,则必须使用其他方法访问数据库才能执行查询。

答案 1 :(得分:1)

Rebecca对于手动管理查询是正确的。虽然如果您希望Neo4j在特定时间段内自动停止查询,您可以在neo4j conf中设置:

dbms.transaction.timeout=60s

您可以在the docs中找到有关该设置的更多信息。

Ruby gem正在使用Faraday通过HTTP连接到Neo4j,而Faraday有一个内置的超时,它与Neo4j中的超时不同。我建议将Neo4j超时设置为比Ruby中的更长(可能是5-10秒)(here是配置法拉第超时的文档)。如果它们都具有相同的超时,Neo4j可能会在Ruby之前引发超时,从而产生不太明显的错误。

答案 2 :(得分:0)

感谢Brian和Rebecca在Neo4j中提供有关查询管理的有用提示。这两个都为我的问题提供了可行的解决方案,并且Brian明确规定了通过Neo4jrb实现一个解决方案的步骤,因此我将其标记为正确。

正如两个答案所假设的那样,我做出的诊断是正确的 - 即如果你从Neo4jrb运行查询并且HTTP连接超时,Neo4j将继续执行查询,Neo4jrb将不会发出任何指令让它停止。 / p>

Neo4jrb没有为任何查询管理功能提供包装器,因此简单地设置事务超时似乎是最明智的,也可能是我采用的。实际上拦截和查杀查询也是可能的,但这意味着在一个线程上运行查询,以便您可以在另一个线程中查找其queryId。这是我与atm合作的有点愚蠢的解决方案:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "OnlyActionToHomeController",
            url: "{action}",
            defaults: new { controller = "Home" },
            constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

public class NoConflictingControllerExists : IRouteConstraint
{
    private static readonly Dictionary<string, bool> _cache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var path = httpContext.Request.Path;

        if (path == "/" || String.IsNullOrEmpty(path))
            return false;

        if (_cache.ContainsKey(path))
            return _cache[path];

        IController ctrl;

        try
        {
            var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
            ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
        }
        catch
        {
            _cache.Add(path, true);
            return true;
        }

        var res = ctrl == null;
        _cache.Add(path, res);

        return res;
    }
}