Draft: Restore statement_timeout instead of RESET at the remaining sites
What does this MR do and why?
RESET statement_timeout restores the cluster default from postgresql.conf, not the value that config/database.yml sets with variables:. The cluster default is usually 0. So every SET statement_timeout ... / ensure RESET statement_timeout block left the connection with no statement timeout after it finished.
!257270 (merged) fixed this inline for lib/gitlab/database/sync_sequences_with_table_data.rb. Its reviewer pointed out the same pattern exists elsewhere. This MR is the follow-up.
It adds Gitlab::Database::StatementTimeout (lib/gitlab/database/statement_timeout.rb), with .current, .set, .disable, .restore. It has the same shape as the existing Gitlab::Database::TransactionTimeout. .current reads SHOW statement_timeout, and .restore writes that exact value back with SET.
It replaces the inline SET/RESET in five places:
lib/gitlab/database/reindexing/reindex_concurrently.rblib/gitlab/database/async_indexes/index_creator.rblib/gitlab/database/async_constraints/validators/base.rblib/gitlab/pool_repositories/orphaned_discoverer.rblib/gitlab/database/sync_sequences_with_table_data.rb(now uses the module instead of its own inlineSHOW/SETfrom the parent MR)
One behavior change: orphaned_discoverer.rb did not raise transaction_timeout alongside statement_timeout before. It now does, like the other sites. Its timeout constant also changed from the string '5min' to 5.minutes, so the SQL now reads '300s' instead of '5min'.
Each changed spec sets statement_timeout to 15s before running the code, and checks it is still 15s afterwards, including when the wrapped code raises.
The same fix is applied to the remaining sites:
- the
disable_statement_timeoutblock form inlib/gitlab/database/migrations/timeout_helpers.rb(used by migrations and by the CollationChecker and RepairIndex rake tasks), for bothstatement_timeoutandtransaction_timeout lib/gitlab/seeder.rb, which saves and restores the values per database connection- the
dev:setuptask inlib/tasks/dev.rake lib/gitlab/database/migrations/prepared_async_dml_operations_testing/index_creator.rbruns inside a transaction, so it now usesSET LOCALand needs no reset at all
Spec cleanups that used RESET statement_timeout now restore the original value too, so a spec file can no longer leak a disabled timeout into the files that run after it.
This MR is branched from and targets the branch of !257270 (merged). After that MR merges, this MR will be retargeted to master.
Resolves #630538
References
How to set up and validate locally
Save as repro.rb and run with RAILS_ENV=test bin/rails runner repro.rb:
connection = ApplicationRecord.connection
puts "before: #{connection.select_value('SHOW statement_timeout')}"
index = Gitlab::Database::PostgresIndex.by_identifier('public.index_users_on_username')
Gitlab::Database::Reindexing::ReindexConcurrently.new(index, logger: Logger.new(nil)).perform
puts "after: #{connection.select_value('SHOW statement_timeout')}"On the parent branch, the after line prints 0. On this branch, both lines print 2min.