incrdecr_cached_counts 0.3.0 → 0.6.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 +4 -4
- data/.circleci/config.yml +16 -28
- data/incrdecr_cached_counts.gemspec +1 -3
- data/lib/cached_counts/query_context.rb +21 -0
- data/lib/cached_counts/version.rb +1 -1
- data/lib/cached_counts.rb +14 -25
- data/spec/spec_helper.rb +2 -9
- metadata +7 -46
- data/.travis.yml +0 -15
- data/lib/cached_counts/connection_for.rb +0 -14
- data/lib/cached_counts/dalli_check.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d5bd60c008ad0b41a08214d9243ebb6278467bb3ca2b5f3314609c5361b6c1a
|
4
|
+
data.tar.gz: cea01587597deb81ff143e8383a194238a00e36c2e2529760aec60a83f485b5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8e9a0efe389831ae4f8d28db0cc23f2b873c705231fed8caa80ee322e84abf0d0998f6f3d777a8e7ce565ce0c2770ab3438322ff50a2921349d3d9e4f81dac6
|
7
|
+
data.tar.gz: b8fdd83b366cc6827cf925bfb003a065a2139ab98a103b9cb2ad9daac89f421fd3110328d80e5c6910caa7ce9322c06791c67b3d64caf66c5d030e41cbdd1b35
|
data/.circleci/config.yml
CHANGED
@@ -1,59 +1,47 @@
|
|
1
|
-
version: 2
|
1
|
+
version: 2.1
|
2
2
|
|
3
3
|
jobs:
|
4
4
|
build:
|
5
5
|
docker:
|
6
|
-
- image:
|
6
|
+
- image: cimg/ruby:2.7-node # use a tailored CircleCI docker image.
|
7
7
|
steps:
|
8
8
|
- checkout
|
9
9
|
|
10
|
+
- run: bundle config set path 'vendor/bundle'
|
11
|
+
- run: sudo apt-get update
|
12
|
+
- run: sudo apt install libsqlite3-dev
|
13
|
+
|
10
14
|
# There's probably a better way of doing this that avoids the repetition and manual
|
11
15
|
# deletion of Gemfile.lock.
|
12
16
|
- restore_cache:
|
13
|
-
key: rails-
|
17
|
+
key: rails-5.2.4.4-{{ checksum "Gemfile" }}
|
14
18
|
- run:
|
15
19
|
name: bundle install
|
16
|
-
command: bundle install
|
20
|
+
command: bundle install
|
17
21
|
environment:
|
18
|
-
ACTIVERECORD_VERSION:
|
22
|
+
ACTIVERECORD_VERSION: 5.2.4.4
|
19
23
|
- save_cache:
|
20
|
-
key: rails-
|
24
|
+
key: rails-5.2.4.4-{{ checksum "Gemfile" }}
|
21
25
|
paths:
|
22
26
|
- vendor/bundle
|
23
27
|
- run:
|
24
|
-
name: Test with Rails
|
28
|
+
name: Test with Rails 5.2
|
25
29
|
command: bundle exec rspec
|
26
30
|
|
27
31
|
- run: rm Gemfile.lock
|
28
32
|
- restore_cache:
|
29
|
-
key: rails-
|
33
|
+
key: rails-6.0.3.4-{{ checksum "Gemfile" }}
|
30
34
|
- run:
|
31
35
|
name: bundle install
|
32
36
|
command: bundle install --path vendor/bundle
|
33
37
|
environment:
|
34
|
-
ACTIVERECORD_VERSION:
|
38
|
+
ACTIVERECORD_VERSION: 6.0.3.4
|
35
39
|
- save_cache:
|
36
|
-
key: rails-
|
40
|
+
key: rails-6.0.3.4-{{ checksum "Gemfile" }}
|
37
41
|
paths:
|
38
42
|
- vendor/bundle
|
39
43
|
- restore_cache:
|
40
|
-
key: rails-
|
41
|
-
- run:
|
42
|
-
name: Test with Rails 5.0.6
|
43
|
-
command: bundle exec rspec
|
44
|
-
|
45
|
-
- run: rm Gemfile.lock
|
46
|
-
- restore_cache:
|
47
|
-
key: rails-5.1.4-{{ checksum "Gemfile" }}
|
48
|
-
- run:
|
49
|
-
name: bundle install
|
50
|
-
command: bundle install --path vendor/bundle
|
51
|
-
environment:
|
52
|
-
ACTIVERECORD_VERSION: 5.1.4
|
53
|
-
- save_cache:
|
54
|
-
key: rails-5.1.4-{{ checksum "Gemfile" }}
|
55
|
-
paths:
|
56
|
-
- vendor/bundle
|
44
|
+
key: rails-6.0.3.4-{{ checksum "Gemfile" }}
|
57
45
|
- run:
|
58
|
-
name: Test with Rails
|
46
|
+
name: Test with Rails 6.0
|
59
47
|
command: bundle exec rspec
|
@@ -19,13 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency "rails", ">=
|
22
|
+
s.add_dependency "rails", ">= 5.2"
|
23
23
|
s.add_dependency "dalli"
|
24
24
|
|
25
25
|
s.add_development_dependency "sqlite3"
|
26
26
|
s.add_development_dependency "rspec"
|
27
27
|
s.add_development_dependency "database_cleaner"
|
28
|
-
s.add_development_dependency "test_after_commit"
|
29
|
-
s.add_development_dependency "after_commit_exception_notification"
|
30
28
|
s.add_development_dependency "rake"
|
31
29
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module CachedCounts
|
2
|
+
class << self
|
3
|
+
# Optional configuration: Set a proc which takes as arguments (1) the class
|
4
|
+
# we are counting and (2) the block that runs the count query. The
|
5
|
+
# `query_context` block must call the block that's passed as an argument.
|
6
|
+
#
|
7
|
+
# This is useful for replication, e.g.,
|
8
|
+
#
|
9
|
+
# CachedCounts.query_context = proc do |klass, &run_query|
|
10
|
+
# role = klass == User ? :reading : :writing
|
11
|
+
# ActiveRecord::Base.connected_to(role: role) do
|
12
|
+
# run_query.call
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
attr_writer :query_context
|
16
|
+
|
17
|
+
def query_context
|
18
|
+
@query_context ||= proc { |_klass, &block| block.call }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cached_counts.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'cached_counts/logger'
|
2
|
-
require 'cached_counts/
|
3
|
-
require 'cached_counts/connection_for'
|
2
|
+
require 'cached_counts/query_context'
|
4
3
|
|
5
4
|
module CachedCounts
|
6
5
|
extend ActiveSupport::Concern
|
@@ -160,16 +159,6 @@ module CachedCounts
|
|
160
159
|
fallback = Rails.cache.read(key)
|
161
160
|
fallback = fallback.value if fallback.is_a?(ActiveSupport::Cache::Entry)
|
162
161
|
|
163
|
-
if fallback.nil?
|
164
|
-
begin
|
165
|
-
fallback = relation.count
|
166
|
-
rescue ActiveRecord::StatementInvalid => e
|
167
|
-
fallback = 0
|
168
|
-
end
|
169
|
-
|
170
|
-
Rails.cache.write key, fallback, expires_in: options.fetch(:expires_in, 1.week), raw: true
|
171
|
-
end
|
172
|
-
|
173
162
|
-> { fallback }
|
174
163
|
end
|
175
164
|
|
@@ -193,7 +182,7 @@ module CachedCounts
|
|
193
182
|
ids.each do |id|
|
194
183
|
result[id] = raw_result[association_count_key(id, attribute_name, version)]&.to_i || default
|
195
184
|
end
|
196
|
-
|
185
|
+
|
197
186
|
result
|
198
187
|
end
|
199
188
|
|
@@ -254,24 +243,24 @@ module CachedCounts
|
|
254
243
|
# Ensure that other reads find something in the cache, but
|
255
244
|
# continue calculating here because the default is likely inaccurate.
|
256
245
|
fallback_value = instance_exec &race_condition_fallback
|
257
|
-
|
258
|
-
|
259
|
-
send(key_method)
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
246
|
+
|
247
|
+
if fallback_value
|
248
|
+
CachedCounts.logger.warn "Setting #{fallback_value} as race_condition_fallback for #{send(key_method)}"
|
249
|
+
Rails.cache.write(
|
250
|
+
send(key_method),
|
251
|
+
fallback_value.to_i,
|
252
|
+
expires_in: 30.seconds,
|
253
|
+
raw: true
|
254
|
+
)
|
255
|
+
end
|
264
256
|
end
|
265
257
|
|
266
258
|
relation = instance_exec(&relation_getter)
|
267
259
|
relation = relation.reorder('')
|
268
260
|
relation.select_values = ['count(*)']
|
269
261
|
|
270
|
-
|
271
|
-
|
272
|
-
conn.select_value(relation.to_sql, nil, relation.values[:bind] || []).to_i
|
273
|
-
else
|
274
|
-
conn.select_value(relation.to_sql).to_i
|
262
|
+
CachedCounts.query_context.call(counted_class) do
|
263
|
+
counted_class.connection.select_value(relation.to_sql).to_i
|
275
264
|
end
|
276
265
|
end
|
277
266
|
|
data/spec/spec_helper.rb
CHANGED
@@ -3,7 +3,7 @@ require 'bundler/setup'
|
|
3
3
|
require 'pry'
|
4
4
|
require 'active_record'
|
5
5
|
require 'rails'
|
6
|
-
require 'active_support/cache/
|
6
|
+
require 'active_support/cache/mem_cache_store'
|
7
7
|
require 'cached_counts'
|
8
8
|
|
9
9
|
ActiveRecord::Base.configurations = YAML::load_file('spec/database.yml')
|
@@ -13,7 +13,7 @@ if ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks)
|
|
13
13
|
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
14
14
|
end
|
15
15
|
|
16
|
-
Rails.cache = ActiveSupport::Cache::
|
16
|
+
Rails.cache = ActiveSupport::Cache::MemCacheStore.new("localhost")
|
17
17
|
|
18
18
|
RSpec.configure do |config|
|
19
19
|
config.before(:each) do
|
@@ -25,13 +25,6 @@ end
|
|
25
25
|
require_relative './fixtures.rb'
|
26
26
|
require 'database_cleaner'
|
27
27
|
|
28
|
-
if Rails.version.to_f < 5.0
|
29
|
-
require 'test_after_commit'
|
30
|
-
end
|
31
|
-
if Rails.version.to_f < 4.2
|
32
|
-
require 'after_commit_exception_notification'
|
33
|
-
end
|
34
|
-
|
35
28
|
RSpec.configure do |config|
|
36
29
|
config.before(:suite) do
|
37
30
|
DatabaseCleaner.strategy = :transaction
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: incrdecr_cached_counts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Judd
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: dalli
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,34 +80,6 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: test_after_commit
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: after_commit_exception_notification
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
83
|
- !ruby/object:Gem::Dependency
|
112
84
|
name: rake
|
113
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,7 +104,6 @@ extra_rdoc_files: []
|
|
132
104
|
files:
|
133
105
|
- ".circleci/config.yml"
|
134
106
|
- ".gitignore"
|
135
|
-
- ".travis.yml"
|
136
107
|
- ".yardopts"
|
137
108
|
- Gemfile
|
138
109
|
- MIT-LICENSE
|
@@ -140,9 +111,8 @@ files:
|
|
140
111
|
- Rakefile
|
141
112
|
- incrdecr_cached_counts.gemspec
|
142
113
|
- lib/cached_counts.rb
|
143
|
-
- lib/cached_counts/connection_for.rb
|
144
|
-
- lib/cached_counts/dalli_check.rb
|
145
114
|
- lib/cached_counts/logger.rb
|
115
|
+
- lib/cached_counts/query_context.rb
|
146
116
|
- lib/cached_counts/railtie.rb
|
147
117
|
- lib/cached_counts/version.rb
|
148
118
|
- spec/caches_count_of_spec.rb
|
@@ -173,17 +143,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
143
|
- !ruby/object:Gem::Version
|
174
144
|
version: '0'
|
175
145
|
requirements: []
|
176
|
-
rubygems_version: 3.
|
146
|
+
rubygems_version: 3.1.4
|
177
147
|
signing_key:
|
178
148
|
specification_version: 4
|
179
149
|
summary: A replacement for Rails' counter caches using memcached (via Dalli)
|
180
|
-
test_files:
|
181
|
-
- spec/caches_count_of_spec.rb
|
182
|
-
- spec/caches_count_where_spec.rb
|
183
|
-
- spec/database.yml
|
184
|
-
- spec/fixtures.rb
|
185
|
-
- spec/fixtures/department.rb
|
186
|
-
- spec/fixtures/following.rb
|
187
|
-
- spec/fixtures/university.rb
|
188
|
-
- spec/fixtures/user.rb
|
189
|
-
- spec/spec_helper.rb
|
150
|
+
test_files: []
|
data/.travis.yml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
sudo: false # use newer travis infrastructure
|
2
|
-
language: ruby
|
3
|
-
rvm:
|
4
|
-
- "2.1.8"
|
5
|
-
- "2.2.4"
|
6
|
-
- "2.3.0"
|
7
|
-
env:
|
8
|
-
- "ACTIVERECORD_VERSION=4.2.6"
|
9
|
-
- "ACTIVERECORD_VERSION=4.1.15"
|
10
|
-
- "ACTIVERECORD_VERSION=4.0.13"
|
11
|
-
- "ACTIVERECORD_VERSION=master"
|
12
|
-
matrix:
|
13
|
-
allow_failures:
|
14
|
-
# Master may or may not pass
|
15
|
-
- env: "ACTIVERECORD_VERSION=master"
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module CachedCounts
|
2
|
-
class << self
|
3
|
-
# Optional configuration: set a proc which takes the class we are counting
|
4
|
-
# and returns a connection. Useful with replication, e.g. with Octopus:
|
5
|
-
#
|
6
|
-
# `CachedCounts.connection_for = proc { |klass| klass.using(:read_slave).connection }`
|
7
|
-
attr_writer :connection_for
|
8
|
-
|
9
|
-
def connection_for(counted_class)
|
10
|
-
@connection_for ||= proc { |klass| klass.connection }
|
11
|
-
@connection_for[counted_class]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|