Class: ActiveReplicas::Rails4::ProcessLocalConnectionHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/active_replicas/rails4/process_local_connection_handler.rb

Overview

Provisioned for each process by ConnectionHandler. Each process owns its own pools of connections to primary and replica databases. Proxying connection pools are then provisioned for each thread.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(proxy_configuration) ⇒ ProcessLocalConnectionHandler

Returns a new instance of ProcessLocalConnectionHandler.



14
15
16
17
18
19
20
21
22
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 14

def initialize(proxy_configuration)
  @proxy_configuration = proxy_configuration
  initialize_pools

  # Each thread gets its own `ProxyingConnectionPool`.
  @reserved_proxies = Concurrent::Map.new

  extend MonitorMixin
end

Instance Attribute Details

#primary_poolObject (readonly)

Returns the value of attribute primary_pool.



12
13
14
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 12

def primary_pool
  @primary_pool
end

#proxy_configurationObject (readonly)

Returns the value of attribute proxy_configuration.



11
12
13
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 11

def proxy_configuration
  @proxy_configuration
end

#replica_poolsObject (readonly)

Returns the value of attribute replica_pools.



12
13
14
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 12

def replica_pools
  @replica_pools
end

Instance Method Details

#active_connections?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 50

def active_connections?
  connection_pool_list.any?(&:active_connection?)
end

#clear_active_connections!Object



54
55
56
57
58
59
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 54

def clear_active_connections!
  synchronize do
    connection_pool_list.each(&:release_connection)
    clear_current_proxy
  end
end

#clear_all_connections!Object



68
69
70
71
72
73
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 68

def clear_all_connections!
  synchronize do
    connection_pool_list.each(&:disconnect!)
    clear_proxies!
  end
end

#clear_current_proxyObject

Remove the current reserved ProxyingConnectionPool from the pool.



113
114
115
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 113

def clear_current_proxy
  @reserved_proxies.delete current_thread_id
end

#clear_proxies!Object

Clear all reserved ProxyingConnectionPool instances from the pool.



118
119
120
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 118

def clear_proxies!
  @reserved_proxies.clear
end

#clear_reloadable_connections!Object



61
62
63
64
65
66
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 61

def clear_reloadable_connections!
  synchronize do
    connection_pool_list.each(&:clear_reloadable_connections!)
    clear_proxies!
  end
end

#connected?(klass) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
88
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 85

def connected?(klass)
  pool = retrieve_connection_pool klass
  pool && pool.connected?
end

#connection_pool_listObject

Returns a list of all the connection pools owned by this handler.



25
26
27
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 25

def connection_pool_list
  [@primary_pool] + @replica_pools.values
end

#current_proxyObject

Returns the ThreadLocalConnectionHandler for this thread.



106
107
108
109
110
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 106

def current_proxy
  @reserved_proxies[current_thread_id] || synchronize do
    @reserved_proxies[current_thread_id] ||= ProxyingConnectionPool.new(self)
  end
end

#current_thread_idObject



122
123
124
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 122

def current_thread_id
  Thread.current.object_id
end

#establish_connection(owner, spec) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 29

def establish_connection(owner, spec)
  prefix = '[ActiveReplicas::Rails4::ConnectionHandler#establish_connection]'
  details = "#{spec.config.inspect} (owner: #{owner.inspect})"

  synchronize do
    if @proxy_configuration[:primary] == spec.config
      ActiveRecord::Base.logger&.warn "#{prefix} Ignoring new spec as it matches existing primary spec: #{details}"
    else
      ActiveRecord::Base.logger&.warn "#{prefix} Overwriting connection spec: #{details}"
      ActiveRecord::Base.logger&.info "#{prefix} Called from:\n" + Kernel.caller.map {|t| "  #{t}" }.join("\n")
      @proxy_configuration = { primary: spec.config }
    end

    clear_all_connections!
    initialize_pools

    # Rails returns a connection pool.
    retrieve_connection_pool owner
  end
end

#remove_connection(owner_klass) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 90

def remove_connection(owner_klass)
  if proxy = clear_current_proxy
    proxy.automatic_reconnect = false
    proxy.disconnect!
    proxy.spec.config
  end
end

#retrieve_connection(klass) ⇒ Object

Cribbed from:

https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L568

Raises:

  • (ConnectionNotEstablished)


77
78
79
80
81
82
83
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 77

def retrieve_connection(klass)
  pool = retrieve_connection_pool klass
  raise ConnectionNotEstablished, "No connection pool for #{klass}" unless pool
  conn = pool.connection
  raise ConnectionNotEstablished, "No connection for #{klass} in connection pool" unless conn
  conn
end

#retrieve_connection_pool(klass) ⇒ Object



98
99
100
# File 'lib/active_replicas/rails4/process_local_connection_handler.rb', line 98

def retrieve_connection_pool(klass)
  current_proxy
end