redis-time-series 0.5.2 → 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/.github/workflows/rspec.yml +10 -4
- data/.gitignore +1 -0
- data/Appraisals +7 -0
- data/CHANGELOG.md +7 -0
- data/lib/redis-time-series.rb +2 -0
- data/lib/redis/time_series.rb +39 -10
- data/lib/redis/time_series/duplicate_policy.rb +49 -0
- data/lib/redis/time_series/errors.rb +5 -0
- data/lib/redis/time_series/info.rb +41 -14
- data/lib/redis/time_series/version.rb +1 -1
- data/redis-time-series.gemspec +3 -2
- metadata +35 -14
- data/Gemfile.lock +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4648678522434687a6e278490c7a308c64f6460394b8ebde16b2ce2daa9e92ad
|
4
|
+
data.tar.gz: e2f48fb1c8efebb3b4d6e4c47d1d86137a10ac8a54735c94b3bdb35ef6396651
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 269a787d8d2a2a467a52e915ab717bc5b20eb28cacc55eb5dfc9ce3909a7d83cdd4e15b19afc92612d19fa551c6ba793df76ceef03d8bb8bdb16b6dc0253d2cc
|
7
|
+
data.tar.gz: c5d845052ca8f2a518fb3a20a82a8d8aa35128cb824f54d2531a949767e90f8c7979ede07ba1bd56ae30a825edb9f6be90e52ca404a14199bfd13484026d8d40
|
data/.github/workflows/rspec.yml
CHANGED
@@ -11,9 +11,13 @@ on:
|
|
11
11
|
jobs:
|
12
12
|
spec:
|
13
13
|
runs-on: ubuntu-latest
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
image_version: ['latest', 'edge']
|
17
|
+
ruby_version: ['2.6', '2.7']
|
14
18
|
services:
|
15
19
|
redis:
|
16
|
-
image: redislabs/redistimeseries
|
20
|
+
image: redislabs/redistimeseries:${{ matrix.image_version }}
|
17
21
|
ports:
|
18
22
|
- 6379:6379/tcp
|
19
23
|
env:
|
@@ -25,16 +29,18 @@ jobs:
|
|
25
29
|
- name: Set up Ruby
|
26
30
|
uses: ruby/setup-ruby@v1
|
27
31
|
with:
|
28
|
-
ruby-version:
|
32
|
+
ruby-version: ${{ matrix.ruby_version }}
|
29
33
|
- name: Set up CodeClimate
|
30
34
|
run: |
|
31
35
|
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
32
36
|
chmod +x ./cc-test-reporter
|
33
37
|
./cc-test-reporter before-build
|
34
38
|
- name: Install dependencies
|
35
|
-
run:
|
39
|
+
run: |
|
40
|
+
bundle install
|
41
|
+
bundle exec appraisal install
|
36
42
|
- name: Run specs
|
37
|
-
run: bundle exec rake spec
|
43
|
+
run: bundle exec appraisal rake spec
|
38
44
|
- name: Upload coverage report
|
39
45
|
run: ./cc-test-reporter after-build -t simplecov coverage/.resultset.json
|
40
46
|
- uses: actions/upload-artifact@v2
|
data/.gitignore
CHANGED
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 0.6.0
|
6
|
+
* Add CHUNK_SIZE param to CREATE, ADD, INCRBY, DECRBY commands (#53)
|
7
|
+
* Add duplication policy to TS.CREATE and TS.ADD commands (#51)
|
8
|
+
* Add support for endless ranges to TS.RANGE (#50)
|
9
|
+
* Cast label values to integers in Info struct (#49)
|
10
|
+
* Build against edge upstream in addition to latest stable (#48)
|
11
|
+
|
5
12
|
## 0.5.2
|
6
13
|
* Add chunk_type to info struct (#47)
|
7
14
|
|
data/lib/redis-time-series.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'forwardable'
|
3
3
|
require 'ext/time_msec'
|
4
|
+
|
4
5
|
require 'redis/time_series/client'
|
5
6
|
require 'redis/time_series/errors'
|
6
7
|
require 'redis/time_series/aggregation'
|
8
|
+
require 'redis/time_series/duplicate_policy'
|
7
9
|
require 'redis/time_series/filters'
|
8
10
|
require 'redis/time_series/rule'
|
9
11
|
require 'redis/time_series/info'
|
data/lib/redis/time_series.rb
CHANGED
@@ -37,6 +37,11 @@ class Redis
|
|
37
37
|
# With no value, the series will not be trimmed.
|
38
38
|
# @option options [Boolean] :uncompressed
|
39
39
|
# When true, series data will be stored in an uncompressed format.
|
40
|
+
# @option options [String, Symbol] :duplicate_policy
|
41
|
+
# A duplication policy to resolve conflicts when adding values to the series.
|
42
|
+
# Valid values are in Redis::TimeSeries::DuplicatePolicy::VALID_POLICIES
|
43
|
+
# @option options [Integer] :chunk_size
|
44
|
+
# Amount of memory, in bytes, to allocate for each chunk of data
|
40
45
|
#
|
41
46
|
# @return [Redis::TimeSeries] the created time series
|
42
47
|
# @see https://oss.redislabs.com/redistimeseries/commands/#tscreate
|
@@ -154,21 +159,33 @@ class Redis
|
|
154
159
|
# @param value [Numeric] the value to add
|
155
160
|
# @param timestamp [Time, Numeric] the +Time+, or integer timestamp in milliseconds, to add the value
|
156
161
|
# @param uncompressed [Boolean] if true, stores data in an uncompressed format
|
162
|
+
# @param on_duplicate [String, Symbol] a duplication policy for conflict resolution
|
163
|
+
# @param chunk_size [Integer] set default chunk size, in bytes, for the time series
|
157
164
|
#
|
158
165
|
# @return [Sample] the value that was added
|
159
166
|
# @raise [Redis::CommandError] if the value being added is older than the latest timestamp in the series
|
160
|
-
|
161
|
-
|
167
|
+
#
|
168
|
+
# @see TimeSeries::DuplicatePolicy
|
169
|
+
def add(value, timestamp = '*', uncompressed: nil, on_duplicate: nil, chunk_size: nil)
|
170
|
+
ts = cmd 'TS.ADD',
|
171
|
+
key,
|
172
|
+
timestamp,
|
173
|
+
value,
|
174
|
+
('UNCOMPRESSED' if uncompressed),
|
175
|
+
(['CHUNK_SIZE', chunk_size] if chunk_size),
|
176
|
+
(DuplicatePolicy.new(on_duplicate).to_a('ON_DUPLICATE') if on_duplicate)
|
162
177
|
Sample.new(ts, value)
|
163
178
|
end
|
164
179
|
|
165
180
|
# Issues a TS.CREATE command for the current series.
|
166
181
|
# You should use class method {Redis::TimeSeries.create} instead.
|
167
182
|
# @api private
|
168
|
-
def create(retention: nil, uncompressed: nil, labels: nil)
|
183
|
+
def create(retention: nil, uncompressed: nil, labels: nil, duplicate_policy: nil, chunk_size: nil)
|
169
184
|
cmd 'TS.CREATE', key,
|
170
185
|
(['RETENTION', retention] if retention),
|
171
186
|
('UNCOMPRESSED' if uncompressed),
|
187
|
+
(['CHUNK_SIZE', chunk_size] if chunk_size),
|
188
|
+
(DuplicatePolicy.new(duplicate_policy).to_a if duplicate_policy),
|
172
189
|
(['LABELS', labels.to_a] if labels&.any?)
|
173
190
|
self
|
174
191
|
end
|
@@ -206,11 +223,17 @@ class Redis
|
|
206
223
|
# @param value [Integer] the amount to decrement by
|
207
224
|
# @param timestamp [Time, Integer] the Time or integer millisecond timestamp to save the new value at
|
208
225
|
# @param uncompressed [Boolean] if true, stores data in an uncompressed format
|
226
|
+
# @param chunk_size [Integer] set default chunk size, in bytes, for the time series
|
209
227
|
#
|
210
228
|
# @return [Integer] the timestamp the value was stored at
|
211
229
|
# @see https://oss.redislabs.com/redistimeseries/commands/#tsincrbytsdecrby
|
212
|
-
def decrby(value = 1, timestamp = nil, uncompressed: nil)
|
213
|
-
cmd 'TS.DECRBY',
|
230
|
+
def decrby(value = 1, timestamp = nil, uncompressed: nil, chunk_size: nil)
|
231
|
+
cmd 'TS.DECRBY',
|
232
|
+
key,
|
233
|
+
value,
|
234
|
+
(timestamp if timestamp),
|
235
|
+
('UNCOMPRESSED' if uncompressed),
|
236
|
+
(['CHUNK_SIZE', chunk_size] if chunk_size)
|
214
237
|
end
|
215
238
|
alias decrement decrby
|
216
239
|
|
@@ -241,11 +264,17 @@ class Redis
|
|
241
264
|
# @param value [Integer] the amount to increment by
|
242
265
|
# @param timestamp [Time, Integer] the Time or integer millisecond timestamp to save the new value at
|
243
266
|
# @param uncompressed [Boolean] if true, stores data in an uncompressed format
|
267
|
+
# @param chunk_size [Integer] set default chunk size, in bytes, for the time series
|
244
268
|
#
|
245
269
|
# @return [Integer] the timestamp the value was stored at
|
246
270
|
# @see https://oss.redislabs.com/redistimeseries/commands/#tsincrbytsdecrby
|
247
|
-
def incrby(value = 1, timestamp = nil, uncompressed: nil)
|
248
|
-
cmd 'TS.INCRBY',
|
271
|
+
def incrby(value = 1, timestamp = nil, uncompressed: nil, chunk_size: nil)
|
272
|
+
cmd 'TS.INCRBY',
|
273
|
+
key,
|
274
|
+
value,
|
275
|
+
(timestamp if timestamp),
|
276
|
+
('UNCOMPRESSED' if uncompressed),
|
277
|
+
(['CHUNK_SIZE', chunk_size] if chunk_size)
|
249
278
|
end
|
250
279
|
alias increment incrby
|
251
280
|
|
@@ -312,12 +341,12 @@ class Redis
|
|
312
341
|
# `range` will swallow all parameters if they're all hash syntax
|
313
342
|
count = range.delete(:count)
|
314
343
|
aggregation = range.delete(:aggregation)
|
315
|
-
range = range.fetch(:from)..range
|
344
|
+
range = range.fetch(:from)..range[:to]
|
316
345
|
end
|
317
346
|
cmd('TS.RANGE',
|
318
347
|
key,
|
319
|
-
range.
|
320
|
-
range.
|
348
|
+
(range.begin || '-'),
|
349
|
+
(range.end || '+'),
|
321
350
|
(['COUNT', count] if count),
|
322
351
|
Aggregation.parse(aggregation)&.to_a
|
323
352
|
).map { |ts, val| Sample.new(ts, val) }
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class Redis
|
3
|
+
class TimeSeries
|
4
|
+
# Duplication policies can be applied to a time series in order to resolve conflicts
|
5
|
+
# when adding data that already exists in the series.
|
6
|
+
#
|
7
|
+
# @see https://oss.redislabs.com/redistimeseries/master/configuration/#duplicate_policy
|
8
|
+
class DuplicatePolicy
|
9
|
+
VALID_POLICIES = %i[
|
10
|
+
block
|
11
|
+
first
|
12
|
+
last
|
13
|
+
min
|
14
|
+
max
|
15
|
+
sum
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
attr_reader :policy
|
19
|
+
|
20
|
+
def initialize(policy)
|
21
|
+
policy = policy.to_s.downcase.to_sym
|
22
|
+
if VALID_POLICIES.include?(policy)
|
23
|
+
@policy = policy
|
24
|
+
else
|
25
|
+
raise UnknownPolicyError, "#{policy} is not a valid duplicate policy"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_a(cmd = 'DUPLICATE_POLICY')
|
30
|
+
[cmd, policy]
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s(cmd = 'DUPLICATE_POLICY')
|
34
|
+
to_a(cmd).join(' ')
|
35
|
+
end
|
36
|
+
|
37
|
+
def ==(other)
|
38
|
+
return policy == other.policy if other.is_a?(self.class)
|
39
|
+
policy == self.class.new(other).policy
|
40
|
+
end
|
41
|
+
|
42
|
+
VALID_POLICIES.each do |policy|
|
43
|
+
define_method("#{policy}?") do
|
44
|
+
@policy == policy
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -15,5 +15,10 @@ class Redis
|
|
15
15
|
# an unknown type, or when calling a command with an invalid aggregation value.
|
16
16
|
# @see Redis::TimeSeries::Aggregation
|
17
17
|
class AggregationError < Error; end
|
18
|
+
|
19
|
+
# +UnknownPolicyError+ is raised when attempting to apply an unkown type of
|
20
|
+
# duplicate policy when creating or adding to a series.
|
21
|
+
# @see Redis::TimeSeries::DuplicatePolicy
|
22
|
+
class UnknownPolicyError < Error; end
|
18
23
|
end
|
19
24
|
end
|
@@ -10,6 +10,10 @@ class Redis
|
|
10
10
|
#
|
11
11
|
# @!attribute [r] chunk_count
|
12
12
|
# @return [Integer] number of memory chunks used for the time-series
|
13
|
+
# @!attribute [r] chunk_size
|
14
|
+
# @return [Integer] amount of allocated memory in bytes
|
15
|
+
# @!attribute [r] chunk_type
|
16
|
+
# @return [String] whether the chunk is "compressed" or "uncompressed"
|
13
17
|
# @!attribute [r] first_timestamp
|
14
18
|
# @return [Integer] first timestamp present in the time-series (milliseconds since epoch)
|
15
19
|
# @!attribute [r] labels
|
@@ -52,20 +56,43 @@ class Redis
|
|
52
56
|
:total_samples,
|
53
57
|
keyword_init: true
|
54
58
|
) do
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
class << self
|
60
|
+
# @api private
|
61
|
+
# @return [Info]
|
62
|
+
def parse(series:, data:)
|
63
|
+
build_hash(data)
|
64
|
+
.merge(series: series)
|
65
|
+
.then(&method(:parse_labels))
|
66
|
+
.then(&method(:parse_policies))
|
67
|
+
.then(&method(:parse_rules))
|
68
|
+
.then(&method(:new))
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def build_hash(data)
|
74
|
+
data.each_slice(2).reduce({}) do |h, (key, value)|
|
75
|
+
# Convert camelCase info keys to snake_case
|
76
|
+
key = key.gsub(/(.)([A-Z])/,'\1_\2').downcase.to_sym
|
77
|
+
# Skip unknown properties
|
78
|
+
next h unless members.include?(key)
|
79
|
+
h.merge(key => value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse_labels(hash)
|
84
|
+
hash[:labels] = hash[:labels].to_h.transform_values { |v| v.to_i.to_s == v ? v.to_i : v }
|
85
|
+
hash
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_policies(hash)
|
89
|
+
hash[:duplicate_policy] = DuplicatePolicy.new(hash[:duplicate_policy]) if hash[:duplicate_policy]
|
90
|
+
hash
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse_rules(hash)
|
94
|
+
hash[:rules] = hash[:rules].map { |d| Rule.new(source: hash[:series], data: d) }
|
95
|
+
hash
|
69
96
|
end
|
70
97
|
end
|
71
98
|
|
data/redis-time-series.gemspec
CHANGED
@@ -31,10 +31,11 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
32
|
spec.require_paths = ['lib']
|
33
33
|
|
34
|
-
spec.add_dependency 'redis', '
|
34
|
+
spec.add_dependency 'redis', '>= 3.3', '< 5'
|
35
35
|
|
36
36
|
spec.add_development_dependency 'activesupport', '~> 6.0'
|
37
|
-
spec.add_development_dependency '
|
37
|
+
spec.add_development_dependency 'appraisal'
|
38
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
38
39
|
spec.add_development_dependency 'pry', '~> 0.13'
|
39
40
|
spec.add_development_dependency 'rake', '~> 13.0'
|
40
41
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-time-series
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Duszynski
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.3'
|
20
|
+
- - "<"
|
18
21
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
22
|
+
version: '5'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
29
|
+
version: '3.3'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: activesupport
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,20 +44,34 @@ dependencies:
|
|
38
44
|
- - "~>"
|
39
45
|
- !ruby/object:Gem::Version
|
40
46
|
version: '6.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: appraisal
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
41
61
|
- !ruby/object:Gem::Dependency
|
42
62
|
name: bundler
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
44
64
|
requirements:
|
45
65
|
- - "~>"
|
46
66
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
67
|
+
version: '2.0'
|
48
68
|
type: :development
|
49
69
|
prerelease: false
|
50
70
|
version_requirements: !ruby/object:Gem::Requirement
|
51
71
|
requirements:
|
52
72
|
- - "~>"
|
53
73
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
74
|
+
version: '2.0'
|
55
75
|
- !ruby/object:Gem::Dependency
|
56
76
|
name: pry
|
57
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,7 +128,7 @@ dependencies:
|
|
108
128
|
- - "<"
|
109
129
|
- !ruby/object:Gem::Version
|
110
130
|
version: '0.18'
|
111
|
-
description:
|
131
|
+
description:
|
112
132
|
email:
|
113
133
|
- dzunk@hey.com
|
114
134
|
executables: []
|
@@ -118,9 +138,9 @@ files:
|
|
118
138
|
- ".github/workflows/rspec.yml"
|
119
139
|
- ".gitignore"
|
120
140
|
- ".rspec"
|
141
|
+
- Appraisals
|
121
142
|
- CHANGELOG.md
|
122
143
|
- Gemfile
|
123
|
-
- Gemfile.lock
|
124
144
|
- LICENSE.txt
|
125
145
|
- README.md
|
126
146
|
- Rakefile
|
@@ -131,6 +151,7 @@ files:
|
|
131
151
|
- lib/redis/time_series.rb
|
132
152
|
- lib/redis/time_series/aggregation.rb
|
133
153
|
- lib/redis/time_series/client.rb
|
154
|
+
- lib/redis/time_series/duplicate_policy.rb
|
134
155
|
- lib/redis/time_series/errors.rb
|
135
156
|
- lib/redis/time_series/filters.rb
|
136
157
|
- lib/redis/time_series/info.rb
|
@@ -145,7 +166,7 @@ metadata:
|
|
145
166
|
homepage_uri: https://github.com/dzunk/redis-time-series
|
146
167
|
source_code_uri: https://github.com/dzunk/redis-time-series
|
147
168
|
changelog_uri: https://github.com/dzunk/redis-time-series/blob/master/CHANGELOG.md
|
148
|
-
post_install_message:
|
169
|
+
post_install_message:
|
149
170
|
rdoc_options: []
|
150
171
|
require_paths:
|
151
172
|
- lib
|
@@ -160,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
181
|
- !ruby/object:Gem::Version
|
161
182
|
version: '0'
|
162
183
|
requirements: []
|
163
|
-
rubygems_version: 3.
|
164
|
-
signing_key:
|
184
|
+
rubygems_version: 3.2.2
|
185
|
+
signing_key:
|
165
186
|
specification_version: 4
|
166
187
|
summary: A Ruby adapter for the RedisTimeSeries module.
|
167
188
|
test_files: []
|
data/Gemfile.lock
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
redis-time-series (0.5.2)
|
5
|
-
redis (~> 4.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activesupport (6.0.3.1)
|
11
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
-
i18n (>= 0.7, < 2)
|
13
|
-
minitest (~> 5.1)
|
14
|
-
tzinfo (~> 1.1)
|
15
|
-
zeitwerk (~> 2.2, >= 2.2.2)
|
16
|
-
coderay (1.1.3)
|
17
|
-
concurrent-ruby (1.1.6)
|
18
|
-
diff-lcs (1.3)
|
19
|
-
docile (1.3.2)
|
20
|
-
i18n (1.8.3)
|
21
|
-
concurrent-ruby (~> 1.0)
|
22
|
-
json (2.3.1)
|
23
|
-
method_source (1.0.0)
|
24
|
-
minitest (5.14.1)
|
25
|
-
pry (0.13.1)
|
26
|
-
coderay (~> 1.1)
|
27
|
-
method_source (~> 1.0)
|
28
|
-
rake (13.0.1)
|
29
|
-
redis (4.2.2)
|
30
|
-
rspec (3.9.0)
|
31
|
-
rspec-core (~> 3.9.0)
|
32
|
-
rspec-expectations (~> 3.9.0)
|
33
|
-
rspec-mocks (~> 3.9.0)
|
34
|
-
rspec-core (3.9.2)
|
35
|
-
rspec-support (~> 3.9.3)
|
36
|
-
rspec-expectations (3.9.2)
|
37
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.9.0)
|
39
|
-
rspec-mocks (3.9.1)
|
40
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
-
rspec-support (~> 3.9.0)
|
42
|
-
rspec-support (3.9.3)
|
43
|
-
simplecov (0.17.1)
|
44
|
-
docile (~> 1.1)
|
45
|
-
json (>= 1.8, < 3)
|
46
|
-
simplecov-html (~> 0.10.0)
|
47
|
-
simplecov-html (0.10.2)
|
48
|
-
thread_safe (0.3.6)
|
49
|
-
tzinfo (1.2.7)
|
50
|
-
thread_safe (~> 0.1)
|
51
|
-
zeitwerk (2.3.0)
|
52
|
-
|
53
|
-
PLATFORMS
|
54
|
-
ruby
|
55
|
-
|
56
|
-
DEPENDENCIES
|
57
|
-
activesupport (~> 6.0)
|
58
|
-
bundler (~> 1.17)
|
59
|
-
pry (~> 0.13)
|
60
|
-
rake (~> 13.0)
|
61
|
-
redis-time-series!
|
62
|
-
rspec (~> 3.0)
|
63
|
-
simplecov (< 0.18)
|
64
|
-
|
65
|
-
BUNDLED WITH
|
66
|
-
1.17.2
|