3scale/porta

View on GitHub
app/lib/three_scale/redis_config.rb

Summary

Maintainability
A
1 hr
Test Coverage
# frozen_string_literal: true

module ThreeScale
  class RedisConfig
    def initialize(redis_config = {})
      raw_config = (redis_config || {}).deep_symbolize_keys
      raw_config.delete_if { |_key, value| value.blank? }
      uri = URI.parse(raw_config[:url].to_s)
      raw_config[:db] ||= uri.path[1..]
      raw_config[:ssl] ||= true if uri.scheme == 'rediss'
      apply_sentinels_config!(raw_config)
      raw_config.compact!

      @config = ActiveSupport::OrderedOptions.new.merge(raw_config)
    end

    attr_reader :config

    def reverse_merge(other)
      other.merge(config)
    end

    def reverse_merge!(other)
      @config = ActiveSupport::OrderedOptions.new.merge(reverse_merge(other))
    end

    def method_missing(method_sym, *args, &block)
      if config.respond_to?(method_sym)
        config.send(method_sym, *args, &block)
      else
        super
      end
    end

    def respond_to_missing?(method_sym, *args)
      super || config.respond_to?(method_sym)
    end

    protected

    DEFAULT_SENTINEL_PORT = 26379

    def apply_sentinels_config!(config)
      sentinels = config.delete(:sentinels).presence
      return unless sentinels

      sentinel_user = nil
      sentinel_password = nil
      config[:sentinels] = sentinels.to_s.split(',').map do |sentinel_url|
        uri = URI.parse((sentinel_url =~ %r{^(redis(s)?|unix):\/\/.+} ? '' : 'redis://') + sentinel_url)
        sentinel_user ||= uri.user
        sentinel_password ||= uri.password
        { host: uri.host, port: (uri.port || DEFAULT_SENTINEL_PORT) }
      end

      config[:name] ||= URI.parse(config[:url].to_s).host
      config[:sentinel_username] = sentinel_user if sentinel_user.present?
      config[:sentinel_password] = sentinel_password if sentinel_password.present?

      config
    end
  end
end