redis_counters 1.3.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 +7 -0
- data/.gitignore +21 -0
- data/CHANGELOG.md +38 -0
- data/Gemfile +3 -0
- data/Makefile +14 -0
- data/README.md +320 -0
- data/Rakefile +15 -0
- data/lib/redis_counters.rb +21 -0
- data/lib/redis_counters/base_counter.rb +84 -0
- data/lib/redis_counters/bucket.rb +59 -0
- data/lib/redis_counters/cluster.rb +22 -0
- data/lib/redis_counters/clusterize_and_partitionize.rb +194 -0
- data/lib/redis_counters/hash_counter.rb +70 -0
- data/lib/redis_counters/partition.rb +16 -0
- data/lib/redis_counters/unique_hash_counter.rb +51 -0
- data/lib/redis_counters/unique_values_lists/base.rb +57 -0
- data/lib/redis_counters/unique_values_lists/blocking.rb +167 -0
- data/lib/redis_counters/unique_values_lists/expirable.rb +155 -0
- data/lib/redis_counters/unique_values_lists/non_blocking.rb +91 -0
- data/lib/redis_counters/version.rb +3 -0
- data/redis_counters.gemspec +31 -0
- data/spec/redis_counters/base_spec.rb +29 -0
- data/spec/redis_counters/hash_counter_spec.rb +462 -0
- data/spec/redis_counters/unique_hash_counter_spec.rb +83 -0
- data/spec/redis_counters/unique_values_lists/blocking_spec.rb +94 -0
- data/spec/redis_counters/unique_values_lists/expirable_spec.rb +6 -0
- data/spec/redis_counters/unique_values_lists/non_blicking_spec.rb +6 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/unique_values_lists/common.rb +563 -0
- data/spec/support/unique_values_lists/expirable.rb +162 -0
- data/spec/support/unique_values_lists/set.rb +119 -0
- data/tasks/audit.rake +6 -0
- data/tasks/cane.rake +12 -0
- data/tasks/changelog.rake +7 -0
- data/tasks/coverage.rake +21 -0
- data/tasks/support.rb +24 -0
- metadata +242 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7686748e5af2550c7895c4d3b893a4464e12495f
|
4
|
+
data.tar.gz: da77d21dac0066c38745affc6301055191f10dc6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ee6ce001671fc800cb85327c64e39196197708da7f32d07a5ef3fbd7b9a1937fb2526e207a8c5c5ef8902973db5e7e2d827434b09401982f7af1cfe917203815
|
7
|
+
data.tar.gz: 3b2fa28eb9a5c12efb45fae68c96da2ac03ad68e95ad59264ca152f3bc080371a79efc61c4d5890653de54c217f10193a56663e4ea4951dc4357d7d2edfd3ce2
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
#### [Current]
|
3
|
+
|
4
|
+
|
5
|
+
#### v1.2.0
|
6
|
+
* 2014-11-10 [be642ce](../../commit/be642ce) - __(Artem Napolskih)__ Release 1.2.0
|
7
|
+
* 2014-11-10 [6257dc2](../../commit/6257dc2) - __(Artem Napolskih)__ feature(hash_counter): added float mode
|
8
|
+
* 2014-10-17 [48deb40](../../commit/48deb40) - __(Artem Napolskih)__ feature(unique_values_list): introduced a list of unique values to expiry of the members
|
9
|
+
* 2014-10-17 [e1206b7](../../commit/e1206b7) - __(Artem Napolskih)__ feature(unique_values_list): introduce has_value? method
|
10
|
+
* 2014-10-17 [cccc2be](../../commit/cccc2be) - __(Artem Napolskih)__ feature(unique_values_list): rename Standard and Fast unique values list to Blocking and NonBlocking respectively
|
11
|
+
* 2014-10-17 [7521fd8](../../commit/7521fd8) - __(Artem Napolskih)__ chore(specs): reorganize unique lists specs
|
12
|
+
* 2014-04-23 [94fada3](../../commit/94fada3) - __(Artem Napolskih)__ chore(all): fix circleci badge
|
13
|
+
* 2013-11-20 [0ae5531](../../commit/0ae5531) - __(Artem Napolskih)__ Release 1.1.0
|
14
|
+
|
15
|
+
#### v1.1.0
|
16
|
+
* 2013-11-20 [01f12f9](../../commit/01f12f9) - __(Artem Napolskih)__ Release 1.1.0
|
17
|
+
* 2013-11-20 [3897988](../../commit/3897988) - __(Artem Napolskih)__ refactor(all): back delete_all! methods
|
18
|
+
* 2013-11-15 [2d1c733](../../commit/2d1c733) - __(Artem Napolskih)__ refactor(all): extract Cluster and Partition classes
|
19
|
+
* 2013-10-22 [020cc8e](../../commit/020cc8e) - __(Napolskih)__ refactor(all): shared code of clustering and partitioning extracted into module - group_keys -> cluster_keys - shared code of clustering and partitioning extracted into module
|
20
|
+
|
21
|
+
#### v1.0.1
|
22
|
+
* 2013-10-21 [9b5e13b](../../commit/9b5e13b) - __(Artem Napolskih)__ Release 1.0.1
|
23
|
+
* 2013-10-21 [bfa328a](../../commit/bfa328a) - __(Artem Napolskih)__ feature(hash_counter): method date when called with a block, now returns the total number of lines
|
24
|
+
* 2013-10-21 [6d04c95](../../commit/6d04c95) - __(Artem Napolskih)__ Release 1.0.0
|
25
|
+
|
26
|
+
#### v1.0.0
|
27
|
+
* 2013-10-21 [b5f5344](../../commit/b5f5344) - __(Artem Napolskih)__ Release 1.0.0
|
28
|
+
* 2013-10-10 [b29eab7](../../commit/b29eab7) - __(Artem Napolskih)__ feature(unique_values_lists): added methods to read and delete data
|
29
|
+
* 2013-10-10 [67c5200](../../commit/67c5200) - __(Artem Napolskih)__ feature(unique_hash_counter): introduce unique list postfix delimiter
|
30
|
+
* 2013-10-08 [8a9a2a9](../../commit/8a9a2a9) - __(Artem Napolskih)__ feature(hash_counter): added methods to read and delete data
|
31
|
+
* 2013-09-13 [f8d037c](../../commit/f8d037c) - __(Artem Napolskih)__ docs(all): documenting
|
32
|
+
|
33
|
+
#### v1.0.0beta1
|
34
|
+
* 2013-09-13 [43016ec](../../commit/43016ec) - __(Artem Napolskih)__ Release 1.0.0beta1
|
35
|
+
* 2013-09-12 [0a176fa](../../commit/0a176fa) - __(Artem Napolskih)__ feature(all) introduce key and value delimiters
|
36
|
+
* 2013-09-12 [addbb40](../../commit/addbb40) - __(Artem Napolskih)__ feature(unique_values_list): fast (non blocking) unique values list added
|
37
|
+
* 2013-08-23 [897418d](../../commit/897418d) - __(Artem Napolskih)__ Initial commit
|
38
|
+
* 2013-08-21 [21ed53b](../../commit/21ed53b) - __(napolskih)__ dummy commit
|
data/Gemfile
ADDED
data/Makefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
BUNDLE = bundle
|
2
|
+
BUNDLE_OPTIONS = -j 4
|
3
|
+
RSPEC = ${BUNDLE} exec rspec
|
4
|
+
|
5
|
+
all: test
|
6
|
+
|
7
|
+
test: bundler/install
|
8
|
+
${RSPEC} 2>&1
|
9
|
+
|
10
|
+
bundler/install:
|
11
|
+
if ! gem list bundler -i > /dev/null; then \
|
12
|
+
gem install bundler; \
|
13
|
+
fi
|
14
|
+
${BUNDLE} install ${BUNDLE_OPTIONS}
|
data/README.md
ADDED
@@ -0,0 +1,320 @@
|
|
1
|
+
# RedisCounters
|
2
|
+
|
3
|
+
[](http://dolly.railsc.ru/projects/36/builds/latest/?ref=master)
|
4
|
+
[](https://codeclimate.com/repos/522e9b497e00a46a0d01227c/feed)
|
5
|
+
[](https://codeclimate.com/repos/522e9b497e00a46a0d01227c/feed)
|
6
|
+
|
7
|
+
Набор структур данных на базе Redis.
|
8
|
+
|
9
|
+
## RedisCounters::HashCounter
|
10
|
+
|
11
|
+
Счетчик на основе Hash, с ~~преферансом и тайками-близняшками~~ партиционированием и кластеризацией значений.
|
12
|
+
|
13
|
+
Обязательные параметры: counter_name, field_name или group_keys.
|
14
|
+
|
15
|
+
### Сложность
|
16
|
+
+ инкремент - O(1).
|
17
|
+
|
18
|
+
### Примеры использования
|
19
|
+
|
20
|
+
Простой счетчик значений.
|
21
|
+
```ruby
|
22
|
+
counter = RedisCounters::HashCounter.new(redis, {
|
23
|
+
:counter_name => :simple_counter,
|
24
|
+
:field_name => :pages
|
25
|
+
})
|
26
|
+
|
27
|
+
5.times { counter.increment }
|
28
|
+
|
29
|
+
redis:
|
30
|
+
simple_counter = {
|
31
|
+
pages => 5
|
32
|
+
}
|
33
|
+
|
34
|
+
> counter.partitions
|
35
|
+
=> [{}]
|
36
|
+
|
37
|
+
> counter.data
|
38
|
+
=> [{:value=>5}]
|
39
|
+
```
|
40
|
+
|
41
|
+
Счетчик посещенных страниц компании с партиционированием по дате.
|
42
|
+
```ruby
|
43
|
+
counter = RedisCounters::HashCounter.new(redis, {
|
44
|
+
:counter_name => :pages_by_day,
|
45
|
+
:group_keys => [:company_id],
|
46
|
+
:partition_keys => [:date]
|
47
|
+
})
|
48
|
+
|
49
|
+
2.times { counter.increment(:company_id => 1, :date => '2013-08-01') }
|
50
|
+
3.times { counter.increment(:company_id => 2, :date => '2013-08-01') }
|
51
|
+
1.times { counter.increment(:company_id => 3, :date => '2013-08-02') }
|
52
|
+
|
53
|
+
redis:
|
54
|
+
pages_by_day:2013-08-01 = {
|
55
|
+
1 => 2
|
56
|
+
2 => 3
|
57
|
+
}
|
58
|
+
pages_by_day:2013-08-02 = {
|
59
|
+
3 => 1
|
60
|
+
}
|
61
|
+
|
62
|
+
> counter.partitions
|
63
|
+
=> [{:date=>"2013-08-01"}, {:date=>"2013-08-02"}]
|
64
|
+
|
65
|
+
> counter.data
|
66
|
+
=> [{:company_id=>"1", :value=>2},
|
67
|
+
{:company_id=>"2", :value=>3},
|
68
|
+
{:company_id=>"3", :value=>1}]
|
69
|
+
|
70
|
+
> counter.delete_partitions!(:date => '2013-08-01')
|
71
|
+
=> [1]
|
72
|
+
|
73
|
+
> counter.partitions
|
74
|
+
=> [{:date=>"2013-08-02"}]
|
75
|
+
|
76
|
+
> counter.data
|
77
|
+
=> [{:company_id=>"3", :value=>1}]
|
78
|
+
|
79
|
+
> counter.delete_all!
|
80
|
+
=> [1]
|
81
|
+
|
82
|
+
> counter.data
|
83
|
+
=> []
|
84
|
+
```
|
85
|
+
|
86
|
+
Тоже самое, но партиция задается с помощью proc.
|
87
|
+
```ruby
|
88
|
+
counter = RedisCounters::HashCounter.new(redis, {
|
89
|
+
:counter_name => :pages_by_day,
|
90
|
+
:group_keys => [:company_id],
|
91
|
+
:partition_keys => proc { |params| params.fetch(:date) }
|
92
|
+
})
|
93
|
+
```
|
94
|
+
|
95
|
+
Счетчик посещенных страниц с группировкой по городу посетителя и партиционированием по дате и компании.
|
96
|
+
```ruby
|
97
|
+
counter = RedisCounters::HashCounter.new(redis, {
|
98
|
+
:counter_name => :pages_by_day_city,
|
99
|
+
:group_keys => [:company_id, :city_id],
|
100
|
+
:partition_keys => [:date, :company_id]
|
101
|
+
})
|
102
|
+
|
103
|
+
2.times { counter.increment(:date => '2013-08-01', :company_id => 1, :city_id => 11) }
|
104
|
+
1.times { counter.increment(:date => '2013-08-01', :company_id => 1, :city_id => 12) }
|
105
|
+
4.times { counter.increment(:date => '2013-08-01', :company_id => 2, :city_id => 10) }
|
106
|
+
3.times { counter.increment(:date => '2013-08-02', :company_id => 1, :city_id => 15) }
|
107
|
+
|
108
|
+
redis:
|
109
|
+
pages_by_day_city:2013-08-01:1 = {
|
110
|
+
1:11 => 2,
|
111
|
+
1:12 => 1
|
112
|
+
}
|
113
|
+
|
114
|
+
pages_by_day_city:2013-08-01:2 = {
|
115
|
+
2:10 => 4
|
116
|
+
}
|
117
|
+
|
118
|
+
pages_by_day_city:2013-08-02:1 = {
|
119
|
+
1:15 => 3
|
120
|
+
}
|
121
|
+
|
122
|
+
> counter.partitions
|
123
|
+
=> [{:date=>"2013-08-02", :company_id=>"1"},
|
124
|
+
{:date=>"2013-08-01", :company_id=>"1"},
|
125
|
+
{:date=>"2013-08-01", :company_id=>"2"}]
|
126
|
+
|
127
|
+
> counter.partitions(:date => '2013-08-01')
|
128
|
+
=> [{:date=>"2013-08-01", :company_id=>"1"},
|
129
|
+
{:date=>"2013-08-01", :company_id=>"2"}]
|
130
|
+
|
131
|
+
> counter.data
|
132
|
+
=> [{:company_id => 1, :city_id=>"15", :value=>3},
|
133
|
+
{:company_id => 1, :city_id=>"11", :value=>2},
|
134
|
+
{:company_id => 1, :city_id=>"12", :value=>1},
|
135
|
+
{:company_id => 2, :city_id=>"10", :value=>4}]
|
136
|
+
|
137
|
+
> counter.data(:date => '2013-08-01')
|
138
|
+
=> [{:company_id => 1, :city_id=>"11", :value=>2},
|
139
|
+
{:company_id => 1, :city_id=>"12", :value=>1},
|
140
|
+
{:company_id => 2, :city_id=>"10", :value=>4}]
|
141
|
+
|
142
|
+
> counter.data(:date => '2013-08-01') { |batch| puts batch }
|
143
|
+
{:company_id => 1, :city_id=>"11", :value=>2}
|
144
|
+
{:company_id => 1, :city_id=>"12", :value=>1}
|
145
|
+
{:company_id => 2, :city_id=>"10", :value=>4}
|
146
|
+
```
|
147
|
+
|
148
|
+
## RedisCounters::UniqueValuesLists::Blocking
|
149
|
+
|
150
|
+
Список уникальных значений, с возможностью кластеризации и партиционирования значений.
|
151
|
+
|
152
|
+
Особенности:
|
153
|
+
- Использует механизм оптимистичных блокировок.
|
154
|
+
- Помимо списка значений, ведет так же, список партиций, для каждого кластера.
|
155
|
+
- Полностью транзакционен - сторонний блок, выполняемый после добавления уникального элемента,
|
156
|
+
выполняется в той же транзакции, в которой добавляется уникальный элемент.
|
157
|
+
|
158
|
+
Вероятно, в условиях большой конкурентности, обладает не лучшей производительносью из-за частых блокировок.
|
159
|
+
|
160
|
+
Обязательные параметры: counter_name и value_keys.
|
161
|
+
|
162
|
+
### Сложность
|
163
|
+
+ добавление элемента - от O(1), при отсутствии партиционирования, до O(N), где N - кол-во партиций.
|
164
|
+
|
165
|
+
### Примеры использования
|
166
|
+
|
167
|
+
Простой список уникальных пользователей.
|
168
|
+
```ruby
|
169
|
+
counter = RedisCounters::UniqueValuesLists::Blocking.new(redis, {
|
170
|
+
:counter_name => :users,
|
171
|
+
:value_keys => [:user_id]
|
172
|
+
})
|
173
|
+
|
174
|
+
counter.increment(:user_id => 1)
|
175
|
+
counter.increment(:user_id => 2)
|
176
|
+
counter.increment(:user_id => 1)
|
177
|
+
|
178
|
+
redis:
|
179
|
+
users = ['1', '2']
|
180
|
+
```
|
181
|
+
|
182
|
+
Список уникальных пользователей, посетивших компаниию, за месяц, партиционированный по суткам.
|
183
|
+
```ruby
|
184
|
+
counter = RedisCounters::UniqueValuesLists::Blocking.new(redis, {
|
185
|
+
:counter_name => :company_users_by_month,
|
186
|
+
:value_keys => [:company_id, :user_id],
|
187
|
+
:cluster_keys => [:start_month_date],
|
188
|
+
:partition_keys => [:date]
|
189
|
+
})
|
190
|
+
|
191
|
+
2.times { counter.add(:company_id => 1, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
192
|
+
3.times { counter.add(:company_id => 1, :user_id => 22, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
193
|
+
3.times { counter.add(:company_id => 1, :user_id => 22, :date => '2013-09-05', :start_month_date => '2013-09-01') }
|
194
|
+
3.times { counter.add(:company_id => 2, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
195
|
+
1.times { counter.add(:company_id => 2, :user_id => 22, :date => '2013-08-11', :start_month_date => '2013-08-01') }
|
196
|
+
|
197
|
+
redis:
|
198
|
+
company_users_by_month:2013-08-01:partitions = ['2013-08-10', '2013-08-11']
|
199
|
+
company_users_by_month:2013-08-01:2013-08-10 = ['1:11', '1:22', '2:11']
|
200
|
+
company_users_by_month:2013-08-01:2013-08-11 = ['2:22']
|
201
|
+
|
202
|
+
company_users_by_month:2013-09-01:partitions = ['2013-09-05']
|
203
|
+
company_users_by_month:2013-09-01:2013-09-05 = ['1:22']
|
204
|
+
```
|
205
|
+
|
206
|
+
## RedisCounters::UniqueValuesLists::NonBlocking
|
207
|
+
|
208
|
+
Быстрый список уникальных значений, с возможностью кластеризации и партиционирования значений.
|
209
|
+
|
210
|
+
Скорость работы достигается за счет следующих особенностей:
|
211
|
+
- Использует 2х объема памяти для хранения элементов,
|
212
|
+
при использовании партиционирования.
|
213
|
+
Eсли партиционирование не используется, то расход памяти такой-же как у UniqueValuesLists::Blocking.
|
214
|
+
- Не транзакционен - сторонний блок, выполняемый после добавления уникального элемента,
|
215
|
+
выполняется за пределами транзакции, в которой добавляется уникальный элемент.
|
216
|
+
- Не ведется список партиций.
|
217
|
+
|
218
|
+
Обязательные параметры: counter_name и value_keys.
|
219
|
+
|
220
|
+
### Сложность
|
221
|
+
+ добавление элемента - O(1)
|
222
|
+
|
223
|
+
|
224
|
+
## RedisCounters::UniqueValuesLists::Expirable
|
225
|
+
|
226
|
+
Список уникальных значений, с возможностью expire отдельных элементов.
|
227
|
+
|
228
|
+
На основе сортированного множества.
|
229
|
+
http://redis4you.com/code.php?id=010
|
230
|
+
|
231
|
+
На основе механизма оптимистических блокировок.
|
232
|
+
смотри Optimistic locking using check-and-set:
|
233
|
+
http://redis.io/topics/transactions
|
234
|
+
|
235
|
+
Особенности:
|
236
|
+
- Expire - таймаут, можно установить как на уровне счетчика,
|
237
|
+
так и на уровне отдельного занчения;
|
238
|
+
- Очистка возможна как в автоматическогом режиме так в и ручном;
|
239
|
+
- Значения сохраняет в партициях;
|
240
|
+
- Ведет список партиций;
|
241
|
+
- Полностью транзакционен.
|
242
|
+
|
243
|
+
Обязательные параметры: counter_name и value_keys.
|
244
|
+
Таймаут задается параметром :expire. По умолчанию :never.
|
245
|
+
:clean_expired - режим автоочистки. По умолчанию true.
|
246
|
+
|
247
|
+
### Примеры использования
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
counter = RedisCounters::UniqueValuesLists::Expirable.new(redis,
|
251
|
+
:counter_name => :sessions,
|
252
|
+
:value_keys => [:session_id],
|
253
|
+
:expire => 10.minutes
|
254
|
+
)
|
255
|
+
|
256
|
+
counter << session_id: 1
|
257
|
+
counter << session_id: 2
|
258
|
+
counter << session_id: 3, expire: :never
|
259
|
+
|
260
|
+
counter.data
|
261
|
+
> [{session_id: 1}, {session_id: 2}, {session_id: 3}]
|
262
|
+
|
263
|
+
# after 10 minutes
|
264
|
+
|
265
|
+
counter.data
|
266
|
+
> [{session_id: 3}]
|
267
|
+
|
268
|
+
counter.has_value?(session_id: 1)
|
269
|
+
false
|
270
|
+
```
|
271
|
+
|
272
|
+
## RedisCounters::UniqueHashCounter
|
273
|
+
|
274
|
+
Сборная конструкция на основе предыдущих.
|
275
|
+
HashCounter, с возможностью подсчета только у уникальных событий.
|
276
|
+
|
277
|
+
### Сложность
|
278
|
+
аналогично сложности, используемого уникального списка.
|
279
|
+
|
280
|
+
### Примеры использования
|
281
|
+
|
282
|
+
Счетчик уникальных пользователей, посетивших компаниию, за месяц, кластеризованный по суткам.
|
283
|
+
```ruby
|
284
|
+
counter = RedisCounters::UniqueHashCounter.new(redis, {
|
285
|
+
:counter_name => :company_users_by_month,
|
286
|
+
:group_keys => [:company_id],
|
287
|
+
:partition_keys => [:date],
|
288
|
+
:unique_list => {
|
289
|
+
:list_class => RedisCounters::UniqueValuesLists::Blocking
|
290
|
+
:value_keys => [:company_id, :user_id],
|
291
|
+
:cluster_keys => [:start_month_date],
|
292
|
+
:partition_keys => [:date]
|
293
|
+
}
|
294
|
+
})
|
295
|
+
|
296
|
+
2.times { counter.increment(:company_id => 1, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
297
|
+
3.times { counter.increment(:company_id => 1, :user_id => 22, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
298
|
+
3.times { counter.increment(:company_id => 1, :user_id => 22, :date => '2013-09-05', :start_month_date => '2013-09-01') }
|
299
|
+
3.times { counter.increment(:company_id => 2, :user_id => 11, :date => '2013-08-10', :start_month_date => '2013-08-01') }
|
300
|
+
1.times { counter.increment(:company_id => 2, :user_id => 22, :date => '2013-08-11', :start_month_date => '2013-08-01') }
|
301
|
+
|
302
|
+
redis:
|
303
|
+
company_users_by_month:2013-08-10 = {
|
304
|
+
1 = 2,
|
305
|
+
2 = 1
|
306
|
+
}
|
307
|
+
company_users_by_month:2013-08-11 = {
|
308
|
+
2 = 1
|
309
|
+
}
|
310
|
+
company_users_by_month:2013-09-05 = {
|
311
|
+
1 = 1
|
312
|
+
}
|
313
|
+
|
314
|
+
company_users_by_month_uq:2013-08-01:partitions = ['2013-08-10', '2013-08-11']
|
315
|
+
company_users_by_month_uq:2013-08-01:2013-08-10 = ['1:11', '1:22', '2:11']
|
316
|
+
company_users_by_month_uq:2013-08-01:2013-08-11 = ['2:22']
|
317
|
+
|
318
|
+
company_users_by_month_uq:2013-09-01:partitions = ['2013-09-05']
|
319
|
+
company_users_by_month_uq:2013-09-01:2013-09-05 = ['1:22']
|
320
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
# load everything from tasks/ directory
|
5
|
+
Dir[File.join(File.dirname(__FILE__), 'tasks', '*.{rb,rake}')].each { |f| load(f) }
|
6
|
+
|
7
|
+
task :release => [:check, :changelog]
|
8
|
+
|
9
|
+
desc 'Check quality'
|
10
|
+
task :check => [:audit, :quality, :coverage]
|
11
|
+
|
12
|
+
require 'rspec/core/rake_task'
|
13
|
+
|
14
|
+
# setup `spec` task
|
15
|
+
RSpec::Core::RakeTask.new(:spec)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'redis_counters/version'
|
3
|
+
require 'redis_counters/base_counter'
|
4
|
+
require 'redis_counters/hash_counter'
|
5
|
+
require 'redis_counters/unique_hash_counter'
|
6
|
+
require 'redis_counters/unique_values_lists/base'
|
7
|
+
require 'redis_counters/unique_values_lists/blocking'
|
8
|
+
require 'redis_counters/unique_values_lists/non_blocking'
|
9
|
+
require 'redis_counters/unique_values_lists/expirable'
|
10
|
+
|
11
|
+
require 'active_support'
|
12
|
+
require 'active_support/core_ext'
|
13
|
+
|
14
|
+
module RedisCounters
|
15
|
+
|
16
|
+
def create_counter(redis, opts)
|
17
|
+
BaseCounter.create(redis, opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
module_function :create_counter
|
21
|
+
end
|