FIX: Thread safety issues with `multisite:migrate` and `SeedFu`.

This commit is contained in:
Guo Xiang Tan 2020-06-17 16:15:43 +08:00
parent 86b43c5329
commit 45eb97c202
No known key found for this signature in database
GPG Key ID: FBD110179AAC1F20
2 changed files with 59 additions and 33 deletions

View File

@ -1,8 +1,19 @@
# frozen_string_literal: true
# fix any bust caches post initial migration
ActiveRecord::Base.connection.tables.each do |table|
table.classify.constantize.reset_column_information rescue nil
class SeedData::Refresher
def self.refresh!
return if @refreshed
# Fix any bust caches post initial migration
# Not that reset_column_information is not thread safe so we have to becareful
# not to run it concurrently within the same process.
ActiveRecord::Base.connection.tables.each do |table|
table.classify.constantize.reset_column_information rescue nil
end
@refreshed = true
end
end
SeedData::Refresher.refresh!
SiteSetting.refresh!

View File

@ -107,48 +107,63 @@ task 'multisite:migrate' => ['db:load_config', 'environment', 'set_locale'] do |
puts "Multisite migrator is running using #{concurrency} threads"
puts
queue = Queue.new
exceptions = Queue.new
old_stdout = $stdout
$stdout = StdOutDemux.new($stdout)
RailsMultisite::ConnectionManagement.each_connection do |db|
queue << db
end
concurrency.times { queue << :done }
SeedFu.quiet = true
(1..concurrency).map do
Thread.new {
while true
db = queue.pop
break if db == :done
def execute_concurently(concurrency)
queue = Queue.new
RailsMultisite::ConnectionManagement.with_connection(db) do
begin
puts "Migrating #{db}"
ActiveRecord::Tasks::DatabaseTasks.migrate
SeedFu.seed(DiscoursePluginRegistry.seed_paths)
if !Discourse.skip_post_deployment_migrations? && ENV['SKIP_OPTIMIZE_ICONS'] != '1'
SiteIconManager.ensure_optimized!
end
rescue => e
exceptions << [db, e]
ensure
RailsMultisite::ConnectionManagement.each_connection do |db|
queue << db
end
concurrency.times { queue << :done }
(1..concurrency).map do
Thread.new {
while true
db = queue.pop
break if db == :done
RailsMultisite::ConnectionManagement.with_connection(db) do
begin
$stdout.finish_chunk
rescue => ex
STDERR.puts ex.inspect
STDERR.puts ex.backtrace
yield(db) if block_given?
rescue => e
exceptions << [db, e]
ensure
begin
$stdout.finish_chunk
rescue => ex
STDERR.puts ex.inspect
STDERR.puts ex.backtrace
end
end
end
end
end
}
end.each(&:join)
}
end.each(&:join)
end
execute_concurently(concurrency) do |db|
puts "Migrating #{db}"
ActiveRecord::Tasks::DatabaseTasks.migrate
if !Discourse.skip_post_deployment_migrations? && ENV['SKIP_OPTIMIZE_ICONS'] != '1'
SiteIconManager.ensure_optimized!
end
end
seed_paths = DiscoursePluginRegistry.seed_paths
SeedFu.seed(seed_paths, /001_refresh/)
execute_concurently(concurrency) do |db|
puts "Seeding #{db}"
SeedFu.seed(seed_paths)
end
$stdout = old_stdout