counter_culture 3.8.2 → 3.9.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
  SHA256:
3
- metadata.gz: 13f043a04b7cca0b364e7692c19425b049b45b4e965ed5caac0dbac2f91622c1
4
- data.tar.gz: 50dfedf030e3c3823829aedc5e3b2a08fe65b63b50fc439d229afb5ab3fa5d5d
3
+ metadata.gz: f93d3d3e415f5d92e3870caf67067cdb75a6a76f68542b82c9ec2411987a0e4d
4
+ data.tar.gz: 89cf5171b549aab368a1dd87117afd429bf557d93f198e220fbe3b2a24e81f20
5
5
  SHA512:
6
- metadata.gz: 604bd858a6660d3e83b74b339a2675366b5d7908c87c37241ed9eb9a2b245ddb4d02b19d6782d3c30df793cd895be45e22455e34f9aca88e5fee462f472c2a48
7
- data.tar.gz: a5828bb5f0bd66b6717401b47f8494687a371546c6f3df89c93dd9a524a055e074aeffc3fa6c02e0b2e2cd25c3e706e76c2ef654e22a0b3f48cfb3d0c0c401b7
6
+ metadata.gz: 17b50c40207f615d0018c142062e536c3da69bebab209d4facb63ee03273363d97f83675d173f3096f98c68393f374e39aae0dba0db6364de9bc3c83d38af160
7
+ data.tar.gz: d7bef1c4214a30fa9888843c35fe2f074ea89e78b9341b5ed458471934576dea9ef8bf12fac72bd549a532fc50d34b9e327c4f2b943e7965720f3b12bef503b6
data/.circleci/config.yml CHANGED
@@ -49,7 +49,7 @@ workflows:
49
49
  matrix:
50
50
  parameters:
51
51
  ruby-version: ["2.6", "2.7", "3.0", "3.1", "3.2", "3.3"]
52
- rails-version: ["5.2", "6.0", "6.1", "7.0", "7.1", "7.2"]
52
+ rails-version: ["5.2", "6.0", "6.1", "7.0", "7.1", "7.2", "8.0"]
53
53
  database: ["postgresql", "sqlite3", "mysql2"]
54
54
  exclude:
55
55
  - ruby-version: "3.0"
@@ -133,3 +133,39 @@ workflows:
133
133
  - ruby-version: "3.0"
134
134
  rails-version: "7.2"
135
135
  database: "mysql2"
136
+ - ruby-version: "2.6"
137
+ rails-version: "8.0"
138
+ database: "postgresql"
139
+ - ruby-version: "2.6"
140
+ rails-version: "8.0"
141
+ database: "sqlite3"
142
+ - ruby-version: "2.6"
143
+ rails-version: "8.0"
144
+ database: "mysql2"
145
+ - ruby-version: "2.7"
146
+ rails-version: "8.0"
147
+ database: "postgresql"
148
+ - ruby-version: "2.7"
149
+ rails-version: "8.0"
150
+ database: "sqlite3"
151
+ - ruby-version: "2.7"
152
+ rails-version: "8.0"
153
+ database: "mysql2"
154
+ - ruby-version: "3.0"
155
+ rails-version: "8.0"
156
+ database: "postgresql"
157
+ - ruby-version: "3.0"
158
+ rails-version: "8.0"
159
+ database: "sqlite3"
160
+ - ruby-version: "3.0"
161
+ rails-version: "8.0"
162
+ database: "mysql2"
163
+ - ruby-version: "3.1"
164
+ rails-version: "8.0"
165
+ database: "postgresql"
166
+ - ruby-version: "3.1"
167
+ rails-version: "8.0"
168
+ database: "sqlite3"
169
+ - ruby-version: "3.1"
170
+ rails-version: "8.0"
171
+ database: "mysql2"
data/Appraisals CHANGED
@@ -5,6 +5,7 @@
5
5
  7.0
6
6
  7.1
7
7
  7.2
8
+ 8.0
8
9
  ].each do |rails_version|
9
10
  appraise "rails-#{rails_version}" do
10
11
  gem 'activerecord', "~> #{rails_version}.0"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 3.9.0 (March 20, 2025)
2
+
3
+ New features:
4
+ - Add global configuration for using a read replica (#405)
5
+
1
6
  ## 3.8.2 (October 21, 2024)
2
7
 
3
8
  Bugfixes:
data/README.md CHANGED
@@ -7,7 +7,7 @@ Turbo-charged counter caches for your Rails app. Huge improvements over the Rail
7
7
  * Supports dynamic column names, making it possible to split up the counter cache for different types of objects
8
8
  * Can keep a running count, or a running total
9
9
 
10
- Tested against Ruby 2.6, 2.7, 3.0, 3.1, 3.2 and 3.3 and against the latest patch releases of Rails 5.2, 6.0, 6.1, 7.0 and 7.1.
10
+ Tested against Ruby 2.6, 2.7, 3.0, 3.1, 3.2 and 3.3 and against the latest patch releases of Rails 5.2, 6.0, 6.1, 7.0, 7.1, 7.2 and 8.0.
11
11
 
12
12
  Please note that -- unlike Rails' built-in counter-caches -- counter_culture does not currently change the behavior of the `.size` method on ActiveRecord associations. If you want to avoid a database query and read the cached value, please use the attribute name containing the counter cache directly.
13
13
 
@@ -618,6 +618,39 @@ Image.counter_culture_fix_counts(polymorphic_classes: Product)
618
618
  Image.counter_culture_fix_counts(polymorphic_classes: [Product, Employee])
619
619
  ```
620
620
 
621
+ ## Using Read Replicas
622
+
623
+ When using `counter_culture_fix_counts`, you can configure counter_culture to use read replicas for counting operations, which can help reduce load on your primary database. Write operations will still use the primary database.
624
+
625
+ ### Global Configuration
626
+
627
+ You can enable read replica support globally:
628
+
629
+ ```ruby
630
+ # config/initializers/counter_culture.rb
631
+ CounterCulture.configure do |config|
632
+ config.use_read_replica = true
633
+ end
634
+ ```
635
+
636
+ ### Per-Call Configuration
637
+
638
+ You can also specify read replica usage per call (this takes precedence over global configuration):
639
+
640
+ ```ruby
641
+ Model.counter_culture_fix_counts(
642
+ db_connection_builder: proc { |reading, block|
643
+ if reading
644
+ ApplicationRecord.connected_to(role: :reading, &block)
645
+ else
646
+ ApplicationRecord.connected_to(role: :writing, &block)
647
+ end
648
+ }
649
+ )
650
+ ```
651
+
652
+ Note: This feature requires Rails 7.1 or higher for full read replica support. On older versions, it will fall back to using the primary database.
653
+
621
654
  ## Contributing to counter_culture
622
655
 
623
656
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 8.0.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,34 @@
1
+ module CounterCulture
2
+ def self.configuration
3
+ @configuration ||= Configuration.new
4
+ end
5
+
6
+ def self.configure
7
+ yield(configuration)
8
+ end
9
+
10
+ def self.reset_configuration
11
+ @configuration = Configuration.new
12
+ end
13
+
14
+ class Configuration
15
+ attr_reader :use_read_replica
16
+
17
+ def initialize
18
+ @use_read_replica = false
19
+ end
20
+
21
+ def use_read_replica=(value)
22
+ if value && !rails_supports_read_replica?
23
+ raise "Counter Culture's read replica support requires Rails 7.1 or higher"
24
+ end
25
+ @use_read_replica = value
26
+ end
27
+
28
+ private
29
+
30
+ def rails_supports_read_replica?
31
+ Gem::Requirement.new('>= 7.1.0').satisfied_by?(ActiveRecord.version)
32
+ end
33
+ end
34
+ end
@@ -66,6 +66,7 @@ module CounterCulture
66
66
  @counter, @options, = counter, options
67
67
  @relation_class = relation_class
68
68
  @changes_holder = changes_holder
69
+ @connection_handler = WithConnection.new(relation_class)
69
70
  end
70
71
 
71
72
  def perform
@@ -314,7 +315,7 @@ module CounterCulture
314
315
  # using Postgres with schema-namespaced tables. But then it's required,
315
316
  # and otherwise it's just a no-op, so why not do it?
316
317
  def quote_table_name(table_name)
317
- WithConnection.new(relation_class).call do |connection|
318
+ @connection_handler.call do |connection|
318
319
  connection.quote_table_name(table_name)
319
320
  end
320
321
  end
@@ -331,7 +332,9 @@ module CounterCulture
331
332
  if builder = options[:db_connection_builder]
332
333
  builder.call(true, block)
333
334
  else
334
- yield
335
+ @connection_handler.call(reading: true) do |_conn|
336
+ yield
337
+ end
335
338
  end
336
339
  end
337
340
 
@@ -339,7 +342,9 @@ module CounterCulture
339
342
  if builder = options[:db_connection_builder]
340
343
  builder.call(false, block)
341
344
  else
342
- yield
345
+ @connection_handler.call(reading: false) do |_conn|
346
+ yield
347
+ end
343
348
  end
344
349
  end
345
350
  end
@@ -1,3 +1,3 @@
1
1
  module CounterCulture
2
- VERSION = '3.8.2'.freeze
2
+ VERSION = '3.9.0'.freeze
3
3
  end
@@ -6,28 +6,42 @@ module CounterCulture
6
6
 
7
7
  attr_reader :recipient
8
8
 
9
- def call
10
- if rails_7_2_or_greater?
11
- recipient.with_connection do |connection|
12
- yield connection
13
- end
14
- elsif rails_7_1?
15
- recipient.connection_pool.with_connection do |connection|
16
- yield connection
9
+ def call(reading: false)
10
+ if rails_7_1_or_greater?
11
+ use_read_replica = CounterCulture.configuration.use_read_replica && reading
12
+ role = use_read_replica ? :reading : :writing
13
+
14
+ ActiveRecord::Base.connected_to(role: role) do
15
+ yield_with_connection { |conn| yield conn }
17
16
  end
18
17
  else
19
- yield recipient.connection
18
+ # For older Rails versions, just use normal connection
19
+ yield_with_connection { |conn| yield conn }
20
20
  end
21
21
  end
22
22
 
23
23
  private
24
24
 
25
- def rails_7_1?
26
- Gem::Requirement.new('~> 7.1.0').satisfied_by?(ActiveRecord.version)
25
+ def yield_with_connection
26
+ if rails_7_2_or_greater?
27
+ recipient.with_connection { |conn| yield conn }
28
+ elsif rails_7_1?
29
+ recipient.connection_pool.with_connection { |conn| yield conn }
30
+ else
31
+ yield recipient.connection
32
+ end
33
+ end
34
+
35
+ def rails_7_1_or_greater?
36
+ Gem::Requirement.new('>= 7.1.0').satisfied_by?(ActiveRecord.version)
27
37
  end
28
38
 
29
39
  def rails_7_2_or_greater?
30
40
  Gem::Requirement.new('>= 7.2.0').satisfied_by?(ActiveRecord.version)
31
41
  end
42
+
43
+ def rails_7_1?
44
+ Gem::Requirement.new('~> 7.1.0').satisfied_by?(ActiveRecord.version)
45
+ end
32
46
  end
33
47
  end
@@ -3,6 +3,7 @@ require 'active_support/lazy_load_hooks'
3
3
 
4
4
  require 'counter_culture/version'
5
5
  require 'counter_culture/extensions'
6
+ require 'counter_culture/configuration'
6
7
  require 'counter_culture/counter'
7
8
  require 'counter_culture/reconciler'
8
9
  require 'counter_culture/skip_updates'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: counter_culture
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.2
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Magnus von Koeller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-21 00:00:00.000000000 Z
11
+ date: 2025-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -319,7 +319,9 @@ files:
319
319
  - gemfiles/rails_7.0.gemfile
320
320
  - gemfiles/rails_7.1.gemfile
321
321
  - gemfiles/rails_7.2.gemfile
322
+ - gemfiles/rails_8.0.gemfile
322
323
  - lib/counter_culture.rb
324
+ - lib/counter_culture/configuration.rb
323
325
  - lib/counter_culture/counter.rb
324
326
  - lib/counter_culture/extensions.rb
325
327
  - lib/counter_culture/reconciler.rb