class Knockoff::Config

Attributes

environment[R]

The current environment. Normally set to Rails.env, but will default to 'development' outside of Rails apps.

replica_configs[R]

An array of configs to use for the replica pool.

replicas_configurations[R]

A hash of replica configs to their config hash.

Public Class Methods

new() click to toggle source
# File lib/knockoff/config.rb, line 13
def initialize
  @environment = 'development'
  @replicas_configurations = {}
  set_replica_configs

  if !properly_configured? && Knockoff.enabled
    puts "[Knockoff] WARNING: Detected enabled Knockoff without proper replica pool configuration. Setting Knockoff.enabled to false."
    Knockoff.enabled = false
  end
end

Public Instance Methods

properly_configured?() click to toggle source

If replica_configs actually containts some configuration information, then we know it was properly configured. Improper URI's will be ignored during the initialization step.

# File lib/knockoff/config.rb, line 46
def properly_configured?
  !@replica_configs.empty?
end
replica_database_keys() click to toggle source
# File lib/knockoff/config.rb, line 24
def replica_database_keys
  @replicas_configurations.keys
end
replica_env_keys() click to toggle source
# File lib/knockoff/config.rb, line 28
def replica_env_keys
  if ENV['KNOCKOFF_REPLICA_ENVS'].nil?
    []
  else
    ENV['KNOCKOFF_REPLICA_ENVS'].split(',').map(&:strip)
  end
end
update_replica_configs(new_configs) click to toggle source
# File lib/knockoff/config.rb, line 36
def update_replica_configs(new_configs)
  ActiveRecord::Base.configurations['knockoff_replicas'].merge(new_configs) if ActiveRecord::Base.configurations['knockoff_replicas'].present?
  @replicas_configurations.each do |key, _config|
    update_replica_config(key, new_configs)
  end
end

Private Instance Methods

parse_knockoff_replica_envs_to_configs() click to toggle source
# File lib/knockoff/config.rb, line 61
def parse_knockoff_replica_envs_to_configs
  # As a basic prevention of crashes, attempt to parse each DB uri
  # and don't add the uri to the final list if it can't be parsed
  replica_env_keys.map.with_index(0) do |env_key, index|
    begin
      uri = URI.parse(ENV[env_key])

      # Configure parameters such as prepared_statements, pool, reaping_frequency for all replicas.
      replica_config = ActiveRecord::Base.configurations['knockoff_replicas'] || {}

      adapter =
        if uri.scheme == "postgres"
          'postgresql'
        else
          uri.scheme
        end

      # Base config from the ENV uri. Sqlite is a special case
      # and all others follow 'normal' config
      uri_config =
        if uri.scheme == 'sqlite3'
          {
            'adapter' => adapter,
            'database' => uri.to_s.split(':')[1]
          }
        else
          {
            'adapter' => adapter,
            'database' => (uri.path || "").split("/")[1],
            'username' => uri.user,
            'password' => uri.password,
            'host' => uri.host,
            'port' => uri.port
          }
        end

      # Store the hash in configuration and use it when we establish the connection later.
      key = "knockoff_replica_#{index}"
      config = replica_config.merge(uri_config)

      if ActiveRecord::VERSION::MAJOR >= 6
        full_config = ActiveRecord::Base.configurations.to_h.merge(key => config)

        ActiveRecord::Base.configurations = full_config
        @replicas_configurations[key] = config
      else
        ActiveRecord::Base.configurations[key] = config
        @replicas_configurations[key] = config
      end
    rescue URI::InvalidURIError
      Rails.logger.info "LOG NOTIFIER: Invalid URL specified in follower_env_keys. Not including URI, which may result in no followers used." # URI is purposely not printed to logs
      # Return a 'nil' which will be removed from
      # configs with `compact`, resulting in no configs and no followers,
      # therefore disabled since this env will not be in environments list.
      nil
    end
  end.compact
end
set_replica_configs() click to toggle source
# File lib/knockoff/config.rb, line 57
def set_replica_configs
  @replica_configs ||= parse_knockoff_replica_envs_to_configs
end
update_replica_config(key, new_configs) click to toggle source
# File lib/knockoff/config.rb, line 52
def update_replica_config(key, new_configs)
  @replicas_configurations[key].merge!(new_configs)
  ActiveRecord::Base.configurations[key].merge!(new_configs)
end