redistat 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.travis.yml +8 -0
  2. data/README.md +219 -97
  3. data/lib/redistat.rb +13 -13
  4. data/lib/redistat/buffer.rb +27 -24
  5. data/lib/redistat/collection.rb +5 -5
  6. data/lib/redistat/connection.rb +23 -18
  7. data/lib/redistat/core_ext.rb +1 -1
  8. data/lib/redistat/core_ext/bignum.rb +2 -2
  9. data/lib/redistat/core_ext/date.rb +2 -2
  10. data/lib/redistat/core_ext/fixnum.rb +2 -2
  11. data/lib/redistat/core_ext/hash.rb +4 -4
  12. data/lib/redistat/date.rb +11 -11
  13. data/lib/redistat/event.rb +18 -18
  14. data/lib/redistat/finder.rb +39 -39
  15. data/lib/redistat/finder/date_set.rb +4 -4
  16. data/lib/redistat/key.rb +16 -16
  17. data/lib/redistat/label.rb +14 -14
  18. data/lib/redistat/mixins/database.rb +1 -1
  19. data/lib/redistat/mixins/date_helper.rb +1 -1
  20. data/lib/redistat/mixins/options.rb +8 -8
  21. data/lib/redistat/mixins/synchronize.rb +12 -11
  22. data/lib/redistat/model.rb +25 -17
  23. data/lib/redistat/result.rb +4 -4
  24. data/lib/redistat/scope.rb +5 -5
  25. data/lib/redistat/summary.rb +33 -26
  26. data/lib/redistat/version.rb +1 -1
  27. data/redistat.gemspec +4 -3
  28. data/spec/buffer_spec.rb +27 -25
  29. data/spec/collection_spec.rb +4 -4
  30. data/spec/connection_spec.rb +12 -12
  31. data/spec/core_ext/hash_spec.rb +5 -5
  32. data/spec/database_spec.rb +3 -3
  33. data/spec/date_spec.rb +15 -15
  34. data/spec/event_spec.rb +8 -8
  35. data/spec/finder/date_set_spec.rb +134 -134
  36. data/spec/finder_spec.rb +36 -36
  37. data/spec/key_spec.rb +19 -19
  38. data/spec/label_spec.rb +10 -10
  39. data/spec/model_helper.rb +10 -9
  40. data/spec/model_spec.rb +38 -41
  41. data/spec/options_spec.rb +9 -9
  42. data/spec/result_spec.rb +4 -4
  43. data/spec/scope_spec.rb +6 -6
  44. data/spec/spec_helper.rb +6 -0
  45. data/spec/summary_spec.rb +31 -24
  46. data/spec/synchronize_spec.rb +118 -57
  47. data/spec/thread_safety_spec.rb +6 -6
  48. metadata +88 -126
  49. data/.rvmrc +0 -1
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - ree
data/README.md CHANGED
@@ -1,164 +1,259 @@
1
- # Redistat #
1
+ # Redistat [![Build Status](https://secure.travis-ci.org/jimeh/redistat.png)](http://travis-ci.org/jimeh/redistat)
2
2
 
3
3
  A Redis-backed statistics storage and querying library written in Ruby.
4
4
 
5
- Redistat was originally created to replace a small hacked together statistics collection solution which was MySQL-based. When I started I had a short list of requirements:
5
+ Redistat was originally created to replace a small hacked together statistics
6
+ collection solution which was MySQL-based. When I started I had a short list
7
+ of requirements:
6
8
 
7
9
  * Store and increment/decrement integer values (counters, etc)
8
10
  * Up to the second statistics available at all times
9
11
  * Screamingly fast
10
12
 
11
- Redis fits perfectly with all of these requirements. It has atomic operations like increment, and it's lightning fast, meaning if the data is structured well, the initial stats reporting call will store data in a format that's instantly retrievable just as fast.
13
+ Redis fits perfectly with all of these requirements. It has atomic operations
14
+ like increment, and it's lightning fast, meaning if the data is structured
15
+ well, the initial stats reporting call will store data in a format that's
16
+ instantly retrievable just as fast.
12
17
 
13
- ## Installation ##
18
+ ## Installation
14
19
 
15
20
  gem install redistat
16
21
 
17
- If you are using Ruby 1.8.x, it's recommended you also install the `SystemTimer` gem, as the Redis gem will otherwise complain.
22
+ If you are using Ruby 1.8.x, it's recommended you also install the
23
+ `SystemTimer` gem, as the Redis gem will otherwise complain.
18
24
 
19
- ## Usage (Crash Course) ##
25
+ ## Usage (Crash Course)
20
26
 
21
27
  view\_stats.rb:
22
28
 
23
- require 'redistat'
24
-
25
- class ViewStats
26
- include Redistat::Model
27
- end
28
-
29
- # if using Redistat in multiple threads set this
30
- # somewhere in the beginning of the execution stack
31
- Redistat.thread_safe = true
29
+ ```ruby
30
+ require 'redistat'
32
31
 
32
+ class ViewStats
33
+ include Redistat::Model
34
+ end
33
35
 
34
- ### Simple Example ###
36
+ # if using Redistat in multiple threads set this
37
+ # somewhere in the beginning of the execution stack
38
+ Redistat.thread_safe = true
39
+ ```
40
+
41
+
42
+ ### Simple Example
35
43
 
36
44
  Store:
37
45
 
38
- ViewStats.store('hello', {:world => 4})
39
- ViewStats.store('hello', {:world => 2}, 2.hours.ago)
46
+ ```ruby
47
+ ViewStats.store('hello', {:world => 4})
48
+ ViewStats.store('hello', {:world => 2}, 2.hours.ago)
49
+ ```
40
50
 
41
51
  Fetch:
42
52
 
43
- ViewStats.find('hello', 1.hour.ago, 1.hour.from_now).all
44
- #=> [{'world' => 4}]
45
- ViewStats.find('hello', 1.hour.ago, 1.hour.from_now).total
46
- #=> {'world' => 4}
47
- ViewStats.find('hello', 3.hour.ago, 1.hour.from_now).total
48
- #=> {'world' => 6}
53
+ ```ruby
54
+ ViewStats.find('hello', 1.hour.ago, 1.hour.from_now).all
55
+ #=> [{'world' => 4}]
56
+ ViewStats.find('hello', 1.hour.ago, 1.hour.from_now).total
57
+ #=> {'world' => 4}
58
+ ViewStats.find('hello', 3.hour.ago, 1.hour.from_now).total
59
+ #=> {'world' => 6}
60
+ ```
49
61
 
50
62
 
51
- ### Advanced Example ###
63
+ ### Advanced Example
52
64
 
53
65
  Store page view on product #44 from Chrome 11:
54
66
 
55
- ViewStats.store('views/product/44', {'count/chrome/11' => 1})
56
-
67
+ ```ruby
68
+ ViewStats.store('views/product/44', {'count/chrome/11' => 1})
69
+ ```
70
+
57
71
  Fetch product #44 stats:
58
72
 
59
- ViewStats.find('views/product/44', 23.hours.ago, 1.hour.from_now).total
60
- #=> { 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 }
73
+ ```ruby
74
+ ViewStats.find('views/product/44', 23.hours.ago, 1.hour.from_now).total
75
+ #=> { 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 }
76
+ ```
61
77
 
62
78
  Store a page view on product #32 from Firefox 3:
63
79
 
64
- ViewStats.store('views/product/32', {'count/firefox/3' => 1})
80
+ ```ruby
81
+ ViewStats.store('views/product/32', {'count/firefox/3' => 1})
82
+ ```
65
83
 
66
84
  Fetch product #32 stats:
67
-
68
- ViewStats.find('views/product/32', 23.hours.ago, 1.hour.from_now).total
69
- #=> { 'count' => 1, 'count/firefox' => 1, 'count/firefox/3' => 1 }
85
+
86
+ ```ruby
87
+ ViewStats.find('views/product/32', 23.hours.ago, 1.hour.from_now).total
88
+ #=> { 'count' => 1, 'count/firefox' => 1, 'count/firefox/3' => 1 }
89
+ ```
70
90
 
71
91
  Fetch stats for all products:
72
92
 
73
- ViewStats.find('views/product', 23.hours.ago, 1.hour.from_now).total
74
- #=> { 'count' => 2,
75
- # 'count/chrome' => 1,
76
- # 'count/chrome/11' => 1,
77
- # 'count/firefox' => 1,
78
- # 'count/firefox/3' => 1 }
93
+ ```ruby
94
+ ViewStats.find('views/product', 23.hours.ago, 1.hour.from_now).total
95
+ #=> { 'count' => 2,
96
+ # 'count/chrome' => 1,
97
+ # 'count/chrome/11' => 1,
98
+ # 'count/firefox' => 1,
99
+ # 'count/firefox/3' => 1 }
100
+ ```
79
101
 
80
102
  Store a 404 error view:
81
103
 
82
- ViewStats.store('views/error/404', {'count/chrome/9' => 1})
104
+ ```ruby
105
+ ViewStats.store('views/error/404', {'count/chrome/9' => 1})
106
+ ```
83
107
 
84
108
  Fetch stats for all views across the board:
85
109
 
86
- ViewStats.find('views', 23.hours.ago, 1.hour.from_now).total
87
- #=> { 'count' => 3,
88
- # 'count/chrome' => 2,
89
- # 'count/chrome/9' => 1,
90
- # 'count/chrome/11' => 1,
91
- # 'count/firefox' => 1,
92
- # 'count/firefox/3' => 1 }
110
+ ```ruby
111
+ ViewStats.find('views', 23.hours.ago, 1.hour.from_now).total
112
+ #=> { 'count' => 3,
113
+ # 'count/chrome' => 2,
114
+ # 'count/chrome/9' => 1,
115
+ # 'count/chrome/11' => 1,
116
+ # 'count/firefox' => 1,
117
+ # 'count/firefox/3' => 1 }
118
+ ```
93
119
 
94
120
  Fetch list of products known to Redistat:
95
121
 
96
- finder = ViewStats.find('views/product', 23.hours.ago, 1.hour.from_now)
97
- finder.children.map { |child| child.label.me }
98
- #=> [ "32", "44" ]
99
- finder.children.map { |child| child.label.to_s }
100
- #=> [ "views/products/32", "views/products/44" ]
101
- finder.children.map { |child| child.total }
102
- #=> [ { "count" => 1, "count/firefox" => 1, "count/firefox/3" => 1 },
103
- # { "count" => 1, "count/chrome" => 1, "count/chrome/11" => 1 } ]
122
+ ```ruby
123
+ finder = ViewStats.find('views/product', 23.hours.ago, 1.hour.from_now)
124
+ finder.children.map { |child| child.label.me }
125
+ #=> [ "32", "44" ]
126
+ finder.children.map { |child| child.label.to_s }
127
+ #=> [ "views/products/32", "views/products/44" ]
128
+ finder.children.map { |child| child.total }
129
+ #=> [ { "count" => 1, "count/firefox" => 1, "count/firefox/3" => 1 },
130
+ # { "count" => 1, "count/chrome" => 1, "count/chrome/11" => 1 } ]
131
+ ```
132
+
133
+
134
+ ## Terminology
135
+
136
+ ### Scope
104
137
 
138
+ A type of global-namespace for storing data. When using the `Redistat::Model`
139
+ wrapper, the scope is automatically set to the class name. In the examples
140
+ above, the scope is `ViewStats`. Can be overridden by calling the `#scope`
141
+ class method on your model class.
105
142
 
106
- ## Terminology ##
143
+ ### Label
107
144
 
108
- ### Scope ###
145
+ Identifier string to separate different types and groups of statistics from
146
+ each other. The first argument of the `#store`, `#find`, and `#fetch` methods
147
+ is the label that you're storing to, or fetching from.
109
148
 
110
- A type of global-namespace for storing data. When using the `Redistat::Model` wrapper, the scope is automatically set to the class name. In the examples above, the scope is `ViewStats`. Can be overridden by calling the `#scope` class method on your model class.
149
+ Labels support multiple grouping levels by splitting the label string with `/`
150
+ and storing the same stats for each level. For example, when storing data to a
151
+ label called `views/product/44`, the data is stored for the label you specify,
152
+ and also for `views/product` and `views`.
111
153
 
112
- ### Label ###
154
+ A word of caution: Don't use a crazy number of group levels. As two levels
155
+ causes twice as many `hincrby` calls to Redis as not using the grouping
156
+ feature. Hence using 10 grouping levels, causes 10 times as many write calls
157
+ to Redis.
113
158
 
114
- Identifier string to separate different types and groups of statistics from each other. The first argument of the `#store`, `#find`, and `#fetch` methods is the label that you're storing to, or fetching from.
159
+ ### Input Statistics Data
115
160
 
116
- Labels support multiple grouping levels by splitting the label string with `/` and storing the same stats for each level. For example, when storing data to a label called `views/product/44`, the data is stored for the label you specify, and also for `views/product` and `views`.
161
+ You provide Redistat with the data you want to store using a Ruby Hash. This
162
+ data is then stored in a corresponding Redis hash with identical key/field
163
+ names.
117
164
 
118
- A word of caution: Don't use a crazy number of group levels. As two levels causes twice as many `hincrby` calls to Redis as not using the grouping feature. Hence using 10 grouping levels, causes 10 times as many write calls to Redis.
165
+ Key names in the hash also support grouping features similar to those
166
+ available for Labels. Again, the more levels you use, the more write calls to
167
+ Redis, so avoid using 10-15 levels.
119
168
 
120
- ### Input Statistics Data ###
169
+ ### Depth (Storage Accuracy)
121
170
 
122
- You provide Redistat with the data you want to store using a Ruby Hash. This data is then stored in a corresponding Redis hash with identical key/field names.
171
+ Define how accurately data should be stored, and how accurately it's looked up
172
+ when fetching it again. By default Redistat uses a depth value of `:hour`,
173
+ which means it's impossible to separate two events which were stored at 10:18
174
+ and 10:23. In Redis they are both stored within a date key of `2011031610`.
123
175
 
124
- Key names in the hash also support grouping features similar to those available for Labels. Again, the more levels you use, the more write calls to Redis, so avoid using 10-15 levels.
176
+ You can set depth within your model using the `#depth` class method. Available
177
+ depths are: `:year`, `:month`, `:day`, `:hour`, `:min`, `:sec`
125
178
 
126
- ### Depth (Storage Accuracy) ###
179
+ ### Time Ranges
127
180
 
128
- Define how accurately data should be stored, and how accurately it's looked up when fetching it again. By default Redistat uses a depth value of `:hour`, which means it's impossible to separate two events which were stored at 10:18 and 10:23. In Redis they are both stored within a date key of `2011031610`.
181
+ When you fetch data, you need to specify a start and an end time. The
182
+ selection behavior can seem a bit weird at first when, but makes sense when
183
+ you understand how Redistat works internally.
129
184
 
130
- You can set depth within your model using the `#depth` class method. Available depths are: `:year`, `:month`, `:day`, `:hour`, `:min`, `:sec`
185
+ For example, if we are using a Depth value of `:hour`, and we trigger a fetch
186
+ call starting at `1.hour.ago` (13:34), till `Time.now` (14:34), only stats
187
+ from 13:00:00 till 13:59:59 are returned, as they were all stored within the
188
+ key for the 13th hour. If both 13:00 and 14:00 was returned, you would get
189
+ results from two whole hours. Hence if you want up to the second data, use an
190
+ end time of `1.hour.from_now`.
131
191
 
132
- ### Time Ranges ###
192
+ ### The Finder Object
133
193
 
134
- When you fetch data, you need to specify a start and an end time. The selection behavior can seem a bit weird at first when, but makes sense when you understand how Redistat works internally.
194
+ Calling the `#find` method on a Redistat model class returns a
195
+ `Redistat::Finder` object. The finder is a lazy-loaded gateway to your
196
+ data. Meaning you can create a new finder, and modify instantiated finder's
197
+ label, scope, dates, and more. It does not call Redis and fetch the data until
198
+ you call `#total`, `#all`, `#map`, `#each`, or `#each_with_index` on the
199
+ finder.
135
200
 
136
- For example, if we are using a Depth value of `:hour`, and we trigger a fetch call starting at `1.hour.ago` (13:34), till `Time.now` (14:34), only stats from 13:00:00 till 13:59:59 are returned, as they were all stored within the key for the 13th hour. If both 13:00 and 14:00 was returned, you would get results from two hole hours. Hence if you want up to the second data, use an end time of `1.hour.from_now`.
201
+ This section does need further expanding as there's a lot to cover when it
202
+ comes to the finder.
137
203
 
138
- ### The Finder Object ###
139
204
 
140
- Calling the `#find` method on a Redistat model class returns a `Redistat::Finder` object. The finder is a lazy-loaded gateway to your data. Meaning you can create a new finder, and modify instantiated finder's label, scope, dates, and more. It does not call Redis and fetch the data until you call `#total`, `#all`, `#map`, `#each`, or `#each_with_index` on the finder.
205
+ ## Key Expiry
141
206
 
142
- This section does need further expanding as there's a lot to cover when it comes to the finder.
207
+ Support for expiring keys from Redis is available, allowing you too keep
208
+ varying levels of details for X period of time. This allows you easily keep
209
+ things nice and tidy by only storing varying levels detailed stats only for as
210
+ long as you need.
143
211
 
212
+ In the below example we define how long Redis keys for varying depths are
213
+ stored. Second by second stats are available for 10 minutes, minute by minute
214
+ stats for 6 hours, hourly stats for 3 months, daily stats for 2 years, and
215
+ yearly stats are retained forever.
144
216
 
217
+ ```ruby
218
+ class ViewStats
219
+ include Redistat::Model
145
220
 
146
- ## Internals ##
221
+ depth :sec
147
222
 
148
- ### Storing / Writing ###
223
+ expire \
224
+ :sec => 10.minutes.to_i,
225
+ :min => 6.hours.to_i,
226
+ :hour => 3.months.to_i,
227
+ :day => 2.years.to_i
228
+ end
229
+ ```
149
230
 
150
- Redistat stores all data into a Redis hash keys. The Redis key name the used consists of three parts. The scope, label, and datetime:
231
+ Keep in mind that when storing stats for a custom date in the past for
232
+ example, the expiry time for the keys will be relative to now. The values you
233
+ specify are simply passed to the `Redis#expire` method.
234
+
235
+
236
+ ## Internals
237
+
238
+ ### Storing / Writing
239
+
240
+ Redistat stores all data into a Redis hash keys. The Redis key name the used
241
+ consists of three parts. The scope, label, and datetime:
151
242
 
152
243
  {scope}/{label}:{datetime}
153
244
 
154
245
  For example, this...
155
246
 
156
- ViewStats.store('views/product/44', {'count/chrome/11' => 1})
247
+ ```ruby
248
+ ViewStats.store('views/product/44', {'count/chrome/11' => 1})
249
+ ```
157
250
 
158
251
  ...would store the follow hash of data...
159
252
 
160
- { 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 }
161
-
253
+ ```ruby
254
+ { 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 }
255
+ ```
256
+
162
257
  ...to all 12 of these Redis hash keys...
163
258
 
164
259
  ViewStats/views:2011
@@ -174,54 +269,81 @@ For example, this...
174
269
  ViewStats/views/product/44:20110315
175
270
  ViewStats/views/product/44:2011031510
176
271
 
177
- ...by creating the Redis key, and/or hash field if needed, otherwise it simply increments the already existing data.
272
+ ...by creating the Redis key, and/or hash field if needed, otherwise it simply
273
+ increments the already existing data.
178
274
 
179
- It would also create the following Redis sets to keep track of which child labels are available:
275
+ It would also create the following Redis sets to keep track of which child
276
+ labels are available:
180
277
 
181
278
  ViewStats.label_index:
182
279
  ViewStats.label_index:views
183
280
  ViewStats.label_index:views/product
184
281
 
185
- It should now be more obvious to you why you should think about how you use the grouping capabilities so you don't go crazy and use 10-15 levels. Storing is done through Redis' `hincrby` call, which only supports a single key/field combo. Meaning the above example would call `hincrby` a total of 36 times to store the data, and `sadd` a total of 3 times to ensure the label index is accurate. 39 calls is however not a problem for Redis, most calls happen in less than 0.15ms (0.00015 seconds) on my local machine.
282
+ It should now be more obvious to you why you should think about how you use
283
+ the grouping capabilities so you don't go crazy and use 10-15 levels. Storing
284
+ is done through Redis' `hincrby` call, which only supports a single key/field
285
+ combo. Meaning the above example would call `hincrby` a total of 36 times to
286
+ store the data, and `sadd` a total of 3 times to ensure the label index is
287
+ accurate. 39 calls is however not a problem for Redis, most calls happen in
288
+ less than 0.15ms (0.00015 seconds) on my local machine.
186
289
 
187
290
 
188
- ### Fetching / Reading ###
291
+ ### Fetching / Reading
189
292
 
190
- By default when fetching statistics, Redistat will figure out how to do the least number of reads from Redis. First it checks how long range you're fetching. If whole days, months or years for example fit within the start and end dates specified, it will fetch the one key for the day/month/year in question. It further drills down to the smaller units.
293
+ By default when fetching statistics, Redistat will figure out how to do the
294
+ least number of reads from Redis. First it checks how long range you're
295
+ fetching. If whole days, months or years for example fit within the start and
296
+ end dates specified, it will fetch the one key for the day/month/year in
297
+ question. It further drills down to the smaller units.
191
298
 
192
- It is also intelligent enough to not fetch each day from 3-31 of a month, instead it would fetch the data for the whole month and the first two days, which are then removed from the summary of the whole month. This means three calls to `hgetall` instead of 29 if each whole day was fetched.
299
+ It is also intelligent enough to not fetch each day from 3-31 of a month,
300
+ instead it would fetch the data for the whole month and the first two days,
301
+ which are then removed from the summary of the whole month. This means three
302
+ calls to `hgetall` instead of 29 if each whole day was fetched.
193
303
 
194
- ### Buffer ###
304
+ ### Buffer
195
305
 
196
- The buffer is a new, still semi-beta, feature aimed to reduce the number of Redis `hincrby` that Redistat sends. This should only really be useful when you're hitting north of 30,000 Redis requests per second, if your Redis server has limited resources, or against my recommendation you've opted to use 10, 20, or more label grouping levels.
306
+ The buffer is a new, still semi-beta, feature aimed to reduce the number of
307
+ Redis `hincrby` that Redistat sends. This should only really be useful when
308
+ you're hitting north of 30,000 Redis requests per second, if your Redis server
309
+ has limited resources, or against my recommendation you've opted to use 10,
310
+ 20, or more label grouping levels.
197
311
 
198
- Buffering tries to fold together multiple `store` calls into as few as possible by merging the statistics hashes from all calls and groups them based on scope, label, date depth, and more. You configure the the buffer by setting `Redistat.buffer_size` to an integer higher than 1. This basically tells Redistat how many `store` calls to buffer in memory before writing all data to Redis.
312
+ Buffering tries to fold together multiple `store` calls into as few as
313
+ possible by merging the statistics hashes from all calls and groups them based
314
+ on scope, label, date depth, and more. You configure the the buffer by setting
315
+ `Redistat.buffer_size` to an integer higher than 1. This basically tells
316
+ Redistat how many `store` calls to buffer in memory before writing all data to
317
+ Redis.
199
318
 
200
319
 
201
- ## Todo ##
320
+ ## Todo
202
321
 
203
322
  * More details in Readme.
204
323
  * Documentation.
205
324
  * Anything else that becomes apparent after real-world use.
206
325
 
207
326
 
208
- ## Credits ##
327
+ ## Credits
328
+
329
+ [Global Personals](http://globalpersonals.co.uk/) deserves a thank
330
+ you. Currently the primary user of Redistat, they've allowed me to spend some
331
+ company time to further develop the project.
209
332
 
210
- [Global Personals](http://globalpersonals.co.uk/) deserves a thank you. Currently the primary user of Redistat, they've allowed me to spend some company time to further develop the project.
211
333
 
334
+ ## Note on Patches/Pull Requests
212
335
 
213
- ## Note on Patches/Pull Requests ##
214
-
215
336
  * Fork the project.
216
337
  * Make your feature addition or bug fix.
217
338
  * Add tests for it. This is important so I don't break it in a
218
339
  future version unintentionally.
219
- * Commit, do not mess with rakefile, version, or history.
220
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
340
+ * Commit, do not mess with rakefile, version, or history. (if you want to
341
+ have your own version, that is fine but bump version in a commit by itself I
342
+ can ignore when I pull)
221
343
  * Send me a pull request. Bonus points for topic branches.
222
344
 
223
345
 
224
- ## License and Copyright ##
346
+ ## License and Copyright
225
347
 
226
348
  Copyright (c) 2011 Jim Myhrberg.
227
349
 
@@ -39,58 +39,58 @@ require 'redistat/core_ext'
39
39
 
40
40
 
41
41
  module Redistat
42
-
42
+
43
43
  KEY_NEXT_ID = ".next_id"
44
44
  KEY_EVENT = ".event:"
45
45
  KEY_LABELS = "Redistat.labels:" # used for reverse label hash lookup
46
46
  KEY_EVENT_IDS = ".event_ids"
47
47
  LABEL_INDEX = ".label_index:"
48
48
  GROUP_SEPARATOR = "/"
49
-
49
+
50
50
  class InvalidOptions < ArgumentError; end
51
51
  class RedisServerIsTooOld < Exception; end
52
-
52
+
53
53
  class << self
54
-
54
+
55
55
  def buffer
56
56
  Buffer.instance
57
57
  end
58
-
58
+
59
59
  def buffer_size
60
60
  buffer.size
61
61
  end
62
-
62
+
63
63
  def buffer_size=(size)
64
64
  buffer.size = size
65
65
  end
66
-
66
+
67
67
  def thread_safe
68
68
  Synchronize.thread_safe
69
69
  end
70
-
70
+
71
71
  def thread_safe=(value)
72
72
  Synchronize.thread_safe = value
73
73
  end
74
-
74
+
75
75
  def connection(ref = nil)
76
76
  Connection.get(ref)
77
77
  end
78
78
  alias :redis :connection
79
-
79
+
80
80
  def connection=(connection)
81
81
  Connection.add(connection)
82
82
  end
83
83
  alias :redis= :connection=
84
-
84
+
85
85
  def connect(options)
86
86
  Connection.create(options)
87
87
  end
88
-
88
+
89
89
  def flush
90
90
  puts "WARNING: Redistat.flush is deprecated. Use Redistat.redis.flushdb instead."
91
91
  connection.flushdb
92
92
  end
93
-
93
+
94
94
  end
95
95
  end
96
96