Class: RedTrend

Inherits:
Object
  • Object
show all
Defined in:
lib/red_trend.rb,
lib/red_trend/version.rb

Constant Summary collapse

CYCLE_UNITS =
{
  :minute => 60,
  :hour  => 3600,
  :day => 86400
}.freeze
VERSION =
"0.0.2"

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ RedTrend

Returns a new instance of RedTrend.



22
23
24
25
26
27
# File 'lib/red_trend.rb', line 22

def initialize(options = {})
  @options = options
  unless CYCLE_UNITS.include?(cycle_unit)
    raise ArgumentError, "cycle unit must be in #{CYCLE_UNITS.keys}"
  end
end

Class Attribute Details

.redisObject



15
16
17
# File 'lib/red_trend.rb', line 15

def redis
  @redis ||= Redis.new
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



20
21
22
# File 'lib/red_trend.rb', line 20

def options
  @options
end

Instance Method Details

#current_cycleObject



49
50
51
52
53
54
55
56
57
58
# File 'lib/red_trend.rb', line 49

def current_cycle
  method = case cycle_unit
           when :minute then :min
           when :hour then :hour
           when :day then :yday
           end

  time = @time || Time.now
  (time.send(method) % cycles_count) + 1
end

#cycle_intervalObject

The interval length of each cycle, probably days for production



45
46
47
# File 'lib/red_trend.rb', line 45

def cycle_interval
  cycle_length * cycles_count
end

#cycle_lengthObject



34
35
36
# File 'lib/red_trend.rb', line 34

def cycle_length
  CYCLE_UNITS[cycle_unit]
end

#cycle_positionsObject



60
61
62
63
64
65
66
# File 'lib/red_trend.rb', line 60

def cycle_positions
  1.upto(cycles_count - 1).inject([current_cycle]) do |n_cycles, offset|
    n = current_cycle - offset
    n = n + cycles_count if n < 1
    n_cycles << n
  end
end

#cycle_unitObject

The length of 1 cycle



39
40
41
# File 'lib/red_trend.rb', line 39

def cycle_unit
  @options.fetch(:cycle_unit, :hour)
end

#cycle_weightsObject



103
104
105
106
107
# File 'lib/red_trend.rb', line 103

def cycle_weights
  cycles_count.times.inject([]) do |weights, n|
    weights << 1 - n * weight_offset
  end
end

#cycles_countObject

How many cycles we’ll persist data for



30
31
32
# File 'lib/red_trend.rb', line 30

def cycles_count
  @options.fetch(:cycles_count, 3)
end

#record(key, member) ⇒ Object

Increment the leaderboard score for the object on the sorted set for the current cycle. Make the key volitile so that it doesn’t persist past the number of cycles. Store the union score set after each new score



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/red_trend.rb', line 73

def record(key, member)
  @time = Time.now

  n_key = make_key(key, current_cycle)

  zcard = redis.zcard(n_key)

  redis.multi do
    redis.zincrby n_key, 1, member
    # FIXME I'm not certain the second redis.ttl is working in the multi
    if zcard < 1 || redis.ttl(n_key) == -1
      redis.expire n_key, calculate_expire_seconds
    end
    unionize_sets(key)
  end

  @time = nil

  true
end

#top(key, limit = 10) ⇒ Object

Returns top scoring ids for the current interval



95
96
97
# File 'lib/red_trend.rb', line 95

def top(key, limit = 10)
  redis.zrevrange make_key(key), 0, limit - 1
end

#weight_offsetObject



99
100
101
# File 'lib/red_trend.rb', line 99

def weight_offset
  ("%0.1f" % (1 / cycles_count.to_f)).to_f
end