tally 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfd6d7b4cdc084ad0d1f638ecbf06fe82909c8e437498abcc8d5987b03628f2f
4
- data.tar.gz: e30633b53c9ae6f9db7b324fb12d9da01a4416399c3c399c4a971a616e1429b6
3
+ metadata.gz: 2326dfbbdcb9474f788b14370829771c27cf8945d9a2c4c07208ef78a157bcfa
4
+ data.tar.gz: 852b21044a153ba21c0eb3f48f282a3157a55f4e535fed2006ea80652263f7b2
5
5
  SHA512:
6
- metadata.gz: f3774064bceec83d7b25ade9e3a68799b0676230392241335231ce8318c33bec2b311694f186f1322ea70cef586bf53c3aacef69ffcc02156d125841d015c6d1
7
- data.tar.gz: 9ee909f93c6e0c6430d6b0ffc21c865b7b94a44e7bdd40ab41c6b0ad5c39eef4109c2b52e313015b1cd78c369dc107a05543732746c0313b7e84007b90f7c269
6
+ metadata.gz: 16d1b206ded32742d3fc04973bb52fc066ba2618ee70a692e3b73322b0950957b34534bd9b3e6c5bfc555de5149ca9f61455265ed91d254962077ba0c689a20f
7
+ data.tar.gz: 5610ac5ba2038971c7aa9e3fb6694971a7cea354939c0a6c65e94515ca6757cc22f4e00a3c095671bf39321d40f6fd9471906a714077e44695be308eb9ac557c
data/README.md CHANGED
@@ -12,8 +12,8 @@ _[Read more about Tally in my blog post introducing it ...](https://johntornow.c
12
12
 
13
13
  ## Requirements
14
14
 
15
- * Ruby 2.2+
16
- * Rails 5.2.x+
15
+ * Ruby 3.0.3+
16
+ * Rails 6.1+
17
17
  * Redis 4+
18
18
 
19
19
  ## Installation
@@ -204,10 +204,31 @@ The endpoints can be used to display JSON-formatted data from `Tally::Record`. T
204
204
 
205
205
  Tally works _really_ well with [Sidekiq](https://github.com/mperham/sidekiq/), but it isn't required. If Sidekiq is installed in your app, Tally will use its connection pooling for Redis connections. If Sidekiq isn't in use, the `Redis.current` connection is used to store stats. If you'd like to override the specific connection used for Tally's redis store, you can do so by setting `Tally.redis_connection` to another instance of `Redis`. This can be useful to use an alternate Redis store for just stats, for example.
206
206
 
207
+ As of version 2.0.0 this connection is automatically used within a [ConnectionPool](https://github.com/mperham/connection_pool).
208
+
207
209
  ```ruby
208
210
  # use an alternate Redis connection (for non-sidekiq integrations)
209
211
  Tally.redis_connection = Redis.new(...)
210
212
  ```
213
+
214
+ Alternatively, you can just set the config for Redis and `Redis.new` will be called for you:
215
+
216
+ ```ruby
217
+ # provide Redis config
218
+ Tally.config.redis_config = {
219
+ driver: :ruby,
220
+ url: "redis://127.0.0.1:6379/10",
221
+ ssl_params: {
222
+ verify_mode: OpenSSL::SSL::VERIFY_NONE
223
+ }
224
+ }
225
+
226
+ # then Tally uses the connection within a pool:
227
+ Tally.redis do |connection|
228
+ connection.incr("test")
229
+ end
230
+ ```
231
+
211
232
  ## Issues
212
233
 
213
234
  If you have any issues or find bugs running Tally, please [report them on Github](https://github.com/jdtornow/tally/issues).
data/lib/tally/daily.rb CHANGED
@@ -10,26 +10,6 @@ module Tally
10
10
 
11
11
  private
12
12
 
13
- def all_keys
14
- @keys ||= build_keys_from_redis
15
- end
16
-
17
- def build_keys_from_redis
18
- result = []
19
- cursor = ""
20
-
21
- scan = scan_from_redis
22
-
23
- while cursor != "0"
24
- result << scan.last
25
- cursor = scan.first
26
-
27
- scan = scan_from_redis(cursor: cursor)
28
- end
29
-
30
- result.flatten
31
- end
32
-
33
13
  def day_key
34
14
  @day_key ||= day.strftime(Tally.config.date_format)
35
15
  end
@@ -39,8 +19,20 @@ module Tally
39
19
  end
40
20
 
41
21
  def scan_from_redis(cursor: "0")
42
- Tally.redis do |conn|
43
- conn.sscan(daily_key, cursor, match: scan_key, count: 25)
22
+ klass = Tally.redis { |conn| conn.class.to_s }
23
+
24
+ # if we're using sidekiq / RedisClient, scan needs a block, and doesn't worry about the cursor
25
+ if klass == "Sidekiq::RedisClientAdapter::CompatClient"
26
+ Tally.redis do |conn|
27
+ [
28
+ "0", # fake cursor to match redis-rb output
29
+ conn.sscan(daily_key, "MATCH", scan_key, "COUNT", 25).to_a
30
+ ]
31
+ end
32
+ else
33
+ Tally.redis do |conn|
34
+ conn.sscan(daily_key, cursor, match: scan_key, count: 25)
35
+ end
44
36
  end
45
37
  end
46
38
 
@@ -5,12 +5,12 @@ module Tally
5
5
 
6
6
  def increment(by = 1)
7
7
  Tally.redis do |conn|
8
- conn.multi do
9
- conn.incrby(redis_key, by)
10
- conn.expire(redis_key, Tally.config.ttl) if Tally.config.ttl.present?
8
+ conn.multi do |pipeline|
9
+ pipeline.incrby(redis_key, by)
10
+ pipeline.expire(redis_key, Tally.config.ttl.to_i) if Tally.config.ttl.present?
11
11
 
12
- conn.sadd(daily_key, simple_key)
13
- conn.expire(daily_key, Tally.config.ttl) if Tally.config.ttl.present?
12
+ pipeline.sadd(daily_key, simple_key)
13
+ pipeline.expire(daily_key, Tally.config.ttl.to_i) if Tally.config.ttl.present?
14
14
  end
15
15
  end
16
16
  end
@@ -73,18 +73,16 @@ module Tally
73
73
 
74
74
  def build_keys_from_redis
75
75
  result = []
76
- cursor = ""
77
-
78
- scan = scan_from_redis
76
+ cursor = nil
79
77
 
80
78
  while cursor != "0"
79
+ scan = scan_from_redis(cursor: cursor.presence || "0")
80
+
81
81
  result << scan.last
82
82
  cursor = scan.first
83
-
84
- scan = scan_from_redis(cursor: cursor)
85
83
  end
86
84
 
87
- result.flatten
85
+ result.flatten.uniq
88
86
  end
89
87
 
90
88
  def day_key
@@ -100,7 +98,19 @@ module Tally
100
98
  end
101
99
 
102
100
  def scan_from_redis(cursor: "0")
103
- Tally.redis { |conn| conn.scan(cursor, match: scan_key) }
101
+ klass = Tally.redis { |conn| conn.class.to_s }
102
+
103
+ # if we're using sidekiq / RedisClient, scan needs a block, and doesn't worry about the cursor
104
+ if klass == "Sidekiq::RedisClientAdapter::CompatClient"
105
+ Tally.redis do |conn|
106
+ [
107
+ "0", # fake cursor to match redis-rb output
108
+ conn.scan("MATCH", scan_key).to_a
109
+ ]
110
+ end
111
+ else
112
+ Tally.redis { |conn| conn.scan(cursor, match: scan_key) }
113
+ end
104
114
  end
105
115
 
106
116
  def scan_key
data/lib/tally/sweeper.rb CHANGED
@@ -22,10 +22,10 @@ module Tally
22
22
 
23
23
  def sweep!
24
24
  Tally.redis do |conn|
25
- purgeable_keys.in_groups_of(25, fill_with = nil).each do |group|
26
- conn.pipelined do
25
+ purgeable_keys.in_groups_of(25, fill_with = false).each do |group|
26
+ conn.pipelined do |pipeline|
27
27
  group.each do |key|
28
- conn.del(key)
28
+ pipeline.del(key)
29
29
  end
30
30
  end
31
31
  end
data/lib/tally/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Tally
2
2
 
3
- VERSION = "1.0.1"
3
+ VERSION = "2.0.0"
4
4
 
5
5
  end
data/lib/tally.rb CHANGED
@@ -46,6 +46,12 @@ module Tally
46
46
  # Archivers get queued into the background with ActiveJob by default
47
47
  # Set to :now to run inline
48
48
  config.perform_calculators = :later
49
+
50
+ # override to set default redis configuration for Tally when Sidekiq is not present
51
+ config.redis_config = {}
52
+
53
+ # override to set connection pool details for Redis
54
+ config.redis_pool_config = {}
49
55
  end
50
56
 
51
57
  # If sidekiq is available, piggyback on its pooling
@@ -57,18 +63,28 @@ module Tally
57
63
  if defined?(Sidekiq)
58
64
  Sidekiq.redis(&block)
59
65
  else
60
- block.call(redis_connection)
66
+ redis_pool.with(&block)
61
67
  end
62
68
  end
63
69
 
64
70
  def self.redis_connection
65
- @redis_connection ||= Redis.current
71
+ @redis_connection ||= Redis.new(Tally.config.redis_config)
66
72
  end
67
73
 
68
74
  def self.redis_connection=(connection)
69
75
  @redis_connection = connection
70
76
  end
71
77
 
78
+ def self.redis_pool
79
+ @redis_pool ||= ConnectionPool.new(Tally.config.redis_pool_config) do
80
+ redis_connection
81
+ end
82
+ end
83
+
84
+ def self.redis_pool=(pool)
85
+ @redis_pool = pool
86
+ end
87
+
72
88
  def self.increment(*args)
73
89
  Increment.public_send(:increment, *args)
74
90
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tally
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John D. Tornow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-21 00:00:00.000000000 Z
11
+ date: 2022-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 5.2.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '7'
22
+ version: '8'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 5.2.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '7'
32
+ version: '8'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: redis
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '4.1'
47
+ - !ruby/object:Gem::Dependency
48
+ name: connection_pool
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '2.0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: kaminari-activerecord
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +92,14 @@ dependencies:
78
92
  requirements:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
- version: '4.0'
95
+ version: '6'
82
96
  type: :development
83
97
  prerelease: false
84
98
  version_requirements: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
- version: '4.0'
102
+ version: '6'
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: factory_bot_rails
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -106,28 +120,14 @@ dependencies:
106
120
  requirements:
107
121
  - - "~>"
108
122
  - !ruby/object:Gem::Version
109
- version: '4.2'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '4.2'
117
- - !ruby/object:Gem::Dependency
118
- name: simplecov
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '0.11'
123
+ version: '5.1'
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.11'
130
+ version: '5.1'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: rspec_junit_formatter
133
133
  requirement: !ruby/object:Gem::Requirement
@@ -230,14 +230,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
230
230
  requirements:
231
231
  - - ">="
232
232
  - !ruby/object:Gem::Version
233
- version: 2.5.7
233
+ version: 3.0.3
234
234
  required_rubygems_version: !ruby/object:Gem::Requirement
235
235
  requirements:
236
236
  - - ">="
237
237
  - !ruby/object:Gem::Version
238
238
  version: 1.8.11
239
239
  requirements: []
240
- rubygems_version: 3.2.32
240
+ rubygems_version: 3.3.26
241
241
  signing_key:
242
242
  specification_version: 4
243
243
  summary: Stats collection and reporting