mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Increment @counter of prepared postgres statements prior to running the query.
If the next query or the prepared statement itself get interrupted, this prevents the database session getting stuck perpetually retrying to recreate the same prepared statement.
This commit is contained in:
parent
56ea638290
commit
2416da9975
3 changed files with 25 additions and 5 deletions
|
@ -1,3 +1,9 @@
|
|||
* Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
|
||||
without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
|
||||
up in perpetual crash state for being inconsistent with Postgres.
|
||||
|
||||
*wbharding*, *Martin Tepper*
|
||||
|
||||
* Switch to database adapter return type for `ActiveRecord::Calculations.calculate`
|
||||
when called with `:average` (aliased as `ActiveRecord::Calculations.average`)
|
||||
|
||||
|
|
|
@ -228,11 +228,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def next_key
|
||||
"a#{@counter + 1}"
|
||||
end
|
||||
|
||||
def []=(sql, key)
|
||||
super.tap { @counter += 1 }
|
||||
"a#{@counter += 1}"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "cases/helper"
|
||||
require "models/computer"
|
||||
require "models/developer"
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
|
@ -16,6 +18,8 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
class StatementPoolTest < ActiveRecord::PostgreSQLTestCase
|
||||
fixtures :developers
|
||||
|
||||
if Process.respond_to?(:fork)
|
||||
def test_cache_is_per_pid
|
||||
cache = StatementPool.new nil, 10
|
||||
|
@ -37,6 +41,20 @@ module ActiveRecord
|
|||
cache["foo"] = "bar"
|
||||
assert_nothing_raised { cache.clear }
|
||||
end
|
||||
|
||||
def test_prepared_statements_do_not_get_stuck_on_query_interruption
|
||||
pg_connection = ActiveRecord::Base.connection.instance_variable_get(:@connection)
|
||||
pg_connection.stub(:get_last_result, -> { raise "random error" }) do
|
||||
assert_raises(RuntimeError) do
|
||||
Developer.where(name: "David").last
|
||||
end
|
||||
|
||||
# without fix, this raises PG::DuplicatePstatement: ERROR: prepared statement "a3" already exists
|
||||
assert_raises(RuntimeError) do
|
||||
Developer.where(name: "David").last
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue