Module: Crspec::Rails::Parallel

Defined in:
lib/crspec/rails/parallel.rb

Constant Summary collapse

WORKER_NUMBER_KEY =
:crspec_worker_number

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.enabledObject

Returns the value of attribute enabled.



13
14
15
# File 'lib/crspec/rails/parallel.rb', line 13

def enabled
  @enabled
end

.setup_blocksObject

Returns the value of attribute setup_blocks.



13
14
15
# File 'lib/crspec/rails/parallel.rb', line 13

def setup_blocks
  @setup_blocks
end

.teardown_blocksObject

Returns the value of attribute teardown_blocks.



13
14
15
# File 'lib/crspec/rails/parallel.rb', line 13

def teardown_blocks
  @teardown_blocks
end

.worker_countObject

Returns the value of attribute worker_count.



13
14
15
# File 'lib/crspec/rails/parallel.rb', line 13

def worker_count
  @worker_count
end

Class Method Details

.current_worker_numberObject



66
67
68
# File 'lib/crspec/rails/parallel.rb', line 66

def current_worker_number
  Fiber[WORKER_NUMBER_KEY]
end

.enabled?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/crspec/rails/parallel.rb', line 41

def enabled?
  !!@enabled
end

.parallelize(workers: :number_of_processors, &block) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/crspec/rails/parallel.rb', line 15

def parallelize(workers: :number_of_processors, &block)
  # For Rails test environments it is often safer to run without
  # process-level parallelism unless the application explicitly opts
  # in. This avoids issues with shared transactional fixtures and
  # global state.
  if defined?(::Rails) && ::Rails.respond_to?(:env) && ::Rails.env.test?
    workers = 1 if workers == :number_of_processors
  end
  count = case workers
          when :number_of_processors
            Etc.nprocessors
          when Integer
            workers
          else
            Etc.nprocessors
          end
  @worker_count = count
  @enabled = true
  @setup_blocks ||= []
  @teardown_blocks ||= []

  return unless block

  instance_eval(&block)
end

.parallelize_setup(&block) ⇒ Object



45
46
47
48
# File 'lib/crspec/rails/parallel.rb', line 45

def parallelize_setup(&block)
  @setup_blocks ||= []
  @setup_blocks << block
end

.parallelize_teardown(&block) ⇒ Object



50
51
52
53
# File 'lib/crspec/rails/parallel.rb', line 50

def parallelize_teardown(&block)
  @teardown_blocks ||= []
  @teardown_blocks << block
end

.reset!Object



89
90
91
92
93
94
# File 'lib/crspec/rails/parallel.rb', line 89

def reset!
  @enabled = false
  @worker_count = nil
  @setup_blocks = []
  @teardown_blocks = []
end

.setup_worker(worker_number) ⇒ Object

Worker identity lives in Fiber Storage (inherited by fibers spawned within the worker), never in ENV: mutating ENV from worker threads is a process-wide race. Per-worker databases move to the process tier (--processes), where the ENV convention is safe to set once per child process before any threads start.



61
62
63
64
# File 'lib/crspec/rails/parallel.rb', line 61

def setup_worker(worker_number)
  Fiber[WORKER_NUMBER_KEY] = worker_number
  @setup_blocks&.each { |b| b.call(worker_number) }
end

.teardown_worker(worker_number) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/crspec/rails/parallel.rb', line 76

def teardown_worker(worker_number)
  @teardown_blocks&.each { |b| b.call(worker_number) }
  Fiber[WORKER_NUMBER_KEY] = nil

  return unless defined?(ActiveRecord::Base) && ActiveRecord::Base.respond_to?(:connection_handler)

  begin
    ActiveRecord::Base.connection_handler.clear_active_connections!
  rescue StandardError
    nil
  end
end

.test_env_number(worker_number = current_worker_number) ⇒ Object



70
71
72
73
74
# File 'lib/crspec/rails/parallel.rb', line 70

def test_env_number(worker_number = current_worker_number)
  return "" if worker_number.nil? || worker_number == 1

  worker_number.to_s
end