149 lines
3.9 KiB
Ruby
149 lines
3.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'erb'
|
|
require 'yaml'
|
|
|
|
RSpec.describe 'runtime scaling configuration' do
|
|
around do |example|
|
|
with_env(
|
|
'DATABASE_URL' => nil,
|
|
'POSTGRES_URL' => nil,
|
|
'PORT' => nil,
|
|
'RAILS_DB_POOL' => nil,
|
|
'RAILS_ENV' => nil,
|
|
'RAILS_MAX_THREADS' => nil,
|
|
'RAILS_MIN_THREADS' => nil,
|
|
'SIDEKIQ_CONCURRENCY' => nil,
|
|
'WEB_CONCURRENCY' => nil
|
|
) { example.run }
|
|
end
|
|
|
|
it 'configures Puma workers and threads from environment variables' do
|
|
with_env(
|
|
'PORT' => '4001',
|
|
'RAILS_ENV' => 'production',
|
|
'RAILS_MAX_THREADS' => '7',
|
|
'RAILS_MIN_THREADS' => '2',
|
|
'WEB_CONCURRENCY' => '4'
|
|
) do
|
|
config = evaluate_puma_config
|
|
|
|
expect(config.fetch(:threads)).to eq(%w[2 7])
|
|
expect(config.fetch(:workers)).to eq('4')
|
|
expect(config.fetch(:preload_app)).to be(true)
|
|
expect(config.fetch(:port)).to eq('4001')
|
|
expect(config.fetch(:environment)).to eq('production')
|
|
expect(config.fetch(:plugin)).to eq(:tmp_restart)
|
|
end
|
|
end
|
|
|
|
it 'uses safe Puma defaults' do
|
|
config = evaluate_puma_config
|
|
|
|
expect(config.fetch(:threads)).to eq([5, 5])
|
|
expect(config.fetch(:workers)).to eq(2)
|
|
expect(config.fetch(:port)).to eq(3000)
|
|
expect(config.fetch(:environment)).to eq('production')
|
|
end
|
|
|
|
it 'configures the production database pool from RAILS_DB_POOL' do
|
|
with_env(
|
|
'DATABASE_URL' => 'postgres://turniere:secret@postgres/turniere',
|
|
'RAILS_DB_POOL' => '9',
|
|
'RAILS_MAX_THREADS' => '7'
|
|
) do
|
|
config = database_config.fetch('production')
|
|
|
|
expect(config.fetch('adapter')).to eq('postgresql')
|
|
expect(config.fetch('encoding')).to eq('unicode')
|
|
expect(config.fetch('url')).to eq('postgres://turniere:secret@postgres/turniere')
|
|
expect(config.fetch('pool')).to eq(9)
|
|
end
|
|
end
|
|
|
|
it 'falls back to RAILS_MAX_THREADS for the database pool and POSTGRES_URL for legacy deployments' do
|
|
with_env(
|
|
'POSTGRES_URL' => 'postgres://turniere:secret@legacy-postgres/turniere',
|
|
'RAILS_MAX_THREADS' => '6'
|
|
) do
|
|
config = database_config.fetch('production')
|
|
|
|
expect(config.fetch('url')).to eq('postgres://turniere:secret@legacy-postgres/turniere')
|
|
expect(config.fetch('pool')).to eq(6)
|
|
end
|
|
end
|
|
|
|
it 'configures Sidekiq concurrency from SIDEKIQ_CONCURRENCY' do
|
|
with_env('SIDEKIQ_CONCURRENCY' => '10') do
|
|
expect(sidekiq_config).to include(':concurrency: 10')
|
|
end
|
|
|
|
expect(sidekiq_config).to include(':concurrency: 5')
|
|
end
|
|
|
|
def evaluate_puma_config
|
|
probe = puma_config_probe_class.new
|
|
probe.instance_eval(File.read(File.join(root, 'config/puma.rb')), File.join(root, 'config/puma.rb'))
|
|
probe.config
|
|
end
|
|
|
|
def database_config
|
|
YAML.safe_load(ERB.new(File.read(File.join(root, 'config/database.yml'))).result, aliases: true)
|
|
end
|
|
|
|
def sidekiq_config
|
|
ERB.new(File.read(File.join(root, 'config/sidekiq.yml'))).result
|
|
end
|
|
|
|
def with_env(values)
|
|
previous = values.to_h { |key, _value| [key, ENV.fetch(key, nil)] }
|
|
values.each do |key, value|
|
|
value.nil? ? ENV.delete(key) : ENV[key] = value
|
|
end
|
|
|
|
yield
|
|
ensure
|
|
previous.each do |key, value|
|
|
value.nil? ? ENV.delete(key) : ENV[key] = value
|
|
end
|
|
end
|
|
|
|
def root
|
|
File.expand_path('../..', __dir__)
|
|
end
|
|
|
|
def puma_config_probe_class
|
|
Class.new do
|
|
attr_reader :config
|
|
|
|
def initialize
|
|
@config = {}
|
|
end
|
|
|
|
def threads(min_threads, max_threads)
|
|
@config[:threads] = [min_threads, max_threads]
|
|
end
|
|
|
|
def workers(count)
|
|
@config[:workers] = count
|
|
end
|
|
|
|
def preload_app!
|
|
@config[:preload_app] = true
|
|
end
|
|
|
|
def port(value)
|
|
@config[:port] = value
|
|
end
|
|
|
|
def environment(value)
|
|
@config[:environment] = value
|
|
end
|
|
|
|
def plugin(name)
|
|
@config[:plugin] = name
|
|
end
|
|
end
|
|
end
|
|
end
|