Skip to content

Instantly share code, notes, and snippets.

@casperisfine
Created September 14, 2019 15:58
Show Gist options
  • Save casperisfine/536a2dd020d6e0038a0f624aa47b2444 to your computer and use it in GitHub Desktop.
Save casperisfine/536a2dd020d6e0038a0f624aa47b2444 to your computer and use it in GitHub Desktop.
default: &default
adapter: mysql2
username: root
host: 192.168.64.72
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
default_animals: &default_animals
<<: *default
migrations_paths: db/animals_migrate
development:
<<: *default
database: test-app_development
development_sharding:
primary:
shards:
one:
reading:
<<: *default
database: primary_development
replica: true
writing:
<<: *default
database: primary_development
two:
<<: *default
database: primary_development
animals:
reading:
<<: *default
database: animals_development
replica: true
writing:
<<: *default
database: animals_development
development_current_multidb:
animals_reading:
<<: *default
database: animals_development
replica: true
animals_writing:
<<: *default
database: animals_development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
primary:
<<: *default
database: primary_test
animals:
<<: *default_animals
database: animals_test
require 'yaml'
require 'active_support/all'
require 'active_record'
require 'active_record/database_configurations'
module ActiveRecord
class DatabaseConfigurations
class Parser
def initialize(env)
@env = env
end
def parse(config)
env_config = config.fetch(@env)
if database_config?(env_config)
{ 'primary' => Group.new('primary', 'writer' => Role.new('writer', env_config)) }
else
env_config.map { |group_name, group_config| parse_group(group_name, group_config) }.index_by(&:name)
end
end
def parse_group(name, config)
if config.size == 1 && config.key?('shards')
ShardedGroup.new(name, parse_shards(config.fetch('shards')))
else
Group.new(name, parse_roles(config))
end
end
def parse_roles(config)
if database_config?(config)
return { 'writer' => Role.new('writer', config) }
end
config.map do |role_name, db_config|
[role_name, Role.new(role_name, db_config)]
end.to_h
end
def parse_shards(config)
config.map { |shard_id, roles| Shard.new(shard_id, parse_roles(roles)) }
end
def database_config?(config)
config.key?('adapter')
end
end
class Group # alt: Schema
attr_reader :name, :roles
def initialize(name, roles)
@name = name
@roles = roles
end
# All roles of the same group share the same schema cache
def schema_cache
raise NotImplementedError
end
end
class ShardedGroup # alt: ShardedSchema
attr_reader :name
def initialize(name, shards)
@name = name
@shards = shards
end
# All roles of the same group share the same schema cache
def schema_cache
raise NotImplementedError
end
end
class Shard
attr_reader :name, :roles
def initialize(name, roles)
@name = name
@roles = roles
end
end
class Role
attr_reader :name, :config
def initialize(name, config)
@name = name
@config = config
end
def pool # The role is responsible for instanciating the connection pool
raise NotImplementedError
end
end
end
end
document = YAML.load_file('config/database.yml')
%w(development development_sharding development_current_multidb).each do |env|
puts
puts env + ('-' * 40)
puts
pp ActiveRecord::DatabaseConfigurations::Parser.new(env).parse(document)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment