Commit 825247ab authored by Thong Kuah's avatar Thong Kuah

Merge branch 'many-dbs-remove-multi-thrds-migrations' into 'master'

Remove unused `Gitlab::Database::MultiThreadedMigration`

See merge request gitlab-org/gitlab!67333
parents 6316a420 d593fe36
...@@ -488,47 +488,6 @@ like a standard migration invocation. ...@@ -488,47 +488,6 @@ like a standard migration invocation.
The migration might fail if there is a very long running transaction (40+ minutes) The migration might fail if there is a very long running transaction (40+ minutes)
accessing the `users` table. accessing the `users` table.
## Multi-Threading
Sometimes a migration might need to use multiple Ruby threads to speed up a
migration. For this to work your migration needs to include the module
`Gitlab::Database::MultiThreadedMigration`:
```ruby
class MyMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
include Gitlab::Database::MultiThreadedMigration
end
```
You can then use the method `with_multiple_threads` to perform work in separate
threads. For example:
```ruby
class MyMigration < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
include Gitlab::Database::MultiThreadedMigration
def up
with_multiple_threads(4) do
disable_statement_timeout
# ...
end
end
end
```
Here the call to `disable_statement_timeout` uses the connection local to
the `with_multiple_threads` block, instead of re-using the global connection
pool. This ensures each thread has its own connection object, and doesn't time
out when trying to obtain one.
PostgreSQL has a maximum amount of connections that it allows. This
limit can vary from installation to installation. As a result, it's recommended
you do not use more than 32 threads in a single migration. Usually, 4-8 threads
should be more than enough.
## Removing indexes ## Removing indexes
If the table is not empty when removing an index, make sure to use the method If the table is not empty when removing an index, make sure to use the method
......
# frozen_string_literal: true
module Gitlab
module Database
module MultiThreadedMigration
MULTI_THREAD_AR_CONNECTION = :thread_local_ar_connection
# This overwrites the default connection method so that every thread can
# use a thread-local connection, while still supporting all of Rails'
# migration methods.
def connection
Thread.current[MULTI_THREAD_AR_CONNECTION] ||
ActiveRecord::Base.connection
end
# Starts a thread-pool for N threads, along with N threads each using a
# single connection. The provided block is yielded from inside each
# thread.
#
# Example:
#
# with_multiple_threads(4) do
# execute('SELECT ...')
# end
#
# thread_count - The number of threads to start.
#
# join - When set to true this method will join the threads, blocking the
# caller until all threads have finished running.
#
# Returns an Array containing the started threads.
def with_multiple_threads(thread_count, join: true)
pool = Gitlab::Database.main.create_connection_pool(thread_count)
threads = Array.new(thread_count) do
Thread.new do
pool.with_connection do |connection|
Thread.current[MULTI_THREAD_AR_CONNECTION] = connection
yield
ensure
Thread.current[MULTI_THREAD_AR_CONNECTION] = nil
end
end
end
threads.each(&:join) if join
threads
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Database::MultiThreadedMigration do
let(:migration) do
Class.new { include Gitlab::Database::MultiThreadedMigration }.new
end
describe '#connection' do
after do
Thread.current[described_class::MULTI_THREAD_AR_CONNECTION] = nil
end
it 'returns the thread-local connection if present' do
Thread.current[described_class::MULTI_THREAD_AR_CONNECTION] = 10
expect(migration.connection).to eq(10)
end
it 'returns the global connection if no thread-local connection was set' do
expect(migration.connection).to eq(ActiveRecord::Base.connection)
end
end
describe '#with_multiple_threads' do
it 'starts multiple threads and yields the supplied block in every thread' do
output = Queue.new
migration.with_multiple_threads(2) do
output << migration.connection.execute('SELECT 1')
end
expect(output.size).to eq(2)
end
it 'joins the threads when the join parameter is set' do
expect_any_instance_of(Thread).to receive(:join).and_call_original
migration.with_multiple_threads(1) { }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment