Skip to content

Commit

Permalink
Use built-in ActiveRecord URL resolver (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlarraz authored Feb 5, 2021
1 parent abd3bf4 commit e584045
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 91 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
All notable changes to this project will be documented in this file.

## Unreleased
- Use ActiveRecord URL resolver instead of copying definition [#294](https://github.com/instacart/makara/pull/294) Matt Larraz
- Deprecated the term `master` in favor of `primary` [#290](https://github.com/instacart/makara/pull/290) Matt Larraz
- Deprecated the term `slave` in favor of `replica` [#286](https://github.com/instacart/makara/pull/286) Matt Larraz
- Drop support for Ruby < 2.5 and ActiveRecord < 5.2 [#281](https://github.com/instacart/makara/pull/281) Matt Larraz
Expand Down
96 changes: 5 additions & 91 deletions lib/makara/config_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,99 +37,13 @@ class ConfigParser
master_ttl: :primary_ttl
}.freeze

# ConnectionUrlResolver is borrowed from Rails 4-2 since its location and implementation
# vary slightly among Rails versions, but the behavior is the same. Thus, borrowing the
# class should be the most future-safe way to parse a database url.
#
# Expands a connection string into a hash.
class ConnectionUrlResolver # :nodoc:
# == Example
#
# url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
# ConnectionUrlResolver.new(url).to_hash
# # => {
# "adapter" => "postgresql",
# "host" => "localhost",
# "port" => 9000,
# "database" => "foo_test",
# "username" => "foo",
# "password" => "bar",
# "pool" => "5",
# "timeout" => "3000"
# }
def initialize(url)
raise "Database URL cannot be empty" if url.blank?

@uri = URI.parse(url)
@adapter = @uri.scheme.tr('-', '_')
@adapter = "postgresql" if @adapter == "postgres"

if @uri.opaque
@uri.opaque, @query = @uri.opaque.split('?', 2)
else
@query = @uri.query
end
end

# Converts the given URL to a full connection hash.
def to_hash
config = raw_config.reject { |_,value| value.blank? }
config.map { |key,value| config[key] = CGI.unescape(value) if value.is_a? String }
config
end

private

def uri
@uri
end

# Converts the query parameters of the URI into a hash.
#
# "localhost?pool=5&reaping_frequency=2"
# # => { "pool" => "5", "reaping_frequency" => "2" }
#
# returns empty hash if no query present.
#
# "localhost"
# # => {}
def query_hash
Hash[(@query || '').split("&").map { |pair| pair.split("=") }]
ConnectionUrlResolver =
if ::ActiveRecord::VERSION::STRING >= "6.1.0"
::ActiveRecord::DatabaseConfigurations::ConnectionUrlResolver
else
::ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver
end

def raw_config
if uri.opaque
query_hash.merge({
"adapter" => @adapter,
"database" => uri.opaque })
else
query_hash.merge({
"adapter" => @adapter,
"username" => uri.user,
"password" => uri.password,
"port" => uri.port,
"database" => database_from_path,
"host" => uri.host })
end
end

# Returns name of the database.
def database_from_path
if @adapter == 'sqlite3'
# 'sqlite3:/foo' is absolute, because that makes sense. The
# corresponding relative version, 'sqlite3:foo', is handled
# elsewhere, as an "opaque".

uri.path
else
# Only SQLite uses a filename as the "database" name; for
# anything else, a leading slash would be silly.

uri.path.sub(%r{^/}, "")
end
end
end

# NOTE: url format must be, e.g.
# url: mysql2://...
# NOT
Expand Down

0 comments on commit e584045

Please sign in to comment.