Class: PgReports::Connection::Target
- Inherits:
-
Object
- Object
- PgReports::Connection::Target
- Defined in:
- lib/pg_reports/connection/target.rb
Overview
Represents a single named PostgreSQL target (host+credentials). Holds a memoized AR-subclass-backed connection per database it has been asked for, so switching between databases on the same target reuses pools.
The :primary target wraps ActiveRecord::Base directly when accessed at its default database — we don’t open a parallel pool to the host app’s DB. For non-default databases we create an isolated AR subclass that has its own pool, so the host application’s pool is never affected.
Defined Under Namespace
Classes: ConnectionFailed
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
-
#ar_class_for(database = nil) ⇒ Object
Resolve the AR class backing the connection for ‘database` (nil = default).
-
#connection_for(database = nil) ⇒ Object
Returns the active PG connection for ‘database`, opening it if needed.
- #default_database ⇒ Object
-
#disconnect! ⇒ Object
Close all derived pools we own.
-
#initialize(name, spec) ⇒ Target
constructor
A new instance of Target.
-
#list_databases(current: nil) ⇒ Object
List all databases visible on this target’s cluster (using pg_database).
-
#spec ⇒ Object
Configuration hash used as a template for derived databases.
Constructor Details
#initialize(name, spec) ⇒ Target
Returns a new instance of Target.
18 19 20 21 22 |
# File 'lib/pg_reports/connection/target.rb', line 18 def initialize(name, spec) @name = name.to_sym @spec = normalize_spec(spec) @pools = {} # database (string) => AR class end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
16 17 18 |
# File 'lib/pg_reports/connection/target.rb', line 16 def name @name end |
Instance Method Details
#ar_class_for(database = nil) ⇒ Object
Resolve the AR class backing the connection for ‘database` (nil = default). Returns a class responding to `.connection` (ActiveRecord::Base or subclass).
35 36 37 38 39 40 |
# File 'lib/pg_reports/connection/target.rb', line 35 def ar_class_for(database = nil) db = (database || default_database).to_s raise ArgumentError, "Cannot resolve connection: target #{name.inspect} has no default database and none was given" if db.empty? @pools[db] ||= build_pool_class(db) end |
#connection_for(database = nil) ⇒ Object
Returns the active PG connection for ‘database`, opening it if needed.
43 44 45 46 47 |
# File 'lib/pg_reports/connection/target.rb', line 43 def connection_for(database = nil) ar_class_for(database).connection rescue ActiveRecord::NoDatabaseError, PG::ConnectionBad => e raise ConnectionFailed, "Cannot connect to #{name}/#{database || default_database}: #{e.}" end |
#default_database ⇒ Object
29 30 31 |
# File 'lib/pg_reports/connection/target.rb', line 29 def default_database @spec[:database]&.to_s end |
#disconnect! ⇒ Object
Close all derived pools we own. The :primary AR::Base pool is never touched.
65 66 67 68 69 70 71 72 73 |
# File 'lib/pg_reports/connection/target.rb', line 65 def disconnect! @pools.each_value do |klass| next if klass.equal?(ActiveRecord::Base) klass.connection_pool.disconnect! if klass.connection_pool.connected? rescue # Best-effort cleanup end @pools.clear end |
#list_databases(current: nil) ⇒ Object
List all databases visible on this target’s cluster (using pg_database). Result rows: { “name” => String, “size” => String, “current” => Boolean }
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/pg_reports/connection/target.rb', line 51 def list_databases(current: nil) rows = connection_for.exec_query(<<~SQL).to_a SELECT datname AS name, pg_size_pretty(pg_database_size(datname)) AS size FROM pg_database WHERE datistemplate = false AND datallowconn = true ORDER BY datname SQL current_db = (current || default_database).to_s rows.each { |r| r["current"] = (r["name"].to_s == current_db) } rows end |
#spec ⇒ Object
Configuration hash used as a template for derived databases.
25 26 27 |
# File 'lib/pg_reports/connection/target.rb', line 25 def spec @spec.dup end |