Introduction
Introduction Statistics Contact Development Disclaimer Help
Greatly improve performance. - reportable - Fork of reportable required by WarV…
Log
Files
Refs
README
---
commit 5f29dfb16b4b34158a89f37283d31d2c42852f04
parent 880e98fc581fd44bac7c4e9337a755be19c7ed24
Author: Cristi Balan <[email protected]>
Date: Fri, 21 Dec 2012 17:55:51 +0200
Greatly improve performance.
Fetch only missing cached data if we're only missing a contiguous part at the e…
Diffstat:
M lib/saulabs/reportable/report_cach… | 50 +++++++++++++++++++++------…
M spec/classes/report_cache_spec.rb | 16 ++++++++++++----
M spec/classes/report_spec.rb | 136 +++++++++++++++++++++++++++++…
3 files changed, 182 insertions(+), 20 deletions(-)
---
diff --git a/lib/saulabs/reportable/report_cache.rb b/lib/saulabs/reportable/re…
@@ -69,6 +69,15 @@ module Saulabs
#
def self.process(report, options, &block)
raise ArgumentError.new('A block must be given') unless block_given?
+
+ # If end_date is in the middle of the current reporting period it mean…
+ # Update the options hash to reflect reality.
+ current_reporting_period = ReportingPeriod.new(options[:grouping])
+ if options[:end_date] && options[:end_date] > current_reporting_period…
+ options[:live_data] = true
+ options.delete(:end_date)
+ end
+
self.transaction do
cached_data = read_cached_data(report, options)
new_data = read_new_data(cached_data, options, &block)
@@ -140,11 +149,10 @@ module Saulabs
serialize_conditions(options[:conditions])
]
first_reporting_period = get_first_reporting_period(options)
- last_reporting_period = get_last_reporting_period(options)
- if last_reporting_period
+ if options[:end_date]
conditions.first << ' AND reporting_period BETWEEN ? AND ?'
conditions << first_reporting_period.date_time
- conditions << last_reporting_period.date_time
+ conditions << ReportingPeriod.new(options[:grouping], options[:end…
else
conditions.first << ' AND reporting_period >= ?'
conditions << first_reporting_period.date_time
@@ -157,16 +165,30 @@ module Saulabs
end
def self.read_new_data(cached_data, options, &block)
- if !options[:live_data] && cached_data.length == options[:limit]
- []
+ return [] if !options[:live_data] && cached_data.length == options[:…
+
+ first_reporting_period_to_read = get_first_reporting_period_to_read(…
+ last_reporting_period_to_read = options[:end_date] ? ReportingPeriod…
+
+ yield(first_reporting_period_to_read.date_time, last_reporting_perio…
+ end
+
+ def self.get_first_reporting_period_to_read(cached_data, options)
+ return get_first_reporting_period(options) if cached_data.empty?
+
+ last_cached_reporting_period = ReportingPeriod.new(options[:grouping…
+ missing_reporting_periods = options[:limit] - cached_data.length
+ last_reporting_period = if !options[:live_data] && options[:end_date]
+ ReportingPeriod.new(options[:grouping], options[:end_date])
else
- first_reporting_period_to_read = if cached_data.length < options[:…
- get_first_reporting_period(options)
- else
- ReportingPeriod.new(options[:grouping], cached_data.last.reporti…
- end
- last_reporting_period_to_read = options[:end_date] ? ReportingPeri…
- yield(first_reporting_period_to_read.date_time, last_reporting_per…
+ ReportingPeriod.new(options[:grouping]).previous
+ end
+
+ if missing_reporting_periods == 0 || last_cached_reporting_period.of…
+ # cache only has missing data contiguously at the end
+ last_cached_reporting_period.next
+ else
+ get_first_reporting_period(options)
end
end
@@ -178,10 +200,6 @@ module Saulabs
end
end
- def self.get_last_reporting_period(options)
- return ReportingPeriod.new(options[:grouping], options[:end_date]) i…
- end
-
end
end
diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec…
@@ -184,7 +184,7 @@ describe Saulabs::Reportable::ReportCache do
describe 'with :end_date = <some date>' do
before do
- @options = @report.options.merge(:end_date => Time.now)
+ @options = @report.options.merge(:end_date => Time.now - 1.send(@rep…
end
it 'should yield the last date and time of the reporting period for th…
@@ -221,7 +221,7 @@ describe Saulabs::Reportable::ReportCache do
end
it 'should utilize the end_date in the conditions' do
- end_date = Time.now
+ end_date = Time.now - 1.send(@report.options[:grouping].identifier)
Saulabs::Reportable::ReportCache.should_receive(:all).once.with(
:conditions => [
%w(model_name report_name grouping aggregation conditions).map do |c…
@@ -232,7 +232,7 @@ describe Saulabs::Reportable::ReportCache do
@report.options[:grouping].identifier.to_s,
@report.aggregation.to_s,
'',
- Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping…
+ Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping…
Saulabs::Reportable::ReportingPeriod.new(@report.options[:grouping],…
],
:limit => 10,
@@ -271,7 +271,15 @@ describe Saulabs::Reportable::ReportCache do
end
end
end
-
+
+ describe '.get_first_reporting_period_to_read' do
+ it 'returns first reporting period if no cached data' do
+ Saulabs::Reportable::ReportCache.should_receive(:get_first_reporting_per…
+ result = Saulabs::Reportable::ReportCache.send(:get_first_reporting_peri…
+ result.should == 'first'
+ end
+ end
+
describe '.serialize_conditions' do
it 'should serialize empty conditions correctly' do
diff --git a/spec/classes/report_spec.rb b/spec/classes/report_spec.rb
@@ -77,6 +77,142 @@ describe Saulabs::Reportable::Report do
User.create!(:login => 'test 4', :created_at => Time.now - 3.send(gr…
end
+ describe 'optimized querying with contiguously cached data' do
+ it "should be optimized with specified end_date" do
+ @end_date = DateTime.now - 1.send(grouping)
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10,
+ :end_date => @end_date
+ )
+ @result = @report.run
+
+ Saulabs::Reportable::ReportCache.last.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.date_time
+ end_at.should == reporting_period.last_date_time
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+
+ it "should be optimized without specific end_date and live_data" do
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10,
+ :live_data => true
+ )
+ @result = @report.run.to_a
+
+ Saulabs::Reportable::ReportCache.last.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.date_time
+ end_at.should == nil
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+
+ it "should be optimized without specific end_date and without live_d…
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10
+ )
+ @result = @report.run.to_a
+
+ Saulabs::Reportable::ReportCache.last.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.date_time
+ end_at.should == nil
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+ end
+
+ describe 'non optimized querying when gaps present in cached data' do
+ it "should not be optimized with specified end_date" do
+ @end_date = DateTime.now - 1.send(grouping)
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10,
+ :end_date => @end_date
+ )
+ @result = @report.run
+
+ Saulabs::Reportable::ReportCache.first.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.offset(-9).date_time
+ end_at.should == reporting_period.last_date_time
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+
+ it "should not be optimized without specific end_date and live_data"…
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10,
+ :live_data => true
+ )
+ @result = @report.run.to_a
+
+ Saulabs::Reportable::ReportCache.first.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.offset(-9).date_time
+ end_at.should == nil
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+
+ it "should not be optimized without specific end_date and without li…
+ @report = Saulabs::Reportable::Report.new(User, :registrations,
+ :grouping => grouping,
+ :limit => 10
+ )
+ @result = @report.run.to_a
+
+ Saulabs::Reportable::ReportCache.first.delete
+
+ grouping_instance = Saulabs::Reportable::Grouping.new(grouping)
+ reporting_period = Saulabs::Reportable::ReportingPeriod.new(groupi…
+
+ @report.should_receive(:read_data) do |begin_at, end_at, options|
+ begin_at.should == reporting_period.offset(-9).date_time
+ end_at.should == nil
+ [] # without this rspec whines about an ambiguous return value
+ end
+
+ @result = @report.run
+ end
+ end
+
describe 'when :end_date is specified' do
it 'should not raise a SQL duplicate key error after multiple runs' …
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.