lib/good_job_connection_pool_size.rb
# frozen_string_literal: true
# This class provides a starting point to dynamically calculate the number of database connections
# needed for our multi-threaded GoodJob deployment. Each process will create
# a certain number of threads based on configuration in the environment.
# The calculations here are guided by https://github.com/bensheldon/good_job/blob/8e7ac0cd47c0382544d99a6e2d7ee2a3053b2490/README.md#database-connections
class GoodJobConnectionPoolSize
# Calculates the number of worker database connections the worker process needs.
def self.calculate_worker_pool_size(queues:, cron_enabled:, max_threads:)
# LISTEN/NOTIFY requires 1 connection
connections = 1
connections += num_explicit_threads_from_queues(queues: queues, max_threads: max_threads)
# Cron requires two connections
connections += 2 if cron_enabled
connections
end
# Calculates the number of primary database connections the worker process needs.
#
# Each worker thread may need a primary database connection. We may not strictly need
# one connection for each, but we will start there for safety.
def self.calculate_primary_pool_size(queues:, max_threads:)
num_explicit_threads_from_queues(queues: queues, max_threads: max_threads)
end
# The '*' queue will have up to `max_threads` threads. Other queues will use their explicitly
# defined thread pool size.
#
# Example: 'low:1;high:2;*' with 5 max_threads would have up to 8 total threads.
# Example: 'low:1;high:2' with 5 max_threads would have up to 3 total threads.
def self.num_explicit_threads_from_queues(queues:, max_threads:)
queues = queues.split(';')
threads = queues.map do |queue|
if queue != '*'
_name, size = queue.split(':')
Integer(size)
else
0
end
end.sum
threads += max_threads if queues.include?('*')
threads
end
end