active_replicas 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e56f8bd047e2f96b83a8246b4cdbcd428dd4e095
4
- data.tar.gz: e02a7e2680c7bc60aa47c2cd75a25ca704f3a5c5
3
+ metadata.gz: e5449461c40a999c9979801ce9395a9a7f3c43d3
4
+ data.tar.gz: 3a222a36c5715a2ae8709f7359d77ec3210114a3
5
5
  SHA512:
6
- metadata.gz: f430544ad26fd4f894addafb5961ea1cfc5aabf99fc565a206556bf70d302efe7afc4b4ae4447345c95c4ec1793d95d109400aa1995b7e72bfe4c1c644d2276e
7
- data.tar.gz: 755fc9c0a43f3860d4c8f2f5b7ef984740f401a51b10dc50c29f0da1bf964648df7d813457272529ab9da73177ce4e2a94db7e64b9e03d622fa305b0e8c57f66
6
+ metadata.gz: 3ce1364563eff9ec842ad01446747f45c0815cca827a251411158f3b7d67d481a930e6af8bedddc32219b561e311753c9406cfe3e5873a0cccc1afcfb5b55e57
7
+ data.tar.gz: 17314509e2bdfdc639bc9c608d03e050a5f291f1a2cead0057e4ebd05ff3bbf5d90809bbdd3def2d21581bd0be1526205c86b19fc47acaee6a5389b7d5bbce2c
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ActiveReplicas
2
2
 
3
- Allows you to automatically send read-only queries to replica databases; writes will automatically go to the primary and "stick" the request into using the primary for any further queries.
3
+ [![Build Status](https://travis-ci.org/dirk/active_replicas.svg?branch=master)](https://travis-ci.org/dirk/active_replicas)
4
+
5
+ Drop-in read-replica querying in ActiveRecord. It proxies around ActiveRecord's connection to send read-only queries to replica databases; writes will automatically go to the primary and "stick" the request into using the primary for any further queries.
4
6
 
5
7
  This is heavily inspired by [Kickstarter's `replica_pools`](https://github.com/kickstarter/replica_pools) gem. It seeks to improve on that gem by better interfacing with ActiveRecord's connection pools.
6
8
 
@@ -24,6 +26,20 @@ ActiveReplicas::Railtie.hijack_active_record primary: { url: 'mysql2://user@prim
24
26
 
25
27
  **Note**: ActiveReplicas does not do anything automatically. It only injects itself into ActiveRecord when you tell it do so (see above).
26
28
 
29
+ ## How it works
30
+
31
+ A few things happen when you call [`hijack_active_record`](http://www.rubydoc.info/github/dirk/active_replicas/master/ActiveReplicas/Railtie#hijack_active_record-class_method):
32
+
33
+ - It defines delegations for the [connection](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters.html) methods that can be sent to replicas and the methods that must be sent to a primary.
34
+ - It sets up a [`ConnectionHandler`](http://www.rubydoc.info/github/dirk/active_replicas/master/ActiveReplicas/Rails4/ConnectionHandler) that will act in place of ActiveRecord's normal connection handler.
35
+ - It replaces ActiveRecord's log subscriber with its own [`LogSubscriber`](http://www.rubydoc.info/github/dirk/active_replicas/master/ActiveReplicas/LogSubscriber) which adds information about replica/primary status to logging messages.
36
+
37
+ The new connection handler manages connection pools for each configured primary and replica database(s). Externally it provides instances of [`ProxyingConnectionPool`](http://www.rubydoc.info/github/dirk/active_replicas/master/ActiveReplicas/ProxyingConnectionPool) in place of normal connection pools. Those proxying pools then forward connection methods to primary or replica pools.
38
+
39
+ ### Using it with Ruby on Rails
40
+
41
+ ActiveReplicas works seamlessly within the Rails request lifecycle. It extends the [`clear_active_connections!` called in ActiveRecord's middleware](https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L645-L663) to not only clear the active connections (releasing them back to their respective pool) but also resets the primary/replica state. That way the next connection will start out using a replica.
42
+
27
43
  ## Contributing
28
44
 
29
45
  Bug reports and pull requests are welcome on [GitHub][]. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -13,12 +13,7 @@ module ActiveReplicas
13
13
 
14
14
  def initialize(proxy_configuration)
15
15
  @proxy_configuration = proxy_configuration
16
-
17
- @primary_pool = Helpers.connection_pool_for_spec @proxy_configuration[:primary]
18
-
19
- @replica_pools = (@proxy_configuration[:replicas] || {}).map do |name, config_spec|
20
- [name, Helpers.connection_pool_for_spec(config_spec)]
21
- end.to_h
16
+ initialize_pools
22
17
 
23
18
  # Each thread gets its own `ProxyingConnectionPool`.
24
19
  @reserved_proxies = Concurrent::Map.new
@@ -33,10 +28,23 @@ module ActiveReplicas
33
28
 
34
29
  def establish_connection(owner, spec)
35
30
  prefix = '[ActiveReplicas::Rails4::ConnectionHandler#establish_connection]'
36
- ActiveRecord::Base.logger&.warn "#{prefix} Ignoring spec for #{owner.inspect}: #{spec.inspect}"
37
- ActiveRecord::Base.logger&.info "#{prefix} Called from:\n" + Kernel.caller.first(5).map {|t| " #{t}" }.join("\n")
31
+ details = "#{spec.config.inspect} (owner: #{owner.inspect})"
38
32
 
39
- current_proxy
33
+ synchronize do
34
+ if @proxy_configuration[:primary] == spec.config
35
+ ActiveRecord::Base.logger&.warn "#{prefix} Ignoring new spec as it matches existing primary spec: #{details}"
36
+ else
37
+ ActiveRecord::Base.logger&.warn "#{prefix} Overwriting connection spec: #{details}"
38
+ ActiveRecord::Base.logger&.info "#{prefix} Called from:\n" + Kernel.caller.map {|t| " #{t}" }.join("\n")
39
+ @proxy_configuration = { primary: spec.config }
40
+ end
41
+
42
+ clear_all_connections!
43
+ initialize_pools
44
+
45
+ # Rails returns a connection pool.
46
+ retrieve_connection_pool owner
47
+ end
40
48
  end
41
49
 
42
50
  def active_connections?
@@ -114,6 +122,18 @@ module ActiveReplicas
114
122
  def current_thread_id
115
123
  Thread.current.object_id
116
124
  end
125
+
126
+ private
127
+
128
+ # Sets up `@primary_pool` and `@replica_pools` from the current
129
+ # `@proxy_configuration`.
130
+ def initialize_pools
131
+ @primary_pool = Helpers.connection_pool_for_spec @proxy_configuration[:primary]
132
+
133
+ @replica_pools = (@proxy_configuration[:replicas] || {}).map do |name, config_spec|
134
+ [name, Helpers.connection_pool_for_spec(config_spec)]
135
+ end.to_h
136
+ end
117
137
  end
118
138
  end
119
139
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveReplicas
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -7,7 +7,6 @@ if defined? ActiveRecord
7
7
  version = ActiveRecord::VERSION::MAJOR
8
8
 
9
9
  if version == 4
10
- require 'active_replicas/rails4/helpers'
11
10
  require 'active_replicas/rails4/connection_handler'
12
11
  else
13
12
  raise "Unsupported ActiveRecord version: #{version}"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_replicas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dirk Gadsden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-04 00:00:00.000000000 Z
11
+ date: 2016-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby