1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #40626 from jonathanhefner/executor-wrap-db-seeds

Wrap evaluation of db/seeds.rb with the executor
This commit is contained in:
Rafael França 2020-11-24 15:01:22 -05:00 committed by GitHub
commit 90fa01b4c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 76 deletions

View file

@ -12,7 +12,7 @@ module ActiveJob
# Rails.application.config.active_job.queue_adapter = :inline # Rails.application.config.active_job.queue_adapter = :inline
class InlineAdapter class InlineAdapter
def enqueue(job) #:nodoc: def enqueue(job) #:nodoc:
Thread.new { Base.execute(job.serialize) }.join Base.execute(job.serialize)
end end
def enqueue_at(*) #:nodoc: def enqueue_at(*) #:nodoc:

View file

@ -4,7 +4,6 @@ require "helper"
require "jobs/logging_job" require "jobs/logging_job"
require "jobs/hello_job" require "jobs/hello_job"
require "jobs/provider_jid_job" require "jobs/provider_jid_job"
require "jobs/thread_job"
require "active_support/core_ext/numeric/time" require "active_support/core_ext/numeric/time"
class QueuingTest < ActiveSupport::TestCase class QueuingTest < ActiveSupport::TestCase
@ -146,21 +145,4 @@ class QueuingTest < ActiveSupport::TestCase
assert job_executed "#{@id}.2" assert job_executed "#{@id}.2"
assert job_executed_at("#{@id}.2") < job_executed_at("#{@id}.1") assert job_executed_at("#{@id}.2") < job_executed_at("#{@id}.1")
end end
test "inline jobs run on separate threads" do
skip unless adapter_is?(:inline)
after_job_thread = Thread.new do
ThreadJob.latch.wait
assert_nil Thread.current[:job_ran]
assert ThreadJob.thread[:job_ran]
ThreadJob.test_latch.count_down
end
ThreadJob.perform_later
after_job_thread.join
assert_nil Thread.current[:job_ran]
end
end end

View file

@ -1,22 +0,0 @@
# frozen_string_literal: true
class ThreadJob < ActiveJob::Base
class << self
attr_accessor :thread
def latch
@latch ||= Concurrent::CountDownLatch.new
end
def test_latch
@test_latch ||= Concurrent::CountDownLatch.new
end
end
def perform
Thread.current[:job_ran] = true
self.class.thread = Thread.current
self.class.latch.count_down
self.class.test_latch.wait
end
end

View file

@ -2,6 +2,7 @@
require "rails/railtie" require "rails/railtie"
require "rails/engine/railties" require "rails/engine/railties"
require "active_support/callbacks"
require "active_support/core_ext/module/delegation" require "active_support/core_ext/module/delegation"
require "active_support/core_ext/object/try" require "active_support/core_ext/object/try"
require "pathname" require "pathname"
@ -422,6 +423,9 @@ module Rails
end end
end end
include ActiveSupport::Callbacks
define_callbacks :load_seed
delegate :middleware, :root, :paths, to: :config delegate :middleware, :root, :paths, to: :config
delegate :engine_name, :isolated?, to: :class delegate :engine_name, :isolated?, to: :class
@ -559,13 +563,7 @@ module Rails
# Blog::Engine.load_seed # Blog::Engine.load_seed
def load_seed def load_seed
seed_file = paths["db/seeds.rb"].existent.first seed_file = paths["db/seeds.rb"].existent.first
return unless seed_file run_callbacks(:load_seed) { load(seed_file) } if seed_file
if config.try(:active_job)&.queue_adapter == :async
with_inline_jobs { load(seed_file) }
else
load(seed_file)
end
end end
initializer :load_environment_config, before: :load_environment_hook, group: :all do initializer :load_environment_config, before: :load_environment_hook, group: :all do
@ -637,6 +635,12 @@ module Rails
end end
end end
initializer :wrap_executor_around_load_seed do |app|
self.class.set_callback(:load_seed, :around) do |engine, seeds_block|
app.executor.wrap(&seeds_block)
end
end
initializer :engines_blank_point do initializer :engines_blank_point do
# We need this initializer so all extra initializers added in engines are # We need this initializer so all extra initializers added in engines are
# consistently executed after all the initializers above across all engines. # consistently executed after all the initializers above across all engines.
@ -678,18 +682,6 @@ module Rails
end end
end end
def with_inline_jobs
queue_adapter = config.active_job.queue_adapter
ActiveSupport.on_load(:active_job) do
self.queue_adapter = :inline
end
yield
ensure
ActiveSupport.on_load(:active_job) do
self.queue_adapter = queue_adapter
end
end
def has_migrations? def has_migrations?
paths["db/migrate"].existent.any? paths["db/migrate"].existent.any?
end end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "rails/initializable" require "rails/initializable"
require "active_support/descendants_tracker"
require "active_support/inflector" require "active_support/inflector"
require "active_support/core_ext/module/introspection" require "active_support/core_ext/module/introspection"
require "active_support/core_ext/module/delegation" require "active_support/core_ext/module/delegation"
@ -135,6 +136,7 @@ module Rails
class Railtie class Railtie
autoload :Configuration, "rails/railtie/configuration" autoload :Configuration, "rails/railtie/configuration"
extend ActiveSupport::DescendantsTracker
include Initializable include Initializable
ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application) ABSTRACT_RAILTIES = %w(Rails::Railtie Rails::Engine Rails::Application)
@ -144,13 +146,7 @@ module Rails
delegate :config, to: :instance delegate :config, to: :instance
def subclasses def subclasses
@subclasses ||= [] super.reject(&:abstract_railtie?)
end
def inherited(base)
unless base.abstract_railtie?
subclasses << base
end
end end
def rake_tasks(&blk) def rake_tasks(&blk)

View file

@ -879,29 +879,40 @@ en:
assert Bukkits::Engine.config.bukkits_seeds_loaded assert Bukkits::Engine.config.bukkits_seeds_loaded
end end
test "jobs are ran inline while loading seeds with async adapter configured" do test "loading seed data is wrapped by the executor" do
app_file "db/seeds.rb", <<-RUBY app_file "db/seeds.rb", <<-RUBY
Rails.application.config.seed_queue_adapter = ActiveJob::Base.queue_adapter Rails.application.config.seeding_wrapped_by_executor = Rails.application.executor.active?
RUBY RUBY
boot_rails boot_rails
Rails.application.load_seed Rails.application.load_seed
assert_instance_of ActiveJob::QueueAdapters::InlineAdapter, Rails.application.config.seed_queue_adapter assert_predicate Rails.application.config, :seeding_wrapped_by_executor
assert_instance_of ActiveJob::QueueAdapters::AsyncAdapter, ActiveJob::Base.queue_adapter
end end
test "jobs are ran with original adapter while loading seeds with custom adapter configured" do test "inline jobs do not clear CurrentAttributes when loading seed data" do
app_file "db/seeds.rb", <<-RUBY app_file "db/seeds.rb", <<-RUBY
Rails.application.config.seed_queue_adapter = ActiveJob::Base.queue_adapter class SeedsAttributes < ActiveSupport::CurrentAttributes
attribute :foo
end
class SeedsJob < ActiveJob::Base
self.queue_adapter = :inline
def perform
Rails.application.config.seeds_job_ran = true
end
end
SeedsAttributes.foo = 42
SeedsJob.perform_later
Rails.application.config.seeds_attributes_foo = SeedsAttributes.foo
RUBY RUBY
boot_rails boot_rails
Rails.application.config.active_job.queue_adapter = :delayed_job
Rails.application.load_seed Rails.application.load_seed
assert_instance_of ActiveJob::QueueAdapters::DelayedJobAdapter, Rails.application.config.seed_queue_adapter assert Rails.application.config.seeds_job_ran
assert_instance_of ActiveJob::QueueAdapters::DelayedJobAdapter, ActiveJob::Base.queue_adapter assert_equal 42, Rails.application.config.seeds_attributes_foo
end end
test "seed data can be loaded when ActiveJob is not present" do test "seed data can be loaded when ActiveJob is not present" do