Для моего приложения в приложении rails время ожидания оператора postgres установлено на 5 секунд. Этот тайм-аут хорошо работает для нас, помогает нам обнаруживать ошибки в работе, убивать ошибочные запросы и т. Д. c. Однако, когда мы внедряем изменение, нам иногда хочется запустить миграцию данных, которая занимает более 5 секунд и часто приводит к жестокой PG::QueryCanceled: ERROR: canceling statement due to statement timeout
. Следовательно, мы ищем способ увеличить время ожидания заявления до ~ 10 минут для наших миграций. Каков наилучший способ сделать это?
Вот варианты, которые мы рассмотрели, и почему мы не довольны ни одним из них.
1) Увеличьте время ожидания утверждения в каждой отдельной миграции Вы думаете, может быть проблематично c. -> Часто разработчики забывают или имеют плохие оценки того, сколько времени это займет. Если они ошибаются, мы заканчиваем неудачным развертыванием, вишневым выбором, и т. Д. c.
2) Используйте Task.enhance для db:migrate
(или другие методы), чтобы увеличить время ожидания оператора перед каждой задачей. -> Можно просто увеличить время ожидания оператора с помощью ActiveRecord::Base.connection.execute 'SET statement_timeout = 600000'
, но это будет применяться только к существующему соединению. Оказывается, когда вы запускаете rake db:migrate
, ActiveRecord
фактически открывает новое соединение с БД, которое возвращается к существующему по умолчанию.
3) Обезьяна исправляет фактический метод переноса, чтобы установить время ожидания оператора ПОСЛЕ соединения создано. -> Посмотрите код ниже, это не красиво и возиться с внутренними функциями ActiveRecord может иметь последствия, о которых мы не знаем.
* Примечание: Если вы используете гем
перенос данных , вам также необходимо указать следующее.
# Override when we are running with the data migrate gem (which we do in prod)
# https://github.com/ilyakatz/data-migrate/blob/4db2dba7d53e73cac06aa9bfab136c10aa38367b/tasks/databases.rake#L9
module OverrideDataMigrateMigration
def self.included base
orig_method = base.method(:run)
base.define_singleton_method :run do |*args|
puts '-- SET statement_timeout = 600000'
ActiveRecord::Base.connection.execute 'SET statement_timeout = 600000' # 10 minutes should suffice, right?
orig_method.call *args
end
end
end
DataMigrate::DataMigrator.send(:include, OverrideDataMigrateMigration)
DataMigrate::SchemaMigration.send(:include, OverrideDataMigrateMigration)