Skip to content
  • 9 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
Showing with 82 additions and 11 deletions.
  1. +4 −1 .travis.yml
  2. +30 −0 README.md
  3. +5 −0 lib/redistat/connection.rb
  4. +8 −0 lib/redistat/model.rb
  5. +17 −10 lib/redistat/summary.rb
  6. +1 −0 spec/model_helper.rb
  7. +2 −0 spec/model_spec.rb
  8. +15 −0 spec/summary_spec.rb
View
5 .travis.yml
@@ -1,5 +1,8 @@
+language: ruby
rvm:
- 1.8.7
- 1.9.2
- - jruby
+ - 1.9.3
+ - jruby-18mode
+ - jruby-19mode
- ree
View
30 README.md
@@ -202,6 +202,36 @@ This section does need further expanding as there's a lot to cover when it
comes to the finder.
+## Key Expiry
+
+Support for expiring keys from Redis is available, allowing you too keep
+varying levels of details for X period of time. This allows you easily keep
+things nice and tidy by only storing varying levels detailed stats only for as
+long as you need.
+
+In the below example we define how long Redis keys for varying depths are
+stored. Second by second stats are available for 10 minutes, minute by minute
+stats for 6 hours, hourly stats for 3 months, daily stats for 2 years, and
+yearly stats are retained forever.
+
+```ruby
+class ViewStats
+ include Redistat::Model
+
+ depth :sec
+
+ expire \
+ :sec => 10.minutes.to_i,
+ :min => 6.hours.to_i,
+ :hour => 3.months.to_i,
+ :day => 2.years.to_i
+end
+```
+
+Keep in mind that when storing stats for a custom date in the past for
+example, the expiry time for the keys will be relative to now. The values you
+specify are simply passed to the `Redis#expire` method.
+
## Internals
View
5 lib/redistat/connection.rb
@@ -4,6 +4,7 @@ module Redistat
module Connection
REQUIRED_SERVER_VERSION = "1.3.10"
+ MIN_EXPIRE_SERVER_VERSION = "2.1.3"
# TODO: Create a ConnectionPool instance object using Sychronize mixin to replace Connection class
@@ -67,6 +68,10 @@ def connection_id(options = {})
def check_redis_version(conn)
raise RedisServerIsTooOld if conn.info["redis_version"] < REQUIRED_SERVER_VERSION
+ if conn.info["redis_version"] < MIN_EXPIRE_SERVER_VERSION
+ STDOUT.puts "WARNING: You MUST upgrade Redis to v2.1.3 or later " +
+ "if you are using key expiry."
+ end
conn
end
View
8 lib/redistat/model.rb
@@ -46,6 +46,14 @@ def find_event(event_id)
alias :class_name :scope
+ def expire(exp = nil)
+ if !exp.nil?
+ options[:expire] = exp.is_a?(Hash) ? exp : Hash.new(exp)
+ else
+ options[:expire]
+ end
+ end
+
def connect_to(opts = {})
Connection.create(opts.merge(:ref => name))
options[:connection_ref] = name
View
27 lib/redistat/summary.rb
@@ -5,9 +5,12 @@ class Summary
class << self
def default_options
- { :enable_grouping => true,
- :label_indexing => true,
- :connection_ref => nil }
+ {
+ :enable_grouping => true,
+ :label_indexing => true,
+ :connection_ref => nil,
+ :expire => {}
+ }
end
def buffer
@@ -29,30 +32,34 @@ def update_through_buffer(*args)
update(*args) unless buffer.store(*args)
end
- def update(key, stats, depth_limit, opts)
+ def update(key, stats, depth_limit, opts = {})
if opts[:enable_grouping]
stats = inject_group_summaries(stats)
key.groups.each do |k|
- update_key(k, stats, depth_limit, opts[:connection_ref])
+ update_key(k, stats, depth_limit, opts)
k.update_index if opts[:label_indexing]
end
else
- update_key(key, stats, depth_limit, opts[:connection_ref])
+ update_key(key, stats, depth_limit, opts)
end
end
private
- def update_key(key, stats, depth_limit, connection_ref)
+ def update_key(key, stats, depth_limit, opts = {})
Date::DEPTHS.each do |depth|
- update_fields(key, stats, depth, connection_ref)
+ update_fields(key, stats, depth, opts)
break if depth == depth_limit
end
end
- def update_fields(key, stats, depth, connection_ref = nil)
+ def update_fields(key, stats, depth, opts = {})
stats.each do |field, value|
- db(connection_ref).hincrby key.to_s(depth), field, value
+ db(opts[:connection_ref]).hincrby key.to_s(depth), field, value
+ end
+
+ if opts[:expire] && !opts[:expire][depth].nil?
+ db(opts[:connection_ref]).expire key.to_s(depth), opts[:expire][depth]
end
end
View
1 spec/model_helper.rb
@@ -26,5 +26,6 @@ class ModelHelper4
include Redistat::Model
scope "FancyHelper"
+ expire :hour => 24*3600
end
View
2 spec/model_spec.rb
@@ -38,6 +38,7 @@
ModelHelper2.store_event.should == true
ModelHelper2.hashed_label.should == true
ModelHelper2.scope.should be_nil
+ ModelHelper2.expire.should be_nil
ModelHelper1.depth.should == nil
ModelHelper1.store_event.should == nil
@@ -57,6 +58,7 @@
ModelHelper4.scope.should == "FancyHelper"
ModelHelper4.send(:name).should == "FancyHelper"
+ ModelHelper4.expire.should == {:hour => 24*3600}
end
it "should store and fetch stats" do
View
15 spec/summary_spec.rb
@@ -10,6 +10,7 @@
@date = Time.now
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
@stats = {"views" => 3, "visitors" => 2}
+ @expire = {:hour => 24*3600}
end
it "should update a single summary properly" do
@@ -32,6 +33,20 @@
summary["visitors"].should == "1"
end
+ it "should set key expiry properly" do
+ Redistat::Summary.update_all(@key, @stats, :hour,{:expire => @expire})
+ ((24*3600)-1..(24*3600)+1).should include(db.ttl(@key.to_s(:hour)))
+ [:day, :month, :year].each do |depth|
+ db.ttl(@key.to_s(depth)).should == -1
+ end
+
+ db.flushdb
+ Redistat::Summary.update_all(@key, @stats, :hour, {:expire => {}})
+ [:hour, :day, :month, :year].each do |depth|
+ db.ttl(@key.to_s(depth)).should == -1
+ end
+ end
+
it "should update all summaries properly" do
Redistat::Summary.update_all(@key, @stats, :sec)
[:year, :month, :day, :hour, :min, :sec, :usec].each do |depth|

No commit comments for this range

Something went wrong with that request. Please try again.