bellycard/redistat — pull request #17 by joedivita (2014-01-22 06:04:29+00:00)
Title: Adding increment / decrement / find functionality for Unique Counters

Adding support for Unique Counters, and all methods minus aggregate which I will be doing in a separate PR.

Unique counters are used when an event with the same unique_id should not be counted twice. A general example of this could be a counter for the number of users (rather than total visits) that visited a place. In this case the "id" parameter would represent the id of the place and the unique_id would be the users id.

Unique counters utilize Redis bitmaps and although their api is the same as regular counters, their implementations of the same methods are slightly different.

This pull request enables the following:

Incrementing / Decrementing (which essentially just set bits to 1 or 0 for that particular unique id)
``` ruby
Customers.increment(id: 1, timestamp: '2014-01-05', unique_id: 1000)
Customers.decrement(id: 1, timestamp: '2014-01-05', unique_id: 1001)
```

Find:
```ruby
Customers.find(id: 1, year: 2014, month: 1, day: 5, unique_id: 1000) # Returns 0 or 1
```

TODO: implement aggregation methods to find total unique's for a given id across a timespan.

Both methods support batch queries for multiple keys at once.

For memory optimization, indexes on the bitmaps do not match the unique_id exactly. Doing that would mean that a unique_id of 10000 would create a bitmap of size 100000 for just one unique_id. Instead, each model of type :unique has an associated unique_ids index hash, which maps the unique_id with its associated index on the bitmap.