中止对 neo4jrb 的查询

Aborting queries on neo4jrb

我正在 运行 遵循以下思路:

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 继续尝试 运行 我的查询。我实际上想让它们超时,所以简单地增加超时 window 对我没有帮助。

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

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

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

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

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

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

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

中设置它
dbms.transaction.timeout=60s

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

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

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

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

Neo4jrb 不提供任何查询管理功能的包装器,因此简单地设置事务超时似乎是最明智的,并且可能是我将采用的方法。实际上拦截和杀死查询也是可能的,但这意味着 运行 在一个线程上执行查询,以便您可以在另一个线程中查找它的 queryId。这是我正在使用 atm 的有点老套的解决方案:

class QueryRunner
  DEFAULT_TIMEOUT=70

  def self.query(query, timeout_limit=DEFAULT_TIMEOUT)
    new(query, timeout_limit).run
  end

  def initialize(query, timeout_limit)
    @query = query
    @timeout_limit = timeout_limit
  end

  def run
    start_time = Time.now.to_i
    Thread.new { @result = Neo4j::Session.query(@query) }
    sleep 0.5

    return @result if @result

    id = if query_ref = Neo4j::Session.query("CALL dbms.listQueries;").to_a.find {|x| x.query == @query }
      query_ref.queryId
    end

    while @result.nil?
      if (Time.now.to_i - start_time) > @timeout_limit
        puts "killing query #{id} due to timeout"
        Neo4j::Session.query("CALL dbms.killQuery('#{id}');")
        @result = []
      else
        sleep 1
      end
    end
    @result
  end
end