diff --git a/lib/redistat/collection.rb b/lib/redistat/collection.rb index eea6891..a8feaf7 100644 --- a/lib/redistat/collection.rb +++ b/lib/redistat/collection.rb @@ -1,7 +1,16 @@ module Redistat - class Collection < Array + class Collection < ::Array + attr_accessor :from + attr_accessor :till + attr_accessor :depth + attr_accessor :total + def initialize(options = {}) + @from = options[:from] ||= nil + @till = options[:till] ||= nil + @depth = options[:depth] ||= nil + end end end \ No newline at end of file diff --git a/lib/redistat/finder.rb b/lib/redistat/finder.rb index b49ba27..77791ba 100644 --- a/lib/redistat/finder.rb +++ b/lib/redistat/finder.rb @@ -26,27 +26,47 @@ module Redistat def find_by_interval(options = {}) @options.merge!(options) raise InvalidOptions.new if !valid_options? - date_sets = Finder::DateSet.new(@options[:from], @options[:till], @options[:depth], @options[:interval]) - + key = build_key + col = Collection.new(@options) + col.total = Result.new(@options) + build_date_sets.each do |set| + set[:add].each do |date| + result = Result.new + result.date = Date.new(date).to_time + db.hgetall("#{key.prefix}#{date}").each do |k, v| + result[k] = v + col.total.set_or_incr(k, v.to_i) + end + col << result + end + end + col end def find_by_magic(options = {}) @options.merge!(options) raise InvalidOptions.new if !valid_options? - date_sets = Finder::DateSet.new(@options[:from], @options[:till], @options[:depth], @options[:interval]) key = Key.new(@options[:scope], @options[:label]) - total_sum = Result.new - date_sets.each do |set| + col = Collection.new(@options) + col.total = Result.new(@options) + col << col.total + build_date_sets.each do |set| sum = Result.new sum = summarize_add_keys(set[:add], key, sum) sum = summarize_rem_keys(set[:rem], key, sum) sum.each do |k, v| - total_sum.set_or_incr(k, v.to_i) + col.total.set_or_incr(k, v.to_i) end end - total_sum.date = Date.new(@options[:from], @options[:depth]) - total_sum.till = Date.new(@options[:till], @options[:depth]) - total_sum + col + end + + def build_date_sets + Finder::DateSet.new(@options[:from], @options[:till], @options[:depth], @options[:interval]) + end + + def build_key + Key.new(@options[:scope], @options[:label]) end def summarize_add_keys(sets, key, sum) diff --git a/lib/redistat/result.rb b/lib/redistat/result.rb index 1f658d7..e433055 100644 --- a/lib/redistat/result.rb +++ b/lib/redistat/result.rb @@ -1,9 +1,18 @@ module Redistat class Result < ::Hash - attr_accessor :date + attr_accessor :from attr_accessor :till + alias :date :from + alias :date= :from= + + def initialize(options = {}) + @from = options[:from] ||= nil + @till = options[:till] ||= nil + end + + def set_or_incr(key, value) self[key] = 0 if !self.has_key?(key) self[key] += value diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb new file mode 100644 index 0000000..52b8834 --- /dev/null +++ b/spec/collection_spec.rb @@ -0,0 +1,13 @@ +require "spec_helper" + +describe Redistat::Collection do + + it "should should initialize properly" do + options = {:from => "from", :till => "till", :depth => "depth"} + result = Redistat::Collection.new(options) + result.from.should == options[:from] + result.till.should == options[:till] + result.depth.should == options[:depth] + end + +end \ No newline at end of file diff --git a/spec/finder_spec.rb b/spec/finder_spec.rb index 3c76eb1..bc78fed 100644 --- a/spec/finder_spec.rb +++ b/spec/finder_spec.rb @@ -44,32 +44,41 @@ describe Redistat::Finder do end it "should fetch stats properly" do - create_example_stats + first_stat, last_stat = create_example_stats - three_hours_ago = 3.hours.ago - two_hours_from_now = 2.hours.from_now - depth = :hour + stats = Redistat::Finder.find({:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour}) + stats.from.should == first_stat + stats.till.should == last_stat + stats.depth.should == :hour - stats = Redistat::Finder.find({:from => three_hours_ago, :till => two_hours_from_now, :scope => @scope, :label => @label, :depth => depth}) - stats.should == { "views" => 9, "visitors" => 6 } - stats.date.to_s.should == three_hours_ago.to_rs.to_s(depth) - stats.till.to_s.should == two_hours_from_now.to_rs.to_s(depth) + stats.total.should == { "views" => 12, "visitors" => 8 } + stats.total.from.should == first_stat + stats.total.till.should == last_stat + stats.first.should == stats.total + end + + it "should fetch data per unit when interval option is specified" do + first_stat, last_stat = create_example_stats + + stats = Redistat::Finder.find(:from => first_stat, :till => last_stat, :scope => @scope, :label => @label, :depth => :hour, :interval => :hour) + stats.from.should == first_stat + stats.till.should == last_stat + stats.total.should == { "views" => 12, "visitors" => 8 } + stats[0].should == {} + stats[0].date.should == Time.parse("2010-05-14 12:00") + stats[1].should == {"visitors"=>"4", "views"=>"6"} + stats[1].date.should == Time.parse("2010-05-14 13:00") + stats[2].should == {"visitors"=>"2", "views"=>"3"} + stats[2].date.should == Time.parse("2010-05-14 14:00") + stats[3].should == {"visitors"=>"2", "views"=>"3"} + stats[3].date.should == Time.parse("2010-05-14 15:00") + stats[4].should == {} + stats[4].date.should == Time.parse("2010-05-14 16:00") end it "should return empty hash when attempting to fetch non-existent results" do stats = Redistat::Finder.find({:from => 3.hours.ago, :till => 2.hours.from_now, :scope => @scope, :label => @label, :depth => :hour}) - stats.should == {} - end - - it "should fetch data per unit when interval option is specified" do - create_example_stats - - three_hours_ago = 3.hours.ago - two_hours_from_now = 2.hours.from_now - depth = :hour - - stats = Redistat::Finder.find(:from => 3.hours.ago, :till => 2.hours.ago, :scope => @scope, :label => @label, :depth => :hour, :interval => :hour) - puts "\n>>>>>> stats: " + stats.inspect + "\n" + stats.total.should == {} end it "should throw error on invalid options" do @@ -84,12 +93,15 @@ describe Redistat::Finder do # helper methods def create_example_stats - key = Redistat::Key.new(@scope, @label, 2.hours.ago) + key = Redistat::Key.new(@scope, @label, (first = Time.parse("2010-05-14 13:43"))) Redistat::Summary.update(key, @stats, :hour) - key = Redistat::Key.new(@scope, @label, 1.hours.ago) + key = Redistat::Key.new(@scope, @label, Time.parse("2010-05-14 13:53")) Redistat::Summary.update(key, @stats, :hour) - key = Redistat::Key.new(@scope, @label, 24.minutes.ago) + key = Redistat::Key.new(@scope, @label, Time.parse("2010-05-14 14:32")) Redistat::Summary.update(key, @stats, :hour) + key = Redistat::Key.new(@scope, @label, (last = Time.parse("2010-05-14 15:02"))) + Redistat::Summary.update(key, @stats, :hour) + [first - 1.hour, last + 1.hour] end end diff --git a/spec/result_spec.rb b/spec/result_spec.rb index e26bb19..d069e12 100644 --- a/spec/result_spec.rb +++ b/spec/result_spec.rb @@ -2,9 +2,11 @@ require "spec_helper" describe Redistat::Result do - before(:each) do - @name = "PageViews" - @scope = Redistat::Scope.new(@name) + it "should should initialize properly" do + options = {:from => "from", :till => "till"} + result = Redistat::Result.new(options) + result.from.should == "from" + result.till.should == "till" end it "should have set_or_incr method" do