Created
October 31, 2012 20:48
-
-
Save mrkvm/3989770 to your computer and use it in GitHub Desktop.
A ridiculous Halloween-themed example of stats tracking using Redis bitwise operations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'redis' | |
class TrickOrTreatTracker | |
def initialize | |
@redis = Redis.new | |
end | |
def track_trick(user_id) | |
key = "trick-#{Time.now.hour}" | |
@redis.setbit key, user_id, 1 | |
@redis.sadd "trick", key | |
end | |
def track_treat(user_id) | |
key = "treat-#{Time.now.hour}" | |
@redis.setbit key, user_id, 1 | |
@redis.sadd "treat", key | |
end | |
def unique_tricks(hour=nil) | |
do_unique(:trick, hour) | |
end | |
def unique_treats(hour=nil) | |
do_unique(:treat, hour) | |
end | |
def unique_tricks_and_treats(hour=nil) | |
do_unique(:trick, hour) + do_unique(:treat, hour) | |
end | |
def check_user(user_id, hour=nil) | |
tricked = false | |
treated = false | |
if hour.nil? | |
tricked = @redis.smembers("trick").any? do |key| | |
@redis.getbit(key, user_id) == 1 | |
end | |
treated = @redis.smembers("treat").any? do |key| | |
@redis.getbit(key, user_id) == 1 | |
end | |
else | |
tricked = (@redis.getbit("#{trick}-#{hour}", user_id) == 1) | |
treated = (@redis.getbit("#{treat}-#{hour}", user_id) == 1) | |
end | |
puts "user #{user_id}: hour=#{hour.nil? ? 'all' : hour} tricked=#{tricked}, treated=#{treated}" | |
end | |
private | |
def do_unique(type, hour) | |
# if hour is nil, then do all tricks/treats | |
if hour.nil? | |
@redis.smembers("#{type}").inject(0) do |total, key| | |
total + @redis.bitcount(key) | |
end | |
else | |
@redis.bitcount "#{type}-#{hour}" | |
end | |
end | |
end | |
if __FILE__ == $0 | |
Redis.new.flushall | |
tracker = TrickOrTreatTracker.new | |
rand(10).times do | |
tracker.track_trick(rand(20)) | |
end | |
rand(10).times do | |
tracker.track_treat(rand(20)) | |
end | |
puts "Total Unique Tricks: #{tracker.unique_tricks}" | |
puts "Total Unique Treats: #{tracker.unique_treats}" | |
puts "Combined Unique Tricks/Treats: #{tracker.unique_tricks_and_treats}" | |
(0...20).each do |user_id| | |
tracker.check_user user_id | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment