Module: NoBrainer::Config

Defined in:
lib/no_brainer/config.rb

Constant Summary collapse

SETTINGS =
{
  app_name: { default: -> { default_app_name } },
  colorize_logger: { default: -> { true }, valid_values: [true, false] },
  criteria_cache_max_entries: { default: -> { 10_000 } },
  db_timezone: { default: -> { :utc }, valid_values: %i[unchanged utc local] },
  distributed_lock_class: { default: -> { 'NoBrainer::Lock' } },
  driver: { default: -> { :regular }, valid_values: %i[regular em] },
  durability: { default: -> {} }, # legacy
  environment: { default: -> { default_environment } },
  geo_options: { default: -> { { geo_system: 'WGS84', unit: 'm' } } },
  lock_options: { default: -> { { expire: 60, timeout: 10 } }, valid_keys: %i[expire timeout] },
  log_slow_queries: { default: -> { false } },
  logger: { default: -> { default_logger } },
  long_query_time: { default: -> { 10 } },
  machine_id: { default: -> { default_machine_id } },
  max_string_length: { default: -> { 255 } },
  per_thread_connection: { default: -> { false }, valid_values: [true, false] },
  rethinkdb_urls: { default: -> { [default_rethinkdb_url] } },
  run_options: { default: -> { { durability: default_durability } } },
  on_slow_query: { default: -> { nil } },
  ssl_options: { default: -> {} },
  table_options: {
    default: -> { { shards: 1, replicas: 1, write_acks: :majority } },
    valid_keys: %i[durability shards replicas primary_replica_tag nonvoting_replica_tags write_acks]
  },
  user_timezone: { default: -> { :local }, valid_values: %i[unchanged utc local] },
  warn_on_active_record: { default: -> { true }, valid_values: [true, false] }
}.freeze
MACHINE_ID_BITS =

XXX Not referencing NoBrainer::Document::PrimaryKey::Generator::MACHINE_ID_MASK because we don’t want to load all the document code to speedup boot time.

24
MACHINE_ID_MASK =
(1 << MACHINE_ID_BITS)-1

Class Method Summary collapse

Class Method Details

.apply_defaultsObject



53
54
55
56
# File 'lib/no_brainer/config.rb', line 53

def apply_defaults
  @applied_defaults_for = SETTINGS.keys.reject { |k| instance_variable_defined?("@#{k}") }
  @applied_defaults_for.each { |k| __send__("#{k}=", SETTINGS[k][:default].call) }
end

.assert_hash_keys_in(name, valid_keys) ⇒ Object



109
110
111
112
113
114
# File 'lib/no_brainer/config.rb', line 109

def assert_hash_keys_in(name, valid_keys)
  extra_keys = __send__(name).keys - valid_keys
  unless extra_keys.empty?
    raise ArgumentError.new("Invalid configuration for  #{name}: #{__send__(name)}. Valid keys are: #{valid_keys.inspect}")
  end
end

.assert_valid_optionsObject



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/no_brainer/config.rb', line 70

def assert_valid_options
  SETTINGS.each do |k,v|
    assert_value_in(k, v[:valid_values]) if v[:valid_values]
    assert_hash_keys_in(k, v[:valid_keys]) if v[:valid_keys]
  end

  validate_urls

  if driver == :em && per_thread_connection
    raise "To use EventMachine, disable per_thread_connection"
  end
end

.assert_value_in(name, valid_values) ⇒ Object



103
104
105
106
107
# File 'lib/no_brainer/config.rb', line 103

def assert_value_in(name, valid_values)
  unless __send__(name).in?(valid_values)
    raise ArgumentError.new("Invalid configuration for #{name}: #{__send__(name)}. Valid values are: #{valid_values.inspect}")
  end
end

.auto_create_databases=(value) ⇒ Object



38
39
40
41
# File 'lib/no_brainer/config.rb', line 38

def auto_create_databases=(value)
  STDERR.puts "[NoBrainer] config.auto_create_databases is no longer active."
  STDERR.puts "[NoBrainer] The current behavior is now to always auto create databases"
end

.auto_create_tables=(value) ⇒ Object



43
44
45
46
# File 'lib/no_brainer/config.rb', line 43

def auto_create_tables=(value)
  STDERR.puts "[NoBrainer] config.auto_create_tables is no longer active."
  STDERR.puts "[NoBrainer] The current behavior is now to always auto create tables"
end

.configure(&block) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/no_brainer/config.rb', line 87

def configure(&block)
  @applied_defaults_for.to_a.each do |k|
    remove_instance_variable("@#{k}") if instance_variable_defined?("@#{k}")
  end
  block.call(self) if block
  apply_defaults
  assert_valid_options
  @configured = true

  NoBrainer::ConnectionManager.notify_url_change
end

.configured?Boolean

Returns:



99
100
101
# File 'lib/no_brainer/config.rb', line 99

def configured?
  !!@configured
end

.default_app_nameObject



120
121
122
123
124
125
# File 'lib/no_brainer/config.rb', line 120

def default_app_name
  return unless defined?(Rails)
  NoBrainer.rails6? ?
    Rails.application.class.module_parent_name.underscore.presence :
    Rails.application.class.parent_name.underscore.presence rescue nil
end

.default_durabilityObject



160
161
162
# File 'lib/no_brainer/config.rb', line 160

def default_durability
  dev_mode? ? :soft : :hard
end

.default_environmentObject



127
128
129
130
# File 'lib/no_brainer/config.rb', line 127

def default_environment
  return Rails.env if defined?(Rails.env)
  ENV['RUBY_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || :production
end

.default_loggerObject



155
156
157
158
# File 'lib/no_brainer/config.rb', line 155

def default_logger
  (Rails.logger if defined?(Rails.logger)) ||
     Logger.new(STDERR).tap { |l| l.level = Logger::WARN }
end

.default_machine_idObject



174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/no_brainer/config.rb', line 174

def default_machine_id
  return ENV['MACHINE_ID'] if ENV['MACHINE_ID']

  require 'socket'
  require 'digest/md5'

  host = Socket.gethostname
  if host.in? %w(127.0.0.1 localhost)
    raise "Please configure NoBrainer::Config.machine_id due to lack of appropriate hostname (Socket.gethostname = #{host})"
  end

  Digest::MD5.digest(host).unpack("N")[0] & MACHINE_ID_MASK
end

.default_max_retries_on_connection_failureObject



164
165
166
167
# File 'lib/no_brainer/config.rb', line 164

def default_max_retries_on_connection_failure
  # TODO remove
  dev_mode? ? 1 : 15
end

.default_rethinkdb_urlObject



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/no_brainer/config.rb', line 136

def default_rethinkdb_url
  db = ENV['RETHINKDB_DB'] || ENV['RDB_DB']
  db ||= "#{self.app_name}_#{self.environment}" if self.app_name && self.environment
  host = ENV['RETHINKDB_HOST'] || ENV['RDB_HOST'] || 'localhost'
  port = ENV['RETHINKDB_PORT'] || ENV['RDB_PORT']
  user = ENV['RETHINKDB_USER'] || ENV['RDB_USER']
  pass = ENV['RETHINKDB_PASSWORD'] || ENV['RDB_PASSWORD'] || ENV['RETHINKDB_AUTH'] || ENV['RDB_AUTH']
  url = ENV['RETHINKDB_URL'] || ENV['RDB_URL']
  url ||= "rethinkdb://#{"#{user}:#{pass}@" if (user || pass)}#{host}#{":#{port}" if port}/#{db}" if db
  url
end

.dev_mode?Boolean

Returns:



116
117
118
# File 'lib/no_brainer/config.rb', line 116

def dev_mode?
  self.environment.to_s.in? %w(development test)
end

.distributed_lock_classObject



199
200
201
202
203
204
# File 'lib/no_brainer/config.rb', line 199

def distributed_lock_class
  if @distributed_lock_class.is_a?(String)
    @distributed_lock_class = @distributed_lock_class.constantize
  end
  @distributed_lock_class
end

.geo_options=(value) ⇒ Object



62
63
64
# File 'lib/no_brainer/config.rb', line 62

def geo_options=(value)
  @geo_options = value.try(:symbolize_keys)
end

.machine_id=(machine_id) ⇒ Object



188
189
190
191
192
193
194
195
196
197
# File 'lib/no_brainer/config.rb', line 188

def machine_id=(machine_id)
  machine_id = case machine_id
    when Integer    then machine_id
    when /^[0-9]+$/ then machine_id.to_i
    else raise "Invalid machine_id"
  end
  max_id = MACHINE_ID_MASK
  raise "Invalid machine_id (must be between 0 and #{max_id})" unless machine_id.in?(0..max_id)
  @machine_id = machine_id
end

.max_retries_on_connection_failure=(value) ⇒ Object



48
49
50
51
# File 'lib/no_brainer/config.rb', line 48

def max_retries_on_connection_failure=(value)
  STDERR.puts "[NoBrainer] config.max_retries_on_connection_failure has been removed."
  STDERR.puts "[NoBrainer] Queries are no longer retried upon failures"
end

.on_slow_query=(callback) ⇒ Object



58
59
60
# File 'lib/no_brainer/config.rb', line 58

def on_slow_query=(callback)
  @on_slow_query = callback
end

.reset!Object



83
84
85
# File 'lib/no_brainer/config.rb', line 83

def reset!
  instance_variables.each { |ivar| remove_instance_variable(ivar) }
end

.rethinkdb_url=(value) ⇒ Object



132
133
134
# File 'lib/no_brainer/config.rb', line 132

def rethinkdb_url=(value)
  self.rethinkdb_urls = [*value]
end

.run_options=(value) ⇒ Object



66
67
68
# File 'lib/no_brainer/config.rb', line 66

def run_options=(value)
  @run_options = value.try(:symbolize_keys)
end

.validate_urlsObject



148
149
150
151
152
153
# File 'lib/no_brainer/config.rb', line 148

def validate_urls
  # This is not connecting, just validating the format.
  dbs = rethinkdb_urls.compact.map { |url| NoBrainer::Connection.new(url).parsed_uri[:db] }.uniq
  raise "Please specify the app_name and the environment, or a rethinkdb_url" if dbs.size == 0
  raise "All the rethinkdb_urls must specify the same db name (instead of #{dbs.inspect})" if dbs.size != 1
end