在我的Rails应用程序中,我有一个控制器负责生成报告。其中一些报告需要很长时间才能生成,这超过了Heroku的30秒限制。在这种情况下,我希望在25秒后向用户显示通知,并取消数据库查询。我的初始想法是使用Timeout
。
class ReportsController < ApplicationController
def expensive_report
Timeout.timeout(25) do
@results = ExpensiveQuery.new(params).results
end
rescue Timeout::Error
render action: "timeout"
end
end
计时器正常工作,但相应的查询没有被取消。在 Rails 控制台中很容易重现此问题。
begin
Timeout.timeout(1) do
ActiveRecord::Base.connection.execute("SELECT pg_sleep(10)")
end
rescue Timeout::Error
puts "Timeout"
end
result = ActiveRecord::Base.connection.execute("SELECT 1 AS value")
puts result[0]["value"]
这段代码将输出“超时”,随后在
result = ActiveRecord::Base.connection.execute("SELECT 1 AS value")
这一行上阻塞,直至pg_sleep
查询结束。如何在Rails内部取消这样的查询?我正在Heroku上托管我的应用程序,因此权限受到限制,无法运行诸如
pg_cancel_backend
或pg_terminate_backend
的命令。