Kill all PostgreSQL connections for rake dev:setup
If there are any clients connected to the DB, PostgreSQL won't let you drop the database. It's possible that Sidekiq, Unicorn, or some other client will be hanging onto a connection, preventing the DROP DATABASE from working. To workaround this problem, this method cancels all the connections so that the db:reset command will work. Note that there's still a slight possibility a client connects after its connection is terminated. If this is an issue, we could solve it by revoking CONNECT access, but for now it seems this works. Closes https://gitlab.com/gitlab-org/gitlab-development-kit/issues/450
This commit is contained in:
		
							parent
							
								
									91b88e0be4
								
							
						
					
					
						commit
						5488e8a4a3
					
				|  | @ -235,6 +235,28 @@ module Gitlab | |||
|       connection.schema_cache.data_source_exists?(table_name) | ||||
|     end | ||||
| 
 | ||||
|     # WARNING: Only run this if you know what you're doing. | ||||
|     # | ||||
|     # If there are any clients connected to the DB, PostgreSQL won't let | ||||
|     # you drop the database. It's possible that Sidekiq, Unicorn, or | ||||
|     # some other client will be hanging onto a connection, preventing | ||||
|     # the DROP DATABASE from working. To workaround this problem, this | ||||
|     # method terminates all the connections so that a subsequent DROP | ||||
|     # will work. | ||||
|     def self.terminate_all_connections | ||||
|       return false unless Gitlab::Database.postgresql? | ||||
| 
 | ||||
|       cmd = <<~SQL | ||||
|         SELECT pg_terminate_backend(pg_stat_activity.pid) | ||||
|         FROM pg_stat_activity | ||||
|         WHERE datname = current_database() | ||||
|         AND pid <> pg_backend_pid(); | ||||
|       SQL | ||||
| 
 | ||||
|       connection.execute(cmd)&.result_status == PG::PGRES_TUPLES_OK | ||||
|     rescue ActiveRecord::NoDatabaseError | ||||
|     end | ||||
| 
 | ||||
|     private_class_method :connection | ||||
| 
 | ||||
|     def self.database_version | ||||
|  |  | |||
|  | @ -25,6 +25,11 @@ namespace :gitlab do | |||
|       puts "" | ||||
|     end | ||||
| 
 | ||||
|     # In production, we might want to prevent ourselves from shooting | ||||
|     # ourselves in the foot, so let's only do this in a test or | ||||
|     # development environment. | ||||
|     Gitlab::Database.terminate_all_connections unless Rails.env.production? | ||||
| 
 | ||||
|     Rake::Task["db:reset"].invoke | ||||
|     Rake::Task["add_limits_mysql"].invoke | ||||
|     Rake::Task["setup_postgresql"].invoke | ||||
|  |  | |||
|  | @ -410,6 +410,18 @@ describe Gitlab::Database do | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '.terminate_all_connections' do | ||||
|     it 'returns true for PostgreSQL', :postgresql do | ||||
|       expect(described_class.terminate_all_connections).to be_truthy | ||||
|     end | ||||
| 
 | ||||
|     it 'returns false for MySQL' do | ||||
|       expect(described_class).to receive(:postgresql?).and_return(false) | ||||
| 
 | ||||
|       expect(described_class.terminate_all_connections).to be_falsey | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe '#true_value' do | ||||
|     it 'returns correct value for PostgreSQL' do | ||||
|       expect(described_class).to receive(:postgresql?).and_return(true) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue