mirror of
https://github.com/jimeh/redistat.git
synced 2026-02-19 13:26:39 +00:00
initial work and specs to properly support lazy-loading results from Finder objects
This commit is contained in:
@@ -2,97 +2,7 @@ module Redistat
|
||||
class Finder
|
||||
include Database
|
||||
|
||||
attr_reader :options
|
||||
|
||||
def initialize(options = {})
|
||||
@options = options
|
||||
end
|
||||
|
||||
def db
|
||||
super(@options[:connection_ref])
|
||||
end
|
||||
|
||||
def valid_options?
|
||||
return true if !@options[:scope].blank? && !@options[:label].blank? && !@options[:from].blank? && !@options[:till].blank?
|
||||
false
|
||||
end
|
||||
|
||||
def find(options = {})
|
||||
@options.merge!(options)
|
||||
raise InvalidOptions.new if !valid_options?
|
||||
if @options[:interval].nil? || !@options[:interval]
|
||||
find_by_magic
|
||||
else
|
||||
find_by_interval
|
||||
end
|
||||
end
|
||||
|
||||
def find_by_interval(options = {})
|
||||
@options.merge!(options)
|
||||
raise InvalidOptions.new if !valid_options?
|
||||
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?
|
||||
key = Key.new(@options[:scope], @options[:label])
|
||||
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|
|
||||
col.total.set_or_incr(k, v.to_i)
|
||||
end
|
||||
end
|
||||
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)
|
||||
sets.each do |date|
|
||||
db.hgetall("#{key.prefix}#{date}").each do |k, v|
|
||||
sum.set_or_incr(k, v.to_i)
|
||||
end
|
||||
end
|
||||
sum
|
||||
end
|
||||
|
||||
def summarize_rem_keys(sets, key, sum)
|
||||
sets.each do |date|
|
||||
db.hgetall("#{key.prefix}#{date}").each do |k, v|
|
||||
sum.set_or_incr(k, -v.to_i)
|
||||
end
|
||||
end
|
||||
sum
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
def find(*args)
|
||||
new.find(*args)
|
||||
end
|
||||
@@ -126,15 +36,49 @@ module Redistat
|
||||
def interval(unit)
|
||||
new.interval(unit)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
attr_reader :options
|
||||
|
||||
def initialize(options = {})
|
||||
@options = options
|
||||
end
|
||||
|
||||
def all(reload = false)
|
||||
@result = nil if reload
|
||||
@result ||= find
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
all.each(&block)
|
||||
end
|
||||
|
||||
def map(&block)
|
||||
all.map(&block)
|
||||
end
|
||||
|
||||
def each_with_index(&block)
|
||||
all.each_with_index(&block)
|
||||
end
|
||||
|
||||
def reset!
|
||||
@result = nil
|
||||
end
|
||||
|
||||
def connection_ref(ref)
|
||||
reset! if @options[:connection_ref] != ref
|
||||
@options[:connection_ref] = ref
|
||||
self
|
||||
end
|
||||
|
||||
def scope(scope)
|
||||
reset! if @options[:scope] != scope
|
||||
@options[:scope] = scope
|
||||
self
|
||||
end
|
||||
|
||||
def label(label)
|
||||
reset! if @options[:label] != label
|
||||
@options[:label] = label
|
||||
self
|
||||
end
|
||||
@@ -145,25 +89,120 @@ module Redistat
|
||||
alias :date :dates
|
||||
|
||||
def from(date)
|
||||
reset! if @options[:from] != date
|
||||
@options[:from] = date
|
||||
self
|
||||
end
|
||||
|
||||
def till(date)
|
||||
reset! if @options[:till] != date
|
||||
@options[:till] = date
|
||||
self
|
||||
end
|
||||
alias :until :till
|
||||
|
||||
def depth(unit)
|
||||
reset! if @options[:depth] != unit
|
||||
@options[:depth] = unit
|
||||
self
|
||||
end
|
||||
|
||||
def interval(unit)
|
||||
reset! if @options[:interval] != unit
|
||||
@options[:interval] = unit
|
||||
self
|
||||
end
|
||||
|
||||
def find(options = {})
|
||||
set_options(options)
|
||||
raise InvalidOptions.new if !valid_options?
|
||||
if @options[:interval].nil? || !@options[:interval]
|
||||
find_by_magic
|
||||
else
|
||||
find_by_interval
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_options(opts = {})
|
||||
opts = opts.clone
|
||||
opts.each do |key, value|
|
||||
self.send(key, opts.delete(key)) if self.respond_to?(key)
|
||||
end
|
||||
@options.merge!(opts)
|
||||
end
|
||||
|
||||
def find_by_interval(options = {})
|
||||
raise InvalidOptions.new if !valid_options?
|
||||
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 = {})
|
||||
raise InvalidOptions.new if !valid_options?
|
||||
key = Key.new(@options[:scope], @options[:label])
|
||||
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|
|
||||
col.total.set_or_incr(k, v.to_i)
|
||||
end
|
||||
end
|
||||
col
|
||||
end
|
||||
|
||||
def db
|
||||
super(@options[:connection_ref])
|
||||
end
|
||||
|
||||
def valid_options?
|
||||
return true if !@options[:scope].blank? && !@options[:label].blank? && !@options[:from].blank? && !@options[:till].blank?
|
||||
false
|
||||
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)
|
||||
sets.each do |date|
|
||||
db.hgetall("#{key.prefix}#{date}").each do |k, v|
|
||||
sum.set_or_incr(k, v.to_i)
|
||||
end
|
||||
end
|
||||
sum
|
||||
end
|
||||
|
||||
def summarize_rem_keys(sets, key, sum)
|
||||
sets.each do |date|
|
||||
db.hgetall("#{key.prefix}#{date}").each do |k, v|
|
||||
sum.set_or_incr(k, -v.to_i)
|
||||
end
|
||||
end
|
||||
sum
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -19,6 +19,10 @@ describe Redistat::Finder do
|
||||
|
||||
finder = Redistat::Finder.new(options)
|
||||
finder.options.should == options
|
||||
|
||||
finder = Redistat::Finder.new
|
||||
finder.send(:set_options, options)
|
||||
finder.options.should == options
|
||||
|
||||
finder = Redistat::Finder.dates(two_hours_ago, one_hour_ago).scope("PageViews").label("Label").depth(:hour).interval(:hour)
|
||||
finder.options.should == options
|
||||
@@ -57,6 +61,29 @@ describe Redistat::Finder do
|
||||
stats.first.should == stats.total
|
||||
end
|
||||
|
||||
it "should be lazy-loaded" do
|
||||
first_stat, last_stat = create_example_stats
|
||||
|
||||
finder = Redistat::Finder.new
|
||||
finder.from(first_stat).till(last_stat)
|
||||
finder.scope(@scope).label(@label)
|
||||
finder.depth(:hour)
|
||||
|
||||
finder.instance_variable_get("@result").should be_nil
|
||||
stats = finder.all
|
||||
finder.instance_variable_get("@result").should_not be_nil
|
||||
|
||||
stats.total.should == { "views" => 12, "visitors" => 8 }
|
||||
stats.total.from.should == first_stat
|
||||
stats.total.till.should == last_stat
|
||||
stats.first.should == stats.total
|
||||
|
||||
finder.all.object_id.should == stats.object_id
|
||||
finder.from(first_stat + 1.hour)
|
||||
finder.instance_variable_get("@result").should be_nil
|
||||
finder.all.object_id.should_not == stats.object_id
|
||||
end
|
||||
|
||||
it "should fetch data per unit when interval option is specified" do
|
||||
first_stat, last_stat = create_example_stats
|
||||
|
||||
|
||||
Reference in New Issue
Block a user