update activerecord-pg-extensions

* moves with_statement_timeout into the gem
 * improves locking profile of change_column_null ..., false

Change-Id: I6973c6ea322ff29e3f7b2044d1650a9d0cb5afcb
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/273154
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jacob Burroughs <jburroughs@instructure.com>
QA-Review: Cody Cutrer <cody@instructure.com>
Product-Review: Cody Cutrer <cody@instructure.com>
This commit is contained in:
Cody Cutrer 2021-09-08 11:53:00 -06:00
parent a4cfe29325
commit 35ee9fc656
9 changed files with 12 additions and 52 deletions

View File

@ -39,7 +39,7 @@ gem 'academic_benchmarks', '1.1.1', require: false
gem 'active_model-better_errors', '1.6.7', require: 'active_model/better_errors'
gem 'active_model_serializers', '0.9.0alpha1',
github: 'rails-api/active_model_serializers', ref: '61882e1e4127facfe92e49057aec71edbe981829'
gem 'activerecord-pg-extensions', '0.2.3'
gem 'activerecord-pg-extensions', '0.3.0'
gem 'addressable', '2.7.0', require: false
gem 'after_transaction_commit', '2.2.2'
gem 'authlogic', '6.4.1'

View File

@ -741,23 +741,6 @@ class ActiveRecord::Base
end
changes_applied
end
def self.with_statement_timeout(timeout = 30_000)
raise ArgumentError.new("timeout must be an integer") unless timeout.is_a? Integer
transaction do
connection.execute "SET LOCAL statement_timeout = #{timeout}"
yield
rescue ActiveRecord::StatementInvalid => e
raise ActiveRecord::QueryTimeout if e.cause.is_a? PG::QueryCanceled
raise e
end
end
end
module ActiveRecord
class QueryTimeout < ActiveRecord::StatementInvalid; end
end
module UsefulFindInBatches

View File

@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
spec.add_dependency 'activerecord', '>= 3.2'
spec.add_dependency 'pg', '>= 0.17', '< 2.0'
spec.add_dependency 'activerecord-pg-extensions', '>= 0.3.0'
spec.add_development_dependency 'bundler', '~> 2.2'
spec.add_development_dependency 'rspec', '~> 3.5.0'

View File

@ -39,7 +39,7 @@ module CanvasPartman
attr_accessor :migrations_scope, :timeout_seconds
def timeout_value
timeout_seconds.call * 1000
timeout_seconds.call
end
end

View File

@ -19,6 +19,7 @@
require 'canvas_partman/partition_manager/by_date'
require 'canvas_partman/partition_manager/by_id'
require "active_record/pg_extensions"
module CanvasPartman
class PartitionManager
@ -118,12 +119,9 @@ SQL
drop_partition_table(partition_table)
end
def with_statement_timeout(timeout_override: nil)
def with_statement_timeout(timeout_override: nil, &block)
tv = timeout_override || ::CanvasPartman.timeout_value
base_class.transaction do
execute("SET LOCAL statement_timeout=#{tv}")
yield
end
base_class.connection.with_statement_timeout(tv.to_f, &block)
end
protected

View File

@ -208,7 +208,7 @@ describe CanvasPartman::PartitionManager do
pm.with_statement_timeout(timeout_override: 1) do
pm.send(:execute, "select pg_sleep(5)")
end
end.to raise_error(ActiveRecord::QueryCanceled)
end.to raise_error(ActiveRecord::QueryTimeout)
end
end
end

View File

@ -35,10 +35,14 @@ module CanvasPartmanTest
end
require 'active_record'
require 'rails/version'
require 'canvas_partman'
require 'uri'
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL', nil))
# we need to ensure this callback is called for active_record-pg_extensions,
# which isn't running because we're not using Rails to setup the database
ActiveRecord::PGExtensions::Railtie.run_initializers
require 'support/schema_helper'
require 'fixtures/zoo'
require 'fixtures/animal'

View File

@ -260,7 +260,7 @@ module Lti
# content migrations that directly or indirectly provided content to
# this course. From there we get the unique list of courses, ordering by
# which has the migration with the latest timestamp.
results = ActiveRecord::Base.with_statement_timeout do
results = Course.connection.with_statement_timeout do
Course.from("(WITH RECURSIVE all_contexts AS (
SELECT context_id, source_course_id
FROM #{ContentMigration.quoted_table_name}

View File

@ -501,32 +501,6 @@ module ActiveRecord
end
end
describe 'with_statement_timeout' do
it 'stops long-running queries' do
expect {
ActiveRecord::Base.with_statement_timeout(1_000) do
ActiveRecord::Base.connection.execute("SELECT pg_sleep(3)")
end
}.to raise_error(ActiveRecord::QueryTimeout)
end
it 'only accepts an integer timeout' do
expect {
ActiveRecord::Base.with_statement_timeout("1_000") do
ActiveRecord::Base.connection.execute("SELECT pg_sleep(3)")
end
}.to raise_error(ArgumentError)
end
it 're-raises other errors' do
expect {
ActiveRecord::Base.with_statement_timeout(1_000) do
ActiveRecord::Base.connection.execute("bad sql")
end
}.to raise_error(ActiveRecord::StatementInvalid)
end
end
end
describe ActiveRecord::Migration::CommandRecorder do