timed-rediscounter 1.0.0 → 1.0.6

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
  SHA1:
3
- metadata.gz: abc6230c879819d52482f8d11b8a7a88b8b5f4a9
4
- data.tar.gz: e9b4a4336ba02e1062f6ababd6f1fe1760a0a8bb
3
+ metadata.gz: 4a7b99e435001e68df58db161216416c209fb6dd
4
+ data.tar.gz: 5abc20bda6f7363fe184041e60c7a2d0015d2ac3
5
5
  SHA512:
6
- metadata.gz: 777ccd32facd6d3028b8355c6d3011a3fbbed8dd541f5254ecdea9f1c37c28aa57da72fc3ff2a0b1100a2a62b215f0aecc14250054dbd6efbb1ee81777a6a07f
7
- data.tar.gz: b0c354cd2aa008f081caa57e327c42e2e7ab0a6594794ebe14ffe75ab2b1344159fbd72817bc55474c04f96a5f93ce520125a9d1d22cca062235efc13d6044e8
6
+ metadata.gz: 9dbd7645ed21eef5fbe2c7c6041fc7e74562e1094afac61e973f88150310ac560678373be955007a800f7f55624157d362fb0b2cfb23ae6b7352de58be23a328
7
+ data.tar.gz: a9b9f7228ea7270461a11d12ba95b17c40f23bdb5ce05a9c161bb1ba0347c5f72f1438b8600972869c8b0bfc66c76a02a2c9f3e7aaa80096af53d08e72a83787
@@ -7,13 +7,15 @@ require 'active_support/core_ext/hash'
7
7
  require "redis"
8
8
 
9
9
  require "timed/rediscounter/version"
10
- require "timed/rediscounter/counter"
10
+
11
11
 
12
12
 
13
13
 
14
14
  module Timed
15
15
  module Rediscounter
16
- extend ActiveSupport::Concern
16
+ def self.included(mod)
17
+ mod.extend(ClassMethods)
18
+ end
17
19
 
18
20
  def self.redis=(r)
19
21
  @redis = r if r.is_a?(Redis)
@@ -64,5 +66,173 @@ module Timed
64
66
  end
65
67
 
66
68
 
69
+ class Counter
70
+
71
+ Periods = [:minute, :hour, :day, :month, :year].freeze
72
+
73
+ attr_reader :periods,:key
74
+ def initialize(key,default_options={})
75
+ @key = key
76
+ @periods = (default_options.delete(:periods) || Periods)
77
+ @redis = (default_options.delete(:redis) || Timed::Rediscounter.redis)
78
+ raise_if_not_valid_periods(@periods)
79
+ @default_options = default_options.to_h
80
+ end
81
+
82
+ # Increments all given period keys by a given offset
83
+ # offset is normally 1
84
+ #
85
+ def incr(options={})
86
+ opt = @default_options.merge(options).with_indifferent_access
87
+ offset = opt.fetch(:offset,1).to_i
88
+ time = opt.fetch(:time,Time.current)
89
+ periods = (opt[:periods] || @periods)
90
+ raise_if_not_valid_periods(periods)
91
+
92
+ if offset > 0
93
+ return redis.multi do
94
+ periods.each do |period|
95
+ redis.hincrby( period_key(period), convert_time_to_period_hash_key(time,period), offset)
96
+ end
97
+ end
98
+ end
99
+
100
+ return []
101
+ end
102
+
103
+ # Returns a Hash by a given range or a period
104
+ #
105
+ # example:
106
+ # history(1.hour.ago..Time.now) or history(1.hour.ago)
107
+ #
108
+ #
109
+ # result:
110
+ # {2017-09-22 15:00:00 +0200=>0, 2017-09-22 16:00:00 +0200=>0}
111
+ #
112
+ # optional Parameter period:
113
+ # [:minute, :hour, :day, :month, :year]
114
+ def history(range_arg,period=nil)
115
+ redis_key, hash_keys = build_redishash_arguments(range_arg,period)
116
+ return Hash.new if hash_keys.empty?
117
+
118
+ redis.mapped_hmget(redis_key, *hash_keys).inject({}) do |h,(k,v)|
119
+ h[Time.at(k)] = v.to_i
120
+ h
121
+ end
122
+ end
123
+
124
+ def sum(range_arg,period=nil)
125
+ redis_key, hash_keys = build_redishash_arguments(range_arg,period)
126
+ return 0 if hash_keys.empty?
127
+ redis.hmget(redis_key, *hash_keys).inject(0){|sum,i| sum += i.to_i}
128
+ end
129
+
130
+ #Expiring all period Keys
131
+ #
132
+ #expire_in in seconds
133
+ def expire_keys(expire_in=nil)
134
+ expire_in ||= @default_options.fetch(:expire_in, 1.year).to_i
135
+ redis.multi do
136
+ Periods.each { |period| redis.expire period_key(period), expire_in }
137
+ end
138
+ end
139
+
140
+ #deleting all period keys
141
+ def delete_keys
142
+ redis.multi do
143
+ Periods.each { |period| redis.del period_key(period) }
144
+ end
145
+ end
146
+
147
+ #helper to access redis
148
+ def redis
149
+ @redis
150
+ end
151
+
152
+ private
153
+
154
+ #builds the
155
+ def build_redishash_arguments(range_arg,period=nil)
156
+ case range_arg
157
+ when Time,Date
158
+ range = (range_arg..Time.current)
159
+ when String
160
+ range = (Time.parse(range_arg)..Time.current)
161
+ when Range
162
+ range = range_arg
163
+ else
164
+ ArgumentError.new
165
+ end
166
+ period ||= period_by_range(range)
167
+ raise_if_not_valid_periods(period)
168
+
169
+ off_set = 1.send(period)
170
+ hash_keys = Set.new
171
+
172
+ start_time = range.first.send("beginning_of_#{period}")
173
+ end_time = range.last.send("beginning_of_#{period}")
174
+
175
+ hash_keys << start_time
176
+ while (end_time - start_time) >= off_set
177
+ start_time += off_set
178
+ hash_keys << start_time
179
+ end
180
+
181
+ return period_key(period), hash_keys.collect(&:to_i)
182
+ end
183
+
184
+ Steps = [1.hour, 1.day, 1.month, 1.year, 2.year].freeze
185
+ # Calculate a a valid period by a given range
186
+ def period_by_range(range)
187
+ diff = (range.last - range.first).round
188
+ period = nil
189
+ Steps.each_with_index do |step,i|
190
+ if diff <= step
191
+ period = @periods[i]
192
+ break
193
+ end
194
+ end
195
+ #if not found => fallback
196
+ period ||= ( @periods[Steps.length] || @periods.last )
197
+ end
198
+
199
+ def raise_if_not_valid_periods(a)
200
+ r = case a
201
+ when Array
202
+ return !a.any?{|it| !Periods.include?(it.to_sym)}
203
+ when Symbol,String
204
+ return Periods.include?(a.to_sym)
205
+ else
206
+ false
207
+ end
208
+ raise ArgumentError.new("Not valid periods: #{a} Must contain one or more of #{Periods}") unless r
209
+ end
210
+
211
+
212
+ def period_key(period)
213
+ "#{self.class.name}::#{@key}::#{period}"
214
+ end
215
+
216
+ def convert_time_to_period_hash_key(time,period)
217
+ case time
218
+ when Time
219
+ t = time
220
+ when Date
221
+ t = time.to_time
222
+ when String
223
+ t = Time.parse(time)
224
+ when Fixnum,Float
225
+ t = Time.at(time)
226
+ else
227
+ raise ArgumentError.new("Not valid Time")
228
+ end
229
+ t.send("beginning_of_#{period}").to_i
230
+ end
231
+
232
+
233
+
234
+ end
235
+
236
+
67
237
  end
68
238
  end
@@ -1,5 +1,5 @@
1
1
  module Timed
2
2
  module Rediscounter
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.6"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timed-rediscounter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Geduhn