redis-time-series 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e2bb0c44197c39258529e093bb34aa0a04576743c4f3d07016f607f9d84cd15e
4
+ data.tar.gz: 95ce400fcbbdeff4adcd326dd3927f535410be3180526c34068926c1908ac447
5
+ SHA512:
6
+ metadata.gz: ea5a10679174714e5f7ad63fe00f093c0d65c2c5954d11c19ea5a6b52a1660d897cb63e8ba6f6c037ca7f31e5281857f90a9fe2485dc0b401d37f281bd82ec70
7
+ data.tar.gz: c3cfb8e9632e9876b7cb39888fe89aab86e8becda9b64f3c6c2f4f78e4c58f59595255111820e89914c46a1a29d0a25c8c50f80c6b4311bb60e5b5141137c400
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
File without changes
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ redis-time-series (0.1.0)
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
+ i18n (1.8.3)
20
+ concurrent-ruby (~> 1.0)
21
+ method_source (1.0.0)
22
+ minitest (5.14.1)
23
+ pry (0.13.1)
24
+ coderay (~> 1.1)
25
+ method_source (~> 1.0)
26
+ rake (13.0.1)
27
+ redis (4.1.4)
28
+ rspec (3.9.0)
29
+ rspec-core (~> 3.9.0)
30
+ rspec-expectations (~> 3.9.0)
31
+ rspec-mocks (~> 3.9.0)
32
+ rspec-core (3.9.2)
33
+ rspec-support (~> 3.9.3)
34
+ rspec-expectations (3.9.2)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.9.0)
37
+ rspec-mocks (3.9.1)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.9.0)
40
+ rspec-support (3.9.3)
41
+ thread_safe (0.3.6)
42
+ tzinfo (1.2.7)
43
+ thread_safe (~> 0.1)
44
+ zeitwerk (2.3.0)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ activesupport (~> 6.0)
51
+ bundler (~> 1.17)
52
+ pry (~> 0.13)
53
+ rake (~> 13.0)
54
+ redis-time-series!
55
+ rspec (~> 3.0)
56
+
57
+ BUNDLED WITH
58
+ 1.17.2
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Matt Duszynski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,151 @@
1
+ # RedisTimeSeries
2
+
3
+ A Ruby adapter for the [RedisTimeSeries module](https://oss.redislabs.com/redistimeseries).
4
+
5
+ This doesn't work with vanilla Redis, you need the time series module compiled and installed. Try it with Docker, and see the [module setup guide](https://oss.redislabs.com/redistimeseries/#setup) for additional options.
6
+ ```
7
+ docker run -p 6379:6379 -it --rm redislabs/redistimeseries
8
+ ```
9
+
10
+
11
+ **TL;DR**
12
+ ```ruby
13
+ ts = Redis::TimeSeries.new('foo')
14
+ ts.add 1234
15
+ => #<Redis::TimeSeries::Sample:0x00007f8c0d2561d8 @time=2020-06-25 23:23:04 -0700, @value=0.1234e4>
16
+ ts.add 56
17
+ => #<Redis::TimeSeries::Sample:0x00007f8c0d26c460 @time=2020-06-25 23:23:16 -0700, @value=0.56e2>
18
+ ts.add 78
19
+ => #<Redis::TimeSeries::Sample:0x00007f8c0d276618 @time=2020-06-25 23:23:20 -0700, @value=0.78e2>
20
+ ts.range (Time.now.to_i - 100)..Time.now.to_i
21
+ => [#<Redis::TimeSeries::Sample:0x00007f8c0d297200 @time=2020-06-25 23:23:04 -0700, @value=0.1234e4>,
22
+ #<Redis::TimeSeries::Sample:0x00007f8c0d297048 @time=2020-06-25 23:23:16 -0700, @value=0.56e2>,
23
+ #<Redis::TimeSeries::Sample:0x00007f8c0d296e90 @time=2020-06-25 23:23:20 -0700, @value=0.78e2>]
24
+ ```
25
+
26
+ ## Installation
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem 'redis-time-series'
32
+ ```
33
+
34
+ And then execute:
35
+
36
+ $ bundle
37
+
38
+ Or install it yourself as:
39
+
40
+ $ gem install redis-time-series
41
+
42
+ ## Usage
43
+
44
+ Check out the Redis Time Series [command documentation](https://oss.redislabs.com/redistimeseries/master/commands/) first. Should be able to do most of that.
45
+
46
+ ### Creating a Series
47
+ Create a series (issues `TS.CREATE` command) and return a Redis::TimeSeries object for further use. Key param is required, all other arguments are optional.
48
+ ```ruby
49
+ ts = Redis::TimeSeries.create(
50
+ 'your_ts_key',
51
+ labels: ['foo', 'bar'],
52
+ retention: 600,
53
+ uncompressed: false,
54
+ redis: Redis.new(url: ENV['REDIS_URL']) # defaults to Redis.current
55
+ )
56
+ ```
57
+ You can also call `.new` instead of `.create` to skip the `TS.CREATE` command.
58
+ ```ruby
59
+ ts = Redis::TimeSeries.new('your_ts_key')
60
+ ```
61
+
62
+ ### Adding Data to a Series
63
+ Add a single value
64
+ ```ruby
65
+ ts.add 1234
66
+ => #<Redis::TimeSeries::Sample:0x00007f8c0ea7edc8 @time=2020-06-25 23:41:29 -0700, @value=0.1234e4>
67
+ ```
68
+ Add a single value with a timestamp
69
+ ```ruby
70
+ ts.add 1234, 3.minutes.ago # Used ActiveSupport here, but any Time object works fine
71
+ => #<Redis::TimeSeries::Sample:0x00007fa6ce05f3f8 @time=2020-06-25 23:39:54 -0700, @value=0.1234e4>
72
+ ```
73
+ Add multiple values with timestamps
74
+ ```ruby
75
+ ts.madd(2.minutes.ago => 12, 1.minute.ago => 34, Time.now => 56)
76
+ => [1593153909466, 1593153969466, 1593154029466]
77
+ ```
78
+ Increment or decrement the most recent value
79
+ ```ruby
80
+ ts.incrby 2
81
+ => 1593154222877
82
+ ts.decrby 1
83
+ => 1593154251392
84
+ ts.increment # alias of incrby
85
+ => 1593154255069
86
+ ts.decrement # alias of decrby
87
+ => 1593154257344
88
+ ```
89
+ ```ruby
90
+ ts.get
91
+ => #<Redis::TimeSeries::Sample:0x00007fa25f17ed88 @time=2020-06-25 23:50:57 -0700, @value=0.57e2>
92
+ ts.increment
93
+ => 1593154290736
94
+ ts.get
95
+ => #<Redis::TimeSeries::Sample:0x00007fa25f199480 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>
96
+ ```
97
+ Add values to multiple series
98
+ ```ruby
99
+ # Without timestamp (series named "foo" and "bar")
100
+ Redis::TimeSeries.madd(foo: 1234, bar: 5678)
101
+ => [#<Redis::TimeSeries::Sample:0x00007ffb3aa32ae0 @time=2020-06-26 00:09:15 -0700, @value=0.1234e4>,
102
+ #<Redis::TimeSeries::Sample:0x00007ffb3aa326d0 @time=2020-06-26 00:09:15 -0700, @value=0.5678e4>]
103
+ ```
104
+ ```ruby
105
+ # With a timestamp
106
+ Redis::TimeSeries.madd(foo: { 1.minute.ago => 1234 }, bar: { 1.minute.ago => 2345 })
107
+ => [#<Redis::TimeSeries::Sample:0x00007fb102431f88 @time=2020-06-26 00:10:22 -0700, @value=0.1234e4>,
108
+ #<Redis::TimeSeries::Sample:0x00007fb102431d80 @time=2020-06-26 00:10:22 -0700, @value=0.2345e4>]
109
+ ```
110
+
111
+ ### Querying a Series
112
+ Get the most recent value
113
+ ```ruby
114
+ ts.get
115
+ => #<Redis::TimeSeries::Sample:0x00007fa25f1b78b8 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>
116
+ ```
117
+ Get a range of values
118
+ ```ruby
119
+ ts.range 10.minutes.ago..Time.current # Time range as an argument
120
+ => [#<Redis::TimeSeries::Sample:0x00007fa25f13fc28 @time=2020-06-25 23:50:51 -0700, @value=0.57e2>,
121
+ #<Redis::TimeSeries::Sample:0x00007fa25f13db58 @time=2020-06-25 23:50:55 -0700, @value=0.58e2>,
122
+ #<Redis::TimeSeries::Sample:0x00007fa25f13d900 @time=2020-06-25 23:50:57 -0700, @value=0.57e2>,
123
+ #<Redis::TimeSeries::Sample:0x00007fa25f13d680 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>]
124
+ ts.range from: 10.minutes.ago, to: Time.current # Time range as keyword args
125
+ => [#<Redis::TimeSeries::Sample:0x00007fa25dc01f00 @time=2020-06-25 23:50:51 -0700, @value=0.57e2>,
126
+ #<Redis::TimeSeries::Sample:0x00007fa25dc01d20 @time=2020-06-25 23:50:55 -0700, @value=0.58e2>,
127
+ #<Redis::TimeSeries::Sample:0x00007fa25dc01b68 @time=2020-06-25 23:50:57 -0700, @value=0.57e2>,
128
+ #<Redis::TimeSeries::Sample:0x00007fa25dc019b0 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>]
129
+ ```
130
+
131
+ ### TODO
132
+ * `TS.REVRANGE`
133
+ * `TS.MRANGE`/`TS.MREVRANGE`
134
+ * `TS.QUERYINDEX`
135
+ * Compaction rules
136
+ * Filters
137
+ * Probably a bunch more stuff
138
+
139
+ ## Development
140
+
141
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
142
+
143
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
144
+
145
+ ## Contributing
146
+
147
+ Bug reports and pull requests are welcome on GitHub at https://github.com/dzunk/redis-time-series.
148
+
149
+ ## License
150
+
151
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'active_support/core_ext/numeric/time'
5
+ require 'pry'
6
+ require 'redis-time-series'
7
+
8
+ Redis.current.flushall
9
+
10
+ @ts1 = Redis::TimeSeries.create('foo')
11
+ @ts2 = Redis::TimeSeries.create('bar')
12
+ @ts3 = Redis::TimeSeries.create('baz')
13
+
14
+ @series = [@ts1, @ts2, @ts3]
15
+ @series.each do |ts|
16
+ 3.times { ts.increment }
17
+ end
18
+
19
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,9 @@
1
+ require 'bigdecimal'
2
+ require 'time/msec'
3
+ require 'redis'
4
+ require 'redis/time_series'
5
+ require 'redis/time_series/sample'
6
+
7
+ class RedisTimeSeries
8
+ VERSION = '0.1.0'
9
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+ class Redis
3
+ class TimeSeries
4
+ class << self
5
+ def create(key, **options)
6
+ new(key, **options).create
7
+ end
8
+
9
+ def madd(data)
10
+ data.reduce([]) do |memo, (key, value)|
11
+ if value.is_a?(Hash) || (value.is_a?(Array) && value.first.is_a?(Array))
12
+ # multiple timestamp => value pairs
13
+ value.each do |timestamp, nested_value|
14
+ timestamp = timestamp.ts_msec if timestamp.is_a? Time
15
+ memo << [key, timestamp, nested_value]
16
+ end
17
+ elsif value.is_a? Array
18
+ # single [timestamp, value]
19
+ key = key.ts_msec if key.is_a? Time
20
+ memo << [key, value]
21
+ else
22
+ # single value, no timestamp
23
+ memo << [key, '*', value]
24
+ end
25
+ memo
26
+ end.then do |args|
27
+ puts "DEBUG: TS.MADD #{args.join(' ')}" if ENV['DEBUG']
28
+ redis.call('TS.MADD', args.flatten).each_with_index.map do |result, idx|
29
+ result.is_a?(Redis::CommandError) ? result : Sample.new(result, args[idx][2])
30
+ end
31
+ end
32
+ end
33
+
34
+ def redis
35
+ @redis ||= Redis.current
36
+ end
37
+
38
+ def redis=(client)
39
+ @redis = redis
40
+ end
41
+ end
42
+
43
+ attr_reader :key, :labels, :redis, :retention, :uncompressed
44
+
45
+ def initialize(key, options = {})
46
+ @key = key
47
+ # TODO: read labels from redis if not loaded in memory
48
+ @labels = options[:labels] || []
49
+ @redis = options[:redis] || self.class.redis
50
+ @retention = options[:retention]
51
+ @uncompressed = options[:uncompressed] || false
52
+ end
53
+
54
+ def add(value, timestamp = '*')
55
+ timestamp = timestamp.ts_msec if timestamp.is_a? Time
56
+ ts = cmd 'TS.ADD', key, timestamp, value
57
+ Sample.new(ts, value)
58
+ end
59
+
60
+ def create
61
+ args = [key]
62
+ args << "RETENTION #{retention}" if retention
63
+ args << "UNCOMPRESSED" if uncompressed
64
+ args << "LABELS #{label_string}" if labels.any?
65
+ cmd 'TS.CREATE', args
66
+ self
67
+ end
68
+
69
+ def decrby(value = 1, timestamp = nil)
70
+ args = [key, value]
71
+ args << timestamp if timestamp
72
+ cmd 'TS.DECRBY', args
73
+ end
74
+ alias decrement decrby
75
+
76
+ def destroy
77
+ redis.del key
78
+ end
79
+
80
+ def get
81
+ cmd('TS.GET', key).then do |timestamp, value|
82
+ return unless value
83
+ Sample.new(timestamp, value)
84
+ end
85
+ end
86
+
87
+ def incrby(value = 1, timestamp = nil)
88
+ args = [key, value]
89
+ args << timestamp if timestamp
90
+ cmd 'TS.INCRBY', args
91
+ end
92
+ alias increment incrby
93
+
94
+ # TODO: extract Info module, with methods for each property
95
+ def info
96
+ cmd('TS.INFO', key).each_slice(2).reduce({}) do |h, (key, value)|
97
+ h[key.gsub(/(.)([A-Z])/,'\1_\2').downcase] = value
98
+ h
99
+ end
100
+ end
101
+
102
+ def labels=(val)
103
+ @labels = val
104
+ cmd 'TS.ALTER', key, 'LABELS', label_string
105
+ end
106
+
107
+ def madd(*values)
108
+ if values.one? && values.first.is_a?(Hash)
109
+ # Hash of timestamp => value pairs
110
+ args = values.first.map do |ts, val|
111
+ ts = ts.ts_msec if ts.is_a? Time
112
+ [key, ts, val]
113
+ end.flatten
114
+ elsif values.one? && values.first.is_a?(Array)
115
+ # Array of values, no timestamps
116
+ initial_ts = Time.now.ts_msec
117
+ args = values.first.each_with_index.map do |val, idx|
118
+ [key, initial_ts + idx, val]
119
+ end.flatten
120
+ else
121
+ # Values as individual arguments, no timestamps
122
+ initial_ts = Time.now.ts_msec
123
+ args = values.each_with_index.map do |val, idx|
124
+ [key, initial_ts + idx, val]
125
+ end.flatten
126
+ end
127
+ # TODO: return Sample objects here
128
+ cmd 'TS.MADD', args
129
+ end
130
+
131
+ def range(range, count: nil, agg: nil)
132
+ if range.is_a? Hash
133
+ args = range.fetch(:from), range.fetch(:to)
134
+ elsif range.is_a? Range
135
+ args = range.min, range.max
136
+ end
137
+ args.map! { |ts| (ts.to_f * 1000).to_i }
138
+ args.append('COUNT', count) if count
139
+ args.append('AGGREGATION', agg) if agg
140
+ cmd('TS.RANGE', key, args).map do |ts, val|
141
+ Sample.new(ts, val)
142
+ end
143
+ end
144
+
145
+ def retention=(val)
146
+ @retention = val.to_i
147
+ cmd 'TS.ALTER', key, 'RETENTION', val.to_i
148
+ end
149
+
150
+ private
151
+
152
+ def cmd(name, *args)
153
+ puts "DEBUG: #{name} #{args.join(' ')}" if ENV['DEBUG']
154
+ redis.call name, *args
155
+ end
156
+
157
+ def label_string
158
+ labels.map { |label, value| "#{label} #{value}" }.join(' ')
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ class Redis
3
+ class TimeSeries
4
+ class Sample
5
+ TS_FACTOR = 1000.0
6
+
7
+ attr_reader :time, :value
8
+
9
+ def initialize(timestamp, value)
10
+ @time = Time.at(timestamp / TS_FACTOR)
11
+ @value = BigDecimal(value)
12
+ end
13
+
14
+ def ts_msec
15
+ (time.to_f * TS_FACTOR).to_i
16
+ end
17
+
18
+ def to_h
19
+ {
20
+ timestamp: ts_msec,
21
+ value: value
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ class Time
3
+ # TODO: use refinemenets instead of monkey-patching Time
4
+ def ts_msec
5
+ (to_f * 1000.0).to_i
6
+ end
7
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'redis-time-series'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'redis-time-series'
8
+ spec.version = RedisTimeSeries::VERSION
9
+ spec.authors = ['Matt Duszynski']
10
+ spec.email = ['mattduszynski@gmail.com']
11
+
12
+ spec.summary = %q{A Ruby adapter for the RedisTimeSeries module.}
13
+ # spec.description = %q{TODO: Write a longer description or delete this line.}
14
+ spec.homepage = 'https://github.com/dzunk/redis-time-series'
15
+ spec.license = 'MIT'
16
+
17
+ if spec.respond_to?(:metadata)
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = spec.homepage
20
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
21
+ else
22
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
+ end
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_dependency 'redis', '~> 4.0'
35
+
36
+ spec.add_development_dependency 'activesupport', '~> 6.0'
37
+ spec.add_development_dependency 'bundler', '~> 1.17'
38
+ spec.add_development_dependency 'pry', '~> 0.13'
39
+ spec.add_development_dependency 'rake', '~> 13.0'
40
+ spec.add_development_dependency 'rspec', '~> 3.0'
41
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis-time-series
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Duszynski
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-06-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.17'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.17'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ description:
98
+ email:
99
+ - mattduszynski@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - CHANGELOG.md
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - bin/console
113
+ - bin/setup
114
+ - lib/redis-time-series.rb
115
+ - lib/redis/time_series.rb
116
+ - lib/redis/time_series/sample.rb
117
+ - lib/time/msec.rb
118
+ - redis-time-series.gemspec
119
+ homepage: https://github.com/dzunk/redis-time-series
120
+ licenses:
121
+ - MIT
122
+ metadata:
123
+ homepage_uri: https://github.com/dzunk/redis-time-series
124
+ source_code_uri: https://github.com/dzunk/redis-time-series
125
+ changelog_uri: https://github.com/dzunk/redis-time-series/blob/master/CHANGELOG.md
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubygems_version: 3.0.3
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: A Ruby adapter for the RedisTimeSeries module.
145
+ test_files: []