From 7b14b9b5ab427d443da55a6b43234f1b6a200b5c Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Tue, 17 Apr 2012 13:03:38 +0100 Subject: [PATCH] Clean up whitespace --- README.md | 6 +- lib/redistat.rb | 26 +-- lib/redistat/buffer.rb | 40 ++--- lib/redistat/collection.rb | 10 +- lib/redistat/connection.rb | 36 ++-- lib/redistat/core_ext.rb | 2 +- lib/redistat/core_ext/bignum.rb | 4 +- lib/redistat/core_ext/date.rb | 4 +- lib/redistat/core_ext/fixnum.rb | 4 +- lib/redistat/core_ext/hash.rb | 8 +- lib/redistat/date.rb | 22 +-- lib/redistat/event.rb | 36 ++-- lib/redistat/finder.rb | 78 ++++----- lib/redistat/finder/date_set.rb | 8 +- lib/redistat/key.rb | 32 ++-- lib/redistat/label.rb | 28 +-- lib/redistat/mixins/database.rb | 2 +- lib/redistat/mixins/date_helper.rb | 2 +- lib/redistat/mixins/options.rb | 16 +- lib/redistat/mixins/synchronize.rb | 20 +-- lib/redistat/model.rb | 34 ++-- lib/redistat/result.rb | 8 +- lib/redistat/scope.rb | 10 +- lib/redistat/summary.rb | 32 ++-- spec/buffer_spec.rb | 38 ++-- spec/collection_spec.rb | 8 +- spec/connection_spec.rb | 24 +-- spec/core_ext/hash_spec.rb | 10 +- spec/database_spec.rb | 6 +- spec/date_spec.rb | 30 ++-- spec/event_spec.rb | 16 +- spec/finder/date_set_spec.rb | 268 ++++++++++++++--------------- spec/finder_spec.rb | 72 ++++---- spec/key_spec.rb | 38 ++-- spec/label_spec.rb | 20 +-- spec/model_helper.rb | 18 +- spec/model_spec.rb | 77 ++++----- spec/options_spec.rb | 18 +- spec/result_spec.rb | 8 +- spec/scope_spec.rb | 12 +- spec/summary_spec.rb | 40 ++--- spec/synchronize_spec.rb | 18 +- spec/thread_safety_spec.rb | 12 +- 43 files changed, 594 insertions(+), 607 deletions(-) diff --git a/README.md b/README.md index e9065a9..3941de0 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Store page view on product #44 from Chrome 11: ```ruby ViewStats.store('views/product/44', {'count/chrome/11' => 1}) ``` - + Fetch product #44 stats: ```ruby @@ -184,7 +184,7 @@ ViewStats.store('views/product/44', {'count/chrome/11' => 1}) ```ruby { 'count' => 1, 'count/chrome' => 1, 'count/chrome/11' => 1 } ``` - + ...to all 12 of these Redis hash keys... ViewStats/views:2011 @@ -237,7 +237,7 @@ Buffering tries to fold together multiple `store` calls into as few as possible ## Note on Patches/Pull Requests ## - + * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a diff --git a/lib/redistat.rb b/lib/redistat.rb index 4ff2389..e41a694 100644 --- a/lib/redistat.rb +++ b/lib/redistat.rb @@ -39,58 +39,58 @@ require 'redistat/core_ext' module Redistat - + KEY_NEXT_ID = ".next_id" KEY_EVENT = ".event:" KEY_LABELS = "Redistat.labels:" # used for reverse label hash lookup KEY_EVENT_IDS = ".event_ids" LABEL_INDEX = ".label_index:" GROUP_SEPARATOR = "/" - + class InvalidOptions < ArgumentError; end class RedisServerIsTooOld < Exception; end - + class << self - + def buffer Buffer.instance end - + def buffer_size buffer.size end - + def buffer_size=(size) buffer.size = size end - + def thread_safe Synchronize.thread_safe end - + def thread_safe=(value) Synchronize.thread_safe = value end - + def connection(ref = nil) Connection.get(ref) end alias :redis :connection - + def connection=(connection) Connection.add(connection) end alias :redis= :connection= - + def connect(options) Connection.create(options) end - + def flush puts "WARNING: Redistat.flush is deprecated. Use Redistat.redis.flushdb instead." connection.flushdb end - + end end diff --git a/lib/redistat/buffer.rb b/lib/redistat/buffer.rb index 66e4f3c..dc13bd6 100644 --- a/lib/redistat/buffer.rb +++ b/lib/redistat/buffer.rb @@ -3,33 +3,33 @@ require 'redistat/core_ext/hash' module Redistat class Buffer include Synchronize - + def self.instance @instance ||= self.new end - + def size synchronize do @size ||= 0 end end - + def size=(value) synchronize do @size = value end end - + def count @count ||= 0 end - + def store(key, stats, depth_limit, opts) return false unless should_buffer? - + to_flush = {} buffkey = buffer_key(key, opts) - + synchronize do if !queue.has_key?(buffkey) queue[buffkey] = { :key => key, @@ -37,19 +37,19 @@ module Redistat :depth_limit => depth_limit, :opts => opts } end - + queue[buffkey][:stats].merge_and_incr!(stats) incr_count - + # return items to be flushed if buffer size limit has been reached to_flush = reset_queue end - + # flush any data that's been cleared from the queue flush_data(to_flush) true end - + def flush(force = false) to_flush = {} synchronize do @@ -57,28 +57,28 @@ module Redistat end flush_data(to_flush) end - + private - + # should always be called from within a synchronize block def incr_count @count ||= 0 @count += 1 end - + def queue @queue ||= {} end - + def should_buffer? size > 1 # buffer size of 1 would be equal to not using buffer end - + # should always be called from within a synchronize block def should_flush? (!queue.blank? && count >= size) end - + # returns items to be flushed if buffer size limit has been reached # should always be called from within a synchronize block def reset_queue(force = false) @@ -88,13 +88,13 @@ module Redistat @count = 0 data end - + def flush_data(buffer_data) buffer_data.each do |k, item| Summary.update(item[:key], item[:stats], item[:depth_limit], item[:opts]) end end - + def buffer_key(key, opts) # depth_limit is not needed as it's evident in key.to_s opts_index = Summary.default_options.keys.sort { |a,b| a.to_s <=> b.to_s }.map do |k| @@ -102,6 +102,6 @@ module Redistat end "#{key.to_s}:#{opts_index.join(':')}" end - + end end diff --git a/lib/redistat/collection.rb b/lib/redistat/collection.rb index d54654d..0ec6816 100644 --- a/lib/redistat/collection.rb +++ b/lib/redistat/collection.rb @@ -1,20 +1,20 @@ module Redistat 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 - + def total @total ||= {} end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/connection.rb b/lib/redistat/connection.rb index 97e84a4..f7dcfd9 100644 --- a/lib/redistat/connection.rb +++ b/lib/redistat/connection.rb @@ -2,22 +2,22 @@ require 'monitor' module Redistat module Connection - + REQUIRED_SERVER_VERSION = "1.3.10" - + # TODO: Create a ConnectionPool instance object using Sychronize mixin to replace Connection class - + class << self - + # TODO: clean/remove all ref-less connections - + def get(ref = nil) ref ||= :default synchronize do connections[references[ref]] || create end end - + def add(conn, ref = nil) ref ||= :default synchronize do @@ -26,7 +26,7 @@ module Redistat connections[conn.client.id] = conn end end - + def create(options = {}) synchronize do options = options.clone @@ -37,39 +37,39 @@ module Redistat conn end end - + def connections @connections ||= {} end - + def references @references ||= {} end - + private - + def monitor @monitor ||= Monitor.new end - + def synchronize(&block) monitor.synchronize(&block) end - + def connection(options) check_redis_version(Redis.new(options)) end - + def connection_id(options = {}) options = options.reverse_merge(default_options) "redis://#{options[:host]}:#{options[:port]}/#{options[:db]}" end - + def check_redis_version(conn) raise RedisServerIsTooOld if conn.info["redis_version"] < REQUIRED_SERVER_VERSION conn end - + def default_options { :host => '127.0.0.1', @@ -78,7 +78,7 @@ module Redistat :timeout => 5 } end - + end end -end \ No newline at end of file +end diff --git a/lib/redistat/core_ext.rb b/lib/redistat/core_ext.rb index f794627..103810c 100644 --- a/lib/redistat/core_ext.rb +++ b/lib/redistat/core_ext.rb @@ -2,4 +2,4 @@ require 'redistat/core_ext/bignum' require 'redistat/core_ext/date' require 'redistat/core_ext/fixnum' require 'redistat/core_ext/hash' -require 'redistat/core_ext/time' \ No newline at end of file +require 'redistat/core_ext/time' diff --git a/lib/redistat/core_ext/bignum.rb b/lib/redistat/core_ext/bignum.rb index 20e08e2..43ebdf2 100755 --- a/lib/redistat/core_ext/bignum.rb +++ b/lib/redistat/core_ext/bignum.rb @@ -1,8 +1,8 @@ class Bignum include Redistat::DateHelper - + def to_time Time.at(self) end - + end diff --git a/lib/redistat/core_ext/date.rb b/lib/redistat/core_ext/date.rb index e17c54f..15abecf 100644 --- a/lib/redistat/core_ext/date.rb +++ b/lib/redistat/core_ext/date.rb @@ -1,8 +1,8 @@ class Date include Redistat::DateHelper - + def to_time Time.parse(self.to_s) end - + end diff --git a/lib/redistat/core_ext/fixnum.rb b/lib/redistat/core_ext/fixnum.rb index 45d4a93..89cba21 100644 --- a/lib/redistat/core_ext/fixnum.rb +++ b/lib/redistat/core_ext/fixnum.rb @@ -1,8 +1,8 @@ class Fixnum include Redistat::DateHelper - + def to_time Time.at(self) end - + end diff --git a/lib/redistat/core_ext/hash.rb b/lib/redistat/core_ext/hash.rb index 398e6e2..e05c584 100644 --- a/lib/redistat/core_ext/hash.rb +++ b/lib/redistat/core_ext/hash.rb @@ -1,9 +1,9 @@ class Hash - + def merge_and_incr(hash) self.clone.merge_and_incr!(hash) end - + def merge_and_incr!(hash) raise ArgumentError unless hash.is_a?(Hash) hash.each do |key, value| @@ -11,7 +11,7 @@ class Hash end self end - + def set_or_incr(key, value) return false unless value.is_a?(Numeric) self[key] = 0 unless self.has_key?(key) @@ -19,5 +19,5 @@ class Hash self[key] += value true end - + end diff --git a/lib/redistat/date.rb b/lib/redistat/date.rb index 2f3e774..ed4eae6 100644 --- a/lib/redistat/date.rb +++ b/lib/redistat/date.rb @@ -1,6 +1,6 @@ module Redistat class Date - + attr_accessor :year attr_accessor :month attr_accessor :day @@ -9,9 +9,9 @@ module Redistat attr_accessor :sec attr_accessor :usec attr_accessor :depth - + DEPTHS = [:year, :month, :day, :hour, :min, :sec, :usec] - + def initialize(input, depth = nil) @depth = depth if input.is_a?(::Time) @@ -26,12 +26,12 @@ module Redistat from_integer(input) end end - + def to_t ::Time.local(@year, @month, @day, @hour, @min, @sec, @usec) end alias :to_time :to_t - + def to_d ::Date.civil(@year, @month, @day) end @@ -41,7 +41,7 @@ module Redistat to_time.to_i end alias :to_integer :to_i - + def to_s(depth = nil) depth ||= @depth ||= :sec output = "" @@ -57,9 +57,9 @@ module Redistat output end alias :to_string :to_s - + private - + def from_time(input) DEPTHS.each do |k| send("#{k}=", input.send(k)) @@ -74,15 +74,15 @@ module Redistat send("#{k}=", 0) end end - + def from_integer(input) from_time(::Time.at(input)) end - + def from_string(input) input += "19700101000000"[input.size..-1] if input =~ /^\d\d\d[\d]+$/i from_time(::Time.parse(input)) end - + end end diff --git a/lib/redistat/event.rb b/lib/redistat/event.rb index dedd696..622f2e2 100644 --- a/lib/redistat/event.rb +++ b/lib/redistat/event.rb @@ -2,13 +2,13 @@ module Redistat class Event include Database include Options - + attr_reader :id attr_reader :key - + attr_accessor :stats attr_accessor :meta - + def default_options { :depth => :hour, :store_event => false, @@ -16,7 +16,7 @@ module Redistat :enable_grouping => true, :label_indexing => true } end - + def initialize(scope, label = nil, date = nil, stats = {}, opts = {}, meta = {}, is_new = true) parse_options(opts) @key = Key.new(scope, label, date, @options) @@ -24,35 +24,35 @@ module Redistat @meta = meta ||= {} @new = is_new end - + def new? @new end - + def date @key.date end - + def date=(input) @key.date = input end - + def scope @key.scope end - + def scope=(input) @key.scope = input end - + def label @key.label end - + def label_hash @key.label_hash end - + def label=(input) @key.label = input end @@ -60,7 +60,7 @@ module Redistat def next_id db.incr("#{self.scope}#{KEY_NEXT_ID}") end - + def save return false if !self.new? Summary.update_all(@key, @stats, depth_limit, @options) @@ -78,21 +78,21 @@ module Redistat @new = false self end - + def depth_limit @options[:depth] ||= @key.depth end - + def self.create(*args) self.new(*args).save end - + def self.find(scope, id) event = db.hgetall "#{scope}#{KEY_EVENT}#{id}" return nil if event.size == 0 self.new( event["scope"], event["label"], event["date"], JSON.parse(event["stats"]), JSON.parse(event["options"]), JSON.parse(event["meta"]), false ) end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/finder.rb b/lib/redistat/finder.rb index 765e194..8c3ffe9 100644 --- a/lib/redistat/finder.rb +++ b/lib/redistat/finder.rb @@ -3,117 +3,117 @@ require 'redistat/finder/date_set' module Redistat class Finder include Database - + class << self def find(*args) new.find(*args) end - + def scope(scope) new.scope(scope) end - + def label(label) new.label(label) end - + def dates(from, till) new.dates(from, till) end alias :date :dates - + def from(date) new.from(date) end - + def till(date) new.till(date) end alias :untill :till - + def depth(unit) new.depth(unit) end - + def interval(unit) new.interval(unit) end end - + attr_reader :options - + def initialize(opts = {}) set_options(opts) end - + def options @options ||= {} end - + def all(reload = false) @result = nil if reload @result ||= find end - + def total all.total 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 parent @parent ||= self.class.new(options.merge(:label => options[:label].parent)) unless options[:label].nil? end - + def children build_key.children.map { |key| self.class.new(options.merge(:label => key.label.to_s)) } end - + def connection_ref(ref = nil) return options[:connection_ref] if ref.nil? reset! if options[:connection_ref] != ref options[:connection_ref] = ref self end - + def scope(input = nil) return options[:scope] if input.nil? reset! if !options[:scope].nil? && options[:scope].to_s != input.to_s options[:scope] = Scope.new(input) self end - + def label(input = nil) return options[:label] if input.nil? reset! if options.has_key?(:label) && options[:label].to_s != input.to_s options[:label] = (!input.nil?) ? Label.new(input) : nil self end - + def dates(start, finish) from(start).till(finish) end alias :date :dates - + def from(date = nil) return options[:from] if date.nil? reset! if options[:from] != date options[:from] = date self end - + def till(date = nil) return options[:till] if date.nil? reset! if options[:till] != date @@ -121,21 +121,21 @@ module Redistat self end alias :until :till - + def depth(unit = nil) return options[:depth] if unit.nil? reset! if options[:depth] != unit options[:depth] = unit self end - + def interval(unit = nil) return options[:interval] if unit.nil? reset! if options[:interval] != unit options[:interval] = unit self end - + def find(opts = {}) set_options(opts) raise InvalidOptions.new if !valid_options? @@ -145,9 +145,9 @@ module Redistat find_by_interval end end - + private - + def set_options(opts = {}) opts = opts.clone opts.each do |key, value| @@ -155,7 +155,7 @@ module Redistat end self.options.merge!(opts) end - + def find_by_interval raise InvalidOptions.new if !valid_options? key = build_key @@ -174,7 +174,7 @@ module Redistat end col end - + def find_by_magic raise InvalidOptions.new if !valid_options? key = build_key @@ -196,20 +196,20 @@ module Redistat @result = nil @parent = nil 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| @@ -218,7 +218,7 @@ module Redistat end sum end - + def summarize_rem_keys(sets, key, sum) sets.each do |date| db.hgetall("#{key.prefix}#{date}").each do |k, v| @@ -227,10 +227,10 @@ module Redistat end sum end - + def db super(options[:connection_ref]) end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/finder/date_set.rb b/lib/redistat/finder/date_set.rb index 43bf961..bf4f4a8 100644 --- a/lib/redistat/finder/date_set.rb +++ b/lib/redistat/finder/date_set.rb @@ -1,7 +1,7 @@ module Redistat class Finder class DateSet < Array - + def initialize(start_date = nil, end_date = nil, depth = nil, interval = false) if !start_date.nil? && !end_date.nil? find_date_sets(start_date, end_date, depth, interval) @@ -71,7 +71,7 @@ module Redistat end { :add => add, :rem => [] } elsif has_nunit - { :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)], + { :add => [end_date.beginning_of(nunit).to_rs.to_s(nunit)], :rem => end_date.map_beginning_of_each(unit, :include_start => !lowest_depth).until(end_date.end_of(nunit)) { |t| t.to_rs.to_s(unit) } } else { :add => [], :rem => [] } @@ -93,7 +93,7 @@ module Redistat { :add => [], :rem => [] } end end - + end end -end \ No newline at end of file +end diff --git a/lib/redistat/key.rb b/lib/redistat/key.rb index f22921b..598c5f3 100644 --- a/lib/redistat/key.rb +++ b/lib/redistat/key.rb @@ -2,56 +2,56 @@ module Redistat class Key include Database include Options - + def default_options { :depth => :hour } end - + def initialize(scope, label_name = nil, time_stamp = nil, opts = {}) parse_options(opts) self.scope = scope self.label = label_name if !label_name.nil? self.date = time_stamp ||= Time.now end - + def prefix key = "#{@scope}" key << "/#{label.name}" if !label.nil? key << ":" key end - + def date=(input) @date = (input.instance_of?(Redistat::Date)) ? input : Date.new(input) # Redistat::Date, not ::Date end attr_reader :date - + def depth options[:depth] end - + # def scope # @scope.to_s # end - + def scope=(input) @scope = (input.instance_of?(Redistat::Scope)) ? input : Scope.new(input) end attr_reader :scope - + def label=(input) @label = (input.instance_of?(Redistat::Label)) ? input : Label.create(input, @options) end attr_reader :label - + def label_hash @label.hash end - + def parent @parent ||= self.class.new(self.scope, @label.parent, self.date, @options) unless @label.parent.nil? end - + def children members = db.smembers("#{scope}#{LABEL_INDEX}#{@label}") || [] # older versions of Redis returns nil members.map { |member| @@ -59,26 +59,26 @@ module Redistat self.class.new(self.scope, child_label.join(GROUP_SEPARATOR), self.date, @options) } end - + def update_index @label.groups.each do |label| parent = (label.parent || "") db.sadd("#{scope}#{LABEL_INDEX}#{parent}", label.me) end end - + def groups @groups ||= @label.groups.map do |label| self.class.new(@scope, label, self.date, @options) end end - + def to_s(depth = nil) depth ||= @options[:depth] key = self.prefix key << @date.to_s(depth) key end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/label.rb b/lib/redistat/label.rb index f3385ba..b4c2101 100644 --- a/lib/redistat/label.rb +++ b/lib/redistat/label.rb @@ -2,55 +2,55 @@ module Redistat class Label include Database include Options - + def default_options { :hashed_label => false } end - + def self.create(name, opts = {}) self.new(name, opts).save end - + def self.join(*args) args = args.map {|i| i.to_s} self.new(args.reject {|i| i.blank? }.join(GROUP_SEPARATOR)) end - + def initialize(str, opts = {}) parse_options(opts) @raw = str.to_s end - + def to_s @raw end - + def name @options[:hashed_label] ? hash : self.to_s end - + def hash @hash ||= Digest::SHA1.hexdigest(self.to_s) end - + def save @saved = db.hset(KEY_LABELS, hash, self.to_s) if @options[:hashed_label] self end - + def saved? return true unless @options[:hashed_label] @saved ||= false end - + def parent @parent ||= groups[1] if groups.size > 1 end - + def me self.to_s.split(GROUP_SEPARATOR).last end - + def groups return @groups unless @groups.nil? @groups = [] @@ -64,6 +64,6 @@ module Redistat end @groups.reverse! end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/mixins/database.rb b/lib/redistat/mixins/database.rb index 9536b1b..b64bfb6 100644 --- a/lib/redistat/mixins/database.rb +++ b/lib/redistat/mixins/database.rb @@ -8,4 +8,4 @@ module Redistat Redistat.connection(ref) end end -end \ No newline at end of file +end diff --git a/lib/redistat/mixins/date_helper.rb b/lib/redistat/mixins/date_helper.rb index 332b59f..42a692d 100644 --- a/lib/redistat/mixins/date_helper.rb +++ b/lib/redistat/mixins/date_helper.rb @@ -5,4 +5,4 @@ module Redistat end alias :to_rs :to_redistat end -end \ No newline at end of file +end diff --git a/lib/redistat/mixins/options.rb b/lib/redistat/mixins/options.rb index 16632d5..f706370 100644 --- a/lib/redistat/mixins/options.rb +++ b/lib/redistat/mixins/options.rb @@ -1,10 +1,10 @@ module Redistat module Options - + def self.included(base) base.extend(ClassMethods) end - + module ClassMethods def option_accessor(*opts) opts.each do |option| @@ -18,24 +18,24 @@ module Redistat end end end - + def parse_options(opts) opts ||= {} @raw_options = opts @options = default_options.merge(opts.reject { |k,v| v.nil? }) end - + def default_options {} end - + def options @options ||= {} end - + def raw_options @raw_options ||= {} end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/mixins/synchronize.rb b/lib/redistat/mixins/synchronize.rb index 2d20b89..170485e 100644 --- a/lib/redistat/mixins/synchronize.rb +++ b/lib/redistat/mixins/synchronize.rb @@ -2,42 +2,42 @@ require 'monitor' module Redistat module Synchronize - + class << self def included(base) base.send(:include, InstanceMethods) end - + def monitor @monitor ||= Monitor.new end - + def thread_safe monitor.synchronize do @thread_safe ||= false end end - + def thread_safe=(value) monitor.synchronize do @thread_safe = value end end end # << self - + module InstanceMethods def thread_safe Synchronize.thread_safe end - + def thread_safe=(value) Synchronize.thread_safe = value end - + def monitor Synchronize.monitor end - + def synchronize(&block) if thread_safe monitor.synchronize(&block) @@ -46,6 +46,6 @@ module Redistat end end end # InstanceMethods - + end -end \ No newline at end of file +end diff --git a/lib/redistat/model.rb b/lib/redistat/model.rb index f1fa4f1..8357cf7 100644 --- a/lib/redistat/model.rb +++ b/lib/redistat/model.rb @@ -2,16 +2,16 @@ module Redistat module Model include Database include Options - + def self.included(base) base.extend(self) end - - + + # # statistics store/fetch methods - # - + # + def store(label, stats = {}, date = nil, opts = {}, meta = {}) Event.new(self.name, label, date, stats, options.merge(opts), meta).save end @@ -28,42 +28,42 @@ module Redistat :from => from, :till => till }.merge(options.merge(opts)) ) end - + def find_event(event_id) Event.find(self.name, event_id) end - - + + # # options methods # - + option_accessor :depth option_accessor :scope option_accessor :store_event option_accessor :hashed_label option_accessor :label_indexing - + alias :class_name :scope - + def connect_to(opts = {}) Connection.create(opts.merge(:ref => name)) options[:connection_ref] = name end - - + + # # resource access methods # - + def connection db(options[:connection_ref]) end alias :redis :connection - + def name options[:scope] || (@name ||= self.to_s) end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/result.rb b/lib/redistat/result.rb index d1a2de3..716a847 100644 --- a/lib/redistat/result.rb +++ b/lib/redistat/result.rb @@ -2,17 +2,17 @@ require 'active_support/core_ext/hash/indifferent_access' module Redistat class Result < HashWithIndifferentAccess - + attr_accessor :from attr_accessor :till - + alias :date :from alias :date= :from= - + def initialize(options = {}) @from = options[:from] ||= nil @till = options[:till] ||= nil end - + end end diff --git a/lib/redistat/scope.rb b/lib/redistat/scope.rb index d64554b..87e9c0a 100644 --- a/lib/redistat/scope.rb +++ b/lib/redistat/scope.rb @@ -1,18 +1,18 @@ module Redistat class Scope include Database - + def initialize(name) @name = name.to_s end - + def to_s @name end - + def next_id db.incr("#{@name}#{KEY_NEXT_ID}") end - + end -end \ No newline at end of file +end diff --git a/lib/redistat/summary.rb b/lib/redistat/summary.rb index cc0bce3..2dd1509 100644 --- a/lib/redistat/summary.rb +++ b/lib/redistat/summary.rb @@ -1,34 +1,34 @@ module Redistat class Summary include Database - + class << self - + def default_options { :enable_grouping => true, :label_indexing => true, :connection_ref => nil } end - + def buffer Redistat.buffer end - + def update_all(key, stats = {}, depth_limit = nil, opts = {}) stats ||= {} return if stats.empty? - + options = default_options.merge((opts || {}).reject { |k,v| v.nil? }) - + depth_limit ||= key.depth - + update_through_buffer(key, stats, depth_limit, options) end - + def update_through_buffer(*args) update(*args) unless buffer.store(*args) end - + def update(key, stats, depth_limit, opts) if opts[:enable_grouping] stats = inject_group_summaries(stats) @@ -40,22 +40,22 @@ module Redistat update_key(key, stats, depth_limit, opts[:connection_ref]) end end - + private - + def update_key(key, stats, depth_limit, connection_ref) Date::DEPTHS.each do |depth| update_fields(key, stats, depth, connection_ref) break if depth == depth_limit end end - + def update_fields(key, stats, depth, connection_ref = nil) stats.each do |field, value| db(connection_ref).hincrby key.to_s(depth), field, value end end - + def inject_group_summaries!(stats) summaries = {} stats.each do |key, value| @@ -72,11 +72,11 @@ module Redistat end stats.merge_and_incr!(summaries) end - + def inject_group_summaries(stats) inject_group_summaries!(stats.clone) end - + end end -end \ No newline at end of file +end diff --git a/spec/buffer_spec.rb b/spec/buffer_spec.rb index dc050c3..5d5d8f5 100644 --- a/spec/buffer_spec.rb +++ b/spec/buffer_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe Redistat::Buffer do - + before(:each) do @class = Redistat::Buffer @buffer = Redistat::Buffer.instance @@ -10,17 +10,17 @@ describe Redistat::Buffer do @depth_limit = :hour @opts = {:enable_grouping => true} end - + # let's cleanup after ourselves for the other specs after(:each) do @class.instance_variable_set("@instance", nil) @buffer.size = 0 end - + it "should provide instance of itself" do @buffer.should be_a(@class) end - + it "should only buffer if buffer size setting is greater than 1" do @buffer.size.should == 0 @buffer.send(:should_buffer?).should be_false @@ -31,7 +31,7 @@ describe Redistat::Buffer do @buffer.size.should == 2 @buffer.send(:should_buffer?).should be_true end - + it "should only flush buffer if buffer size is greater than or equal to buffer size setting" do @buffer.size.should == 0 @buffer.send(:queue).size.should == 0 @@ -50,7 +50,7 @@ describe Redistat::Buffer do @buffer.send(:incr_count) @buffer.send(:should_flush?).should be_true end - + it "should force flush queue irregardless of result of #should_flush? when #reset_queue is called with true" do @buffer.send(:queue)[:hello] = 'world' @buffer.send(:incr_count) @@ -62,7 +62,7 @@ describe Redistat::Buffer do @buffer.send(:reset_queue, true).should == {:hello => 'world'} @buffer.instance_variable_get("@count").should == 0 end - + it "should #flush_data into Summary.update properly" do # the root level key value doesn't actually matter, but it's something like this... data = {'ScopeName/label/goes/here:2011::true:true' => { @@ -75,14 +75,14 @@ describe Redistat::Buffer do Redistat::Summary.should_receive(:update).with(@key, @stats, @depth_limit, @opts) @buffer.send(:flush_data, data) end - + it "should build #buffer_key correctly" do opts = {:enable_grouping => true, :label_indexing => false, :connection_ref => nil} @buffer.send(:buffer_key, @key, opts).should == "#{@key.to_s}::true:false" opts = {:enable_grouping => false, :label_indexing => true, :connection_ref => :omg} @buffer.send(:buffer_key, @key, opts).should == "#{@key.to_s}:omg:false:true" end - + describe "Buffering" do it "should store items on buffer queue" do @buffer.store(@key, @stats, @depth_limit, @opts).should be_false @@ -96,7 +96,7 @@ describe Redistat::Buffer do @buffer.send(:queue)[@buffer.send(:queue).keys.first][:stats][:count].should == 2 @buffer.send(:queue)[@buffer.send(:queue).keys.first][:stats][:views].should == 6 end - + it "should flush buffer queue when size is reached" do key = mock('Key', :to_s => "Scope/labelx:2011") @buffer.size = 10 @@ -115,18 +115,18 @@ describe Redistat::Buffer do 4.times { @buffer.store(key, @stats, @depth_limit, @opts).should be_true } end end - + describe "Thread-Safety" do it "should read/write to buffer queue in a thread-safe manner" do - + # Setting thread_safe to false only makes the spec fail with # JRuby. 1.8.x and 1.9.x both pass fine for some reason # regardless of what the thread_safe option is set to. Redistat.thread_safe = true - + key = mock('Key', :to_s => "Scope/labelx:2011") @buffer.size = 100 - + Redistat::Summary.should_receive(:update).exactly(2).times.and_return do |k, stats, depth_limit, opts| depth_limit.should == @depth_limit opts.should == @opts @@ -138,7 +138,7 @@ describe Redistat::Buffer do stats[:views].should == 120 end end - + threads = [] 10.times do threads << Thread.new { @@ -146,12 +146,12 @@ describe Redistat::Buffer do 4.times { @buffer.store(key, @stats, @depth_limit, @opts).should be_true } } end - + threads.each { |t| t.join } end - + it "should have specs that fail on 1.8.x/1.9.x when thread_safe is disabled" - + end - + end diff --git a/spec/collection_spec.rb b/spec/collection_spec.rb index 74f040f..f85aa87 100644 --- a/spec/collection_spec.rb +++ b/spec/collection_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe Redistat::Collection do - + it "should initialize properly" do options = {:from => "from", :till => "till", :depth => "depth"} result = Redistat::Collection.new(options) @@ -9,12 +9,12 @@ describe Redistat::Collection do result.till.should == options[:till] result.depth.should == options[:depth] end - + it "should have a total property" do col = Redistat::Collection.new() col.total.should == {} col.total = {:foo => "bar"} col.total.should == {:foo => "bar"} end - -end \ No newline at end of file + +end diff --git a/spec/connection_spec.rb b/spec/connection_spec.rb index 907a7d1..7960430 100644 --- a/spec/connection_spec.rb +++ b/spec/connection_spec.rb @@ -2,11 +2,11 @@ require "spec_helper" include Redistat describe Redistat::Connection do - + before(:each) do @redis = Redistat.redis end - + it "should have a valid Redis client instance" do Redistat.redis.should_not be_nil end @@ -16,13 +16,13 @@ describe Redistat::Connection do @redis.client.port.should == 8379 @redis.client.db.should == 15 end - + it "should be able to set and get data" do @redis.set("hello", "world") @redis.get("hello").should == "world" @redis.del("hello").should be_true end - + it "should be able to store hashes to Redis" do @redis.hset("hash", "field", "1") @redis.hget("hash", "field").should == "1" @@ -32,36 +32,36 @@ describe Redistat::Connection do @redis.hget("hash", "field").should == "1" @redis.del("hash") end - + it "should be accessible from Redistat module" do Redistat.redis.should == Connection.get Redistat.redis.should == Redistat.connection end - + it "should handle multiple connections with refs" do Redistat.redis.client.db.should == 15 Redistat.connect(:port => 8379, :db => 14, :ref => "Custom") Redistat.redis.client.db.should == 15 Redistat.redis("Custom").client.db.should == 14 end - + it "should be able to overwrite default and custom refs" do Redistat.redis.client.db.should == 15 Redistat.connect(:port => 8379, :db => 14) Redistat.redis.client.db.should == 14 - + Redistat.redis("Custom").client.db.should == 14 Redistat.connect(:port => 8379, :db => 15, :ref => "Custom") Redistat.redis("Custom").client.db.should == 15 - + # Reset the default connection to the testing server or all hell # might brake loose from the rest of the specs Redistat.connect(:port => 8379, :db => 15) end - + # TODO: Test thread-safety it "should be thread-safe" do pending("need to figure out a way to test thread-safety") end - -end \ No newline at end of file + +end diff --git a/spec/core_ext/hash_spec.rb b/spec/core_ext/hash_spec.rb index c838dc2..73e3987 100644 --- a/spec/core_ext/hash_spec.rb +++ b/spec/core_ext/hash_spec.rb @@ -1,7 +1,7 @@ require "spec_helper" describe Hash do - + it "should #set_or_incr values" do hash = {:count => 1} hash.set_or_incr(:sum, 3).should be_true @@ -14,17 +14,17 @@ describe Hash do hash[:view] = 'test' hash.set_or_incr(:view, 3).should be_false end - + it "should #merge_and_incr hashes" do hash = { :count => 1, :city => 'hell', :sum => 3, :name => 'john' } - + new_hash = { :count => 3, :city => 'slum', :views => 2 } hash.clone.merge_and_incr(new_hash).should == { :count => 4, :city => 'slum', :views => 2, :sum => 3, :name => 'john' } - + new_hash = { :count => 'six', :city => 'slum', :views => 2, :time => 'late' } hash.clone.merge_and_incr(new_hash).should == { :count => 'six', :city => 'slum', :views => 2, :sum => 3, :name => 'john', :time => 'late' } end - + end diff --git a/spec/database_spec.rb b/spec/database_spec.rb index d7e8051..dde4b37 100644 --- a/spec/database_spec.rb +++ b/spec/database_spec.rb @@ -2,9 +2,9 @@ require "spec_helper" describe Redistat::Database do include Redistat::Database - + it "should make #db method available when included" do db.should == Redistat.redis end - -end \ No newline at end of file + +end diff --git a/spec/date_spec.rb b/spec/date_spec.rb index 143481f..1f0021c 100644 --- a/spec/date_spec.rb +++ b/spec/date_spec.rb @@ -1,14 +1,14 @@ require "spec_helper" describe Redistat::Date do - + it "should initialize from Time object" do now = Time.now [Redistat::Date.new(now), now.to_rs].each do |rdate| Redistat::Date::DEPTHS.each { |k| rdate.send(k).should == now.send(k) } end end - + it "should initialize from Date object" do today = Date.today [Redistat::Date.new(today), today.to_rs].each do |rdate| @@ -16,7 +16,7 @@ describe Redistat::Date do [:hour, :min, :sec, :usec].each { |k| rdate.send(k).should == 0 } end end - + it "should initialize from Fixnum object (UNIX Timestamp)" do now = Time.now.to_i time = Time.at(now) @@ -24,13 +24,13 @@ describe Redistat::Date do [:year, :month, :day, :hour, :min, :sec].each { |k| rdate.send(k).should == time.send(k) } end end - + it "should initialize from String object" do now = Time.now rdate = Redistat::Date.new(now.to_s) [:year, :month, :day, :hour, :min, :sec].each { |k| rdate.send(k).should == now.send(k) } end - + it "should initialize from Redistat date String" do now = Time.now rdate = Redistat::Date.new(now.to_s) @@ -38,25 +38,25 @@ describe Redistat::Date do rdate.to_s(k).should == Redistat::Date.new(rdate.to_s(k)).to_s(k) } end - + it "should convert to Time object" do now = Time.now rdate = Redistat::Date.new(now) rdate.to_time.to_s.should == now.to_s end - + it "should convert to Date object" do today = Date.today rdate = Redistat::Date.new(today) rdate.to_date.to_s.should == today.to_s end - + it "should convert to Fixnum object (UNIX Timestamp)" do now = Time.now rdate = Redistat::Date.new(now) rdate.to_i.should == now.to_i end - + it "should convert to string with correct depths" do today = Date.today now = Time.now @@ -71,25 +71,25 @@ describe Redistat::Date do end end end - + it "should add helper methods to Date, Time and Fixnum classes" do Date.today.to_time.should == Time.parse(Date.today.to_s) Time.now.to_i.to_time.should == Time.at(Time.now.to_i) Date.today.to_rs.to_date.should == Date.today end - + it "should have a depth property" do now = Time.now - + date = Redistat::Date.new(now) date.depth.should be_nil date.to_s.should == now.to_rs(:sec).to_s date.to_s.should == now.to_rs.to_s(:sec) - + date = Redistat::Date.new(now, :hour) date.depth.should == :hour date.to_s.should == now.to_rs(:hour).to_s date.to_s.should == now.to_rs.to_s(:hour) end - -end \ No newline at end of file + +end diff --git a/spec/event_spec.rb b/spec/event_spec.rb index 39add3b..232ba96 100644 --- a/spec/event_spec.rb +++ b/spec/event_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" describe Redistat::Event do include Redistat::Database - + before(:each) do db.flushdb @scope = "PageViews" @@ -14,7 +14,7 @@ describe Redistat::Event do @date = Time.now @event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta) end - + it "should initialize properly" do @event.id.should be_nil @event.scope.to_s.should == @scope @@ -41,7 +41,7 @@ describe Redistat::Event do @event.label.to_s.should == @label @event.label_hash.should == @label_hash end - + it "should increment next_id" do event = Redistat::Event.new("VisitorCount", @label, @date, @stats, @options, @meta) @event.next_id.should == 1 @@ -49,7 +49,7 @@ describe Redistat::Event do @event.next_id.should == 2 event.next_id.should == 2 end - + it "should store event properly" do @event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta) @event.new?.should be_true @@ -59,7 +59,7 @@ describe Redistat::Event do keys.should include("#{@event.scope}#{Redistat::KEY_EVENT}#{@event.id}") keys.should include("#{@event.scope}#{Redistat::KEY_EVENT_IDS}") end - + it "should find event by id" do @event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta).save fetched = Redistat::Event.find(@scope, @event.id) @@ -69,7 +69,7 @@ describe Redistat::Event do @event.stats.should == fetched.stats @event.meta.should == fetched.meta end - + it "should store summarized statistics" do 2.times do |i| @event = Redistat::Event.new(@scope, @label, @date, @stats, @options, @meta).save @@ -81,5 +81,5 @@ describe Redistat::Event do end end end - -end \ No newline at end of file + +end diff --git a/spec/finder/date_set_spec.rb b/spec/finder/date_set_spec.rb index 2439e6b..a260408 100644 --- a/spec/finder/date_set_spec.rb +++ b/spec/finder/date_set_spec.rb @@ -1,11 +1,11 @@ require "spec_helper" describe Redistat::Finder::DateSet do - + before(:all) do @finder = Redistat::Finder::DateSet.new end - + it "should initialize properly" do t_start = Time.utc(2010, 8, 28, 22, 54, 57) t_end = Time.utc(2013, 12, 4, 22, 52, 3) @@ -20,508 +20,508 @@ describe Redistat::Finder::DateSet do { :add => ["2011", "2012"], :rem => [] } ] end - + it "should find date sets by interval" do t_start = Time.utc(2010, 8, 28, 18, 54, 57) - + t_end = t_start + 4.hours result = Redistat::Finder::DateSet.new.find_date_sets(t_start, t_end, :hour, true) result[0][:add].should == ["2010082818", "2010082819", "2010082820", "2010082821", "2010082822"] result[0][:rem].should == [] result.should == Redistat::Finder::DateSet.new(t_start, t_end, nil, :hour) - + t_end = t_start + 4.days result = Redistat::Finder::DateSet.new.find_date_sets(t_start, t_end, :day, true) result[0][:add].should == ["20100828", "20100829", "20100830", "20100831", "20100901"] result[0][:rem].should == [] result.should == Redistat::Finder::DateSet.new(t_start, t_end, nil, :day) end - + it "should find start keys properly" do - + # # Simple fetching # Dates: 22:54, 26th August, 2010 --> 22:52, 14th December, 2010 # - + t_start = Time.utc(2010, 8, 26, 22, 54, 57) t_end = Time.utc(2013, 12, 14, 22, 52, 3) - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end) result[:add].should == ["20100826225458", "20100826225459"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262255", "201008262256", "201008262257", "201008262258", "201008262259"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010082623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["20100827", "20100828", "20100829", "20100830", "20100831"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end) result[:add].should == ["201009", "201010", "201011", "201012"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :year, t_start, t_end) result[:add].should == ["2011", "2012"] result[:rem].should == [] - + # # Reverse / Inteligent fetching # Dates: 5:06, 4th April, 2010 --> 22:52, 14th February, 2011 # - + t_start = Time.utc(2010, 4, 4, 5, 6, 4) t_end = Time.utc(2011, 2, 14, 22, 52, 3) - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end) result[:add].should == ["201004040506"] result[:rem].should == ["20100404050600", "20100404050601", "20100404050602", "20100404050603", "20100404050604"] - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["2010040405"] result[:rem].should == ["201004040500", "201004040501", "201004040502", "201004040503", "201004040504", "201004040505", "201004040506"] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["20100404"] result[:rem].should == ["2010040400", "2010040401", "2010040402", "2010040403", "2010040404", "2010040405"] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["201004"] result[:rem].should == ["20100401", "20100402", "20100403", "20100404"] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end) result[:add].should == ["2010"] result[:rem].should == ["201001", "201002", "201003", "201004"] - + result = @finder.send(:find_start_keys_for, :year, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + end - + it "should find end keys properly" do - + # # Simple fetching # Dates: 22:04, 26th December, 2007 --> 5:06, 7th May, 2010 # - + t_start = Time.utc(2007, 12, 26, 22, 4, 4) t_end = Time.utc(2010, 5, 7, 5, 6, 3) - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end) result[:add].should == ["20100507050600", "20100507050601", "20100507050602"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["201005070500", "201005070501", "201005070502", "201005070503", "201005070504", "201005070505"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["2010050700", "2010050701", "2010050702", "2010050703", "2010050704"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == ["20100501", "20100502", "20100503", "20100504", "20100505", "20100506"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end) result[:add].should == ["201001", "201002", "201003", "201004"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :year, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + # # Reverse / Inteligent fetching # Dates: 22:04, 26th December, 2009 --> 22:56, 27th October, 2010 # - + t_start = Time.utc(2009, 12, 26, 22, 4, 4) t_end = Time.utc(2010, 10, 27, 22, 56, 57) - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end) result[:add].should == ["201010272256"] result[:rem].should == ["20101027225657", "20101027225658", "20101027225659"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010102722"] result[:rem].should == ["201010272256", "201010272257", "201010272258", "201010272259"] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["20101027"] result[:rem].should == ["2010102722", "2010102723"] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == ["201010"] result[:rem].should == ["20101027", "20101028", "20101029", "20101030", "20101031"] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end) result[:add].should == ["2010"] result[:rem].should == ["201010", "201011", "201012"] - + result = @finder.send(:find_end_keys_for, :year, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + end - + it "should fetch start/end keys with limits" do - + # # Simple fetching with Limits # - + # seconds t_start = Time.utc(2010, 8, 26, 20, 54, 45) t_end = t_start + 4.seconds - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end) result[:add].should == ["20100826205446", "20100826205447", "20100826205448"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + t_start = Time.utc(2010, 8, 26, 20, 54, 4) t_end = t_start + 4.seconds - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end) result[:add].should == ["20100826205405", "20100826205406", "20100826205407"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + # minutes t_start = Time.utc(2010, 8, 26, 20, 54) t_end = t_start + 4.minutes - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262055", "201008262056", "201008262057"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + t_start = Time.utc(2010, 8, 26, 20, 4) t_end = t_start + 4.minutes - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262005", "201008262006", "201008262007"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + # hours t_start = Time.utc(2010, 8, 26, 20, 54) t_end = t_start + 2.hours - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010082621"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010082622"] result[:rem].should == ["201008262254", "201008262255", "201008262256", "201008262257", "201008262258", "201008262259"] - + t_start = Time.utc(2010, 8, 26, 4, 54) t_end = t_start + 5.hours - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008260455", "201008260456", "201008260457", "201008260458", "201008260459"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010082605", "2010082606", "2010082607", "2010082608"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010082609"] result[:rem].should == ["201008260954", "201008260955", "201008260956", "201008260957", "201008260958", "201008260959"] - + # days t_start = Time.utc(2010, 8, 26, 20, 54) t_end = t_start + 2.day - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010082621", "2010082622", "2010082623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["20100827"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["20100828"] result[:rem].should == ["2010082820", "2010082821", "2010082822", "2010082823"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010082820"] result[:rem].should == ["201008282054", "201008282055", "201008282056", "201008282057", "201008282058", "201008282059"] - + t_start = Time.utc(2010, 8, 6, 20, 54) t_end = t_start + 2.day - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008062055", "201008062056", "201008062057", "201008062058", "201008062059"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010080621", "2010080622", "2010080623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["20100807"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["20100808"] result[:rem].should == ["2010080820", "2010080821", "2010080822", "2010080823"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010080820"] result[:rem].should == ["201008082054", "201008082055", "201008082056", "201008082057", "201008082058", "201008082059"] - + # months t_start = Time.utc(2010, 8, 26, 20, 54) t_end = t_start + 3.months - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201008262055", "201008262056", "201008262057", "201008262058", "201008262059"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010082621", "2010082622", "2010082623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["20100827", "20100828", "20100829", "20100830", "20100831"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end) result[:add].should == ["201009", "201010"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == ["201011"] result[:rem].should == ["20101126", "20101127", "20101128", "20101129", "20101130"] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["20101126"] result[:rem].should == ["2010112620", "2010112621", "2010112622", "2010112623"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010112620"] result[:rem].should == ["201011262054", "201011262055", "201011262056", "201011262057", "201011262058", "201011262059"] - + t_start = Time.utc(2010, 4, 26, 20, 54) t_end = t_start + 3.months - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end) result[:add].should == ["201004262055", "201004262056", "201004262057", "201004262058", "201004262059"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end) result[:add].should == ["2010042621", "2010042622", "2010042623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end) result[:add].should == ["20100427", "20100428", "20100429", "20100430"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end) result[:add].should == ["201005", "201006"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end) result[:add].should == [] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end) result[:add].should == ["201007"] result[:rem].should == ["20100726", "20100727", "20100728", "20100729", "20100730", "20100731"] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end) result[:add].should == ["20100726"] result[:rem].should == ["2010072620", "2010072621", "2010072622", "2010072623"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end) result[:add].should == ["2010072620"] result[:rem].should == ["201007262054", "201007262055", "201007262056", "201007262057", "201007262058", "201007262059"] - + end - + it "should find inclusive keys on lowest depth" do - + # # Simple start fetching # Dates: 22:54, 26th August, 2010 --> 22:52, 14th December, 2010 # - + t_start = Time.utc(2010, 8, 26, 22, 54, 57) t_end = Time.utc(2013, 12, 14, 22, 52, 3) - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end, true) result[:add].should == ["20100826225457", "20100826225458", "20100826225459"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end, true) result[:add].should == ["201008262254", "201008262255", "201008262256", "201008262257", "201008262258", "201008262259"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end, true) result[:add].should == ["2010082622", "2010082623"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end, true) result[:add].should == ["20100826", "20100827", "20100828", "20100829", "20100830", "20100831"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end, true) result[:add].should == ["201008", "201009", "201010", "201011", "201012"] result[:rem].should == [] - + result = @finder.send(:find_start_keys_for, :year, t_start, t_end, true) result[:add].should == ["2011", "2012", "2013"] result[:rem].should == [] - + # # Reverse / Inteligent start fetching # Dates: 5:06, 4th April, 2010 --> 22:52, 14th February, 2011 # - + t_start = Time.utc(2010, 4, 4, 5, 6, 4) t_end = Time.utc(2013, 2, 14, 22, 52, 3) - + result = @finder.send(:find_start_keys_for, :sec, t_start, t_end, true) result[:add].should == ["201004040506"] result[:rem].should == ["20100404050600", "20100404050601", "20100404050602", "20100404050603"] - + result = @finder.send(:find_start_keys_for, :min, t_start, t_end, true) result[:add].should == ["2010040405"] result[:rem].should == ["201004040500", "201004040501", "201004040502", "201004040503", "201004040504", "201004040505"] - + result = @finder.send(:find_start_keys_for, :hour, t_start, t_end, true) result[:add].should == ["20100404"] result[:rem].should == ["2010040400", "2010040401", "2010040402", "2010040403", "2010040404"] - + result = @finder.send(:find_start_keys_for, :day, t_start, t_end, true) result[:add].should == ["201004"] result[:rem].should == ["20100401", "20100402", "20100403"] - + result = @finder.send(:find_start_keys_for, :month, t_start, t_end, true) result[:add].should == ["2010"] result[:rem].should == ["201001", "201002", "201003"] - + result = @finder.send(:find_start_keys_for, :year, t_start, t_end, true) result[:add].should == ["2011", "2012", "2013"] result[:rem].should == [] - + # # Simple fetching # Dates: 22:04, 26th December, 2007 --> 5:06, 7th May, 2010 # - + t_start = Time.utc(2007, 12, 26, 22, 4, 4) t_end = Time.utc(2010, 5, 7, 5, 6, 3) - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end, true) result[:add].should == ["20100507050600", "20100507050601", "20100507050602", "20100507050603"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end, true) result[:add].should == ["201005070500", "201005070501", "201005070502", "201005070503", "201005070504", "201005070505", "201005070506"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end, true) result[:add].should == ["2010050700", "2010050701", "2010050702", "2010050703", "2010050704", "2010050705"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end, true) result[:add].should == ["20100501", "20100502", "20100503", "20100504", "20100505", "20100506", "20100507"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end, true) result[:add].should == ["201001", "201002", "201003", "201004", "201005"] result[:rem].should == [] - + result = @finder.send(:find_end_keys_for, :year, t_start, t_end, true) result[:add].should == ["2010"] result[:rem].should == [] - + # # Reverse / Inteligent fetching # Dates: 22:04, 26th December, 2009 --> 22:56, 27th October, 2010 # - + t_start = Time.utc(2009, 12, 26, 22, 4, 4) t_end = Time.utc(2010, 10, 27, 22, 56, 57) - + result = @finder.send(:find_end_keys_for, :sec, t_start, t_end, true) result[:add].should == ["201010272256"] result[:rem].should == ["20101027225658", "20101027225659"] - + result = @finder.send(:find_end_keys_for, :min, t_start, t_end, true) result[:add].should == ["2010102722"] result[:rem].should == ["201010272257", "201010272258", "201010272259"] - + result = @finder.send(:find_end_keys_for, :hour, t_start, t_end, true) result[:add].should == ["20101027"] result[:rem].should == ["2010102723"] - + result = @finder.send(:find_end_keys_for, :day, t_start, t_end, true) result[:add].should == ["201010"] result[:rem].should == ["20101028", "20101029", "20101030", "20101031"] - + result = @finder.send(:find_end_keys_for, :month, t_start, t_end, true) result[:add].should == ["2010"] result[:rem].should == ["201011", "201012"] - + result = @finder.send(:find_end_keys_for, :year, t_start, t_end, true) result[:add].should == ["2010"] result[:rem].should == [] - + end - -end \ No newline at end of file + +end diff --git a/spec/finder_spec.rb b/spec/finder_spec.rb index d8748bf..d091808 100644 --- a/spec/finder_spec.rb +++ b/spec/finder_spec.rb @@ -2,21 +2,21 @@ require "spec_helper" describe Redistat::Finder do include Redistat::Database - + before(:each) do db.flushdb @scope = "PageViews" @label = "about_us" @date = Time.now @key = Redistat::Key.new(@scope, @label, @date, {:depth => :day}) - @stats = {"views" => 3, "visitors" => 2} + @stats = {"views" => 3, "visitors" => 2} @two_hours_ago = 2.hours.ago @one_hour_ago = 1.hour.ago end - + it "should initialize properly" do options = {:scope => "PageViews", :label => "Label", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour} - + finder = Redistat::Finder.new finder.send(:set_options, options) finder.options[:scope].should be_a(Redistat::Scope) @@ -24,31 +24,31 @@ describe Redistat::Finder do finder.options[:label].should be_a(Redistat::Label) finder.options[:label].to_s.should == options[:label] finder.options.should == options.merge(:scope => finder.options[:scope], :label => finder.options[:label]) - + finder = Redistat::Finder.scope("hello") finder.options[:scope].to_s.should == "hello" finder.scope.to_s.should == "hello" - + finder = Redistat::Finder.label("hello") finder.options[:label].to_s.should == "hello" finder.label.to_s.should == "hello" - + finder = Redistat::Finder.dates(@two_hours_ago, @one_hour_ago) finder.options[:from].should == @two_hours_ago finder.options[:till].should == @one_hour_ago - + finder = Redistat::Finder.from(@two_hours_ago) finder.options[:from].should == @two_hours_ago finder.from.should == @two_hours_ago - + finder = Redistat::Finder.till(@one_hour_ago) finder.options[:till].should == @one_hour_ago finder.till.should == @one_hour_ago - + finder = Redistat::Finder.depth(:hour) finder.options[:depth].should == :hour finder.depth.should == :hour - + finder = Redistat::Finder.interval(true) finder.options[:interval].should be_true finder.interval.should be_true @@ -56,24 +56,24 @@ describe Redistat::Finder do finder.options[:interval].should be_false finder.interval.should be_false end - + it "should fetch stats properly" do first_stat, last_stat = create_example_stats - + 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.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 @@ -89,22 +89,22 @@ describe Redistat::Finder do 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.total.should == {} end - + it "should throw error on invalid options" do lambda { Redistat::Finder.find(:from => 3.hours.ago) }.should raise_error(Redistat::InvalidOptions) end - + describe "Grouping" do before(:each) do @options = {:scope => "PageViews", :label => "message/public", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour} @finder = Redistat::Finder.new(@options) end - + it "should return parent finder" do @finder.instance_variable_get("@parent").should be_nil @finder.parent.should be_a(Redistat::Finder) @@ -116,7 +116,7 @@ describe Redistat::Finder do @finder.parent.options[:label].should be_nil @finder.parent.parent.should be_nil end - + it "should find children" do Redistat::Key.new("PageViews", "message/public/die").update_index Redistat::Key.new("PageViews", "message/public/live").update_index @@ -130,25 +130,25 @@ describe Redistat::Finder do subs.should include('fester') end end - + describe "Lazy-Loading" do - + before(:each) do @first_stat, @last_stat = create_example_stats @finder = Redistat::Finder.new @finder.from(@first_stat).till(@last_stat).scope(@scope).label(@label).depth(:hour) - + @match = [{}, {"visitors"=>"4", "views"=>"6"}, {"visitors"=>"2", "views"=>"3"}, {"visitors"=>"2", "views"=>"3"}, {}] end - + it "should lazy-load" do @finder.instance_variable_get("@result").should be_nil stats = @finder.all @finder.instance_variable_get("@result").should_not be_nil - + stats.should == @finder.find # find method directly fetches results stats.total.should == @finder.total stats.total.should == { "views" => 12, "visitors" => 8 } @@ -163,35 +163,35 @@ describe Redistat::Finder do stats = @finder.all stats.total.should == { "views" => 6, "visitors" => 4 } end - + it "should handle #map" do @finder.interval(:hour) @finder.map { |r| r }.should == @match end - + it "should handle #each" do @finder.interval(:hour) - + res = [] @finder.each { |r| res << r } res.should == @match end - + it "should handle #each_with_index" do @finder.interval(:hour) - + res = {} match = {} @finder.each_with_index { |r, i| res[i] = r } @match.each_with_index { |r, i| match[i] = r } res.should == match end - + end # "Lazy-Loading" - - + + # helper methods - + def create_example_stats key = Redistat::Key.new(@scope, @label, (first = Time.parse("2010-05-14 13:43"))) Redistat::Summary.send(:update_fields, key, @stats, :hour) @@ -203,5 +203,5 @@ describe Redistat::Finder do Redistat::Summary.send(:update_fields, key, @stats, :hour) [first - 1.hour, last + 1.hour] end - + end diff --git a/spec/key_spec.rb b/spec/key_spec.rb index 95b8609..da9af9f 100644 --- a/spec/key_spec.rb +++ b/spec/key_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" describe Redistat::Key do include Redistat::Database - + before(:each) do db.flushdb @scope = "PageViews" @@ -11,7 +11,7 @@ describe Redistat::Key do @date = Time.now @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour}) end - + it "should initialize properly" do @key.scope.to_s.should == @scope @key.label.to_s.should == @label @@ -20,7 +20,7 @@ describe Redistat::Key do @key.date.should be_instance_of(Redistat::Date) @key.date.to_time.to_s.should == @date.to_s end - + it "should convert to string properly" do @key.to_s.should == "#{@scope}/#{@label}:#{@key.date.to_s(:hour)}" props = [:year, :month, :day, :hour, :min, :sec] @@ -31,19 +31,19 @@ describe Redistat::Key do key = Redistat::Key.new(@scope, nil, @date, {:depth => :hour}) key.to_s.should == "#{@scope}:#{key.date.to_s(:hour)}" end - + it "should abide to hashed_label option" do @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :hashed_label => true}) @key.to_s.should == "#{@scope}/#{@label_hash}:#{@key.date.to_s(:hour)}" @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour, :hashed_label => false}) @key.to_s.should == "#{@scope}/#{@label}:#{@key.date.to_s(:hour)}" end - + it "should have default depth option" do @key = Redistat::Key.new(@scope, @label, @date) @key.depth.should == :hour end - + it "should allow changing attributes" do # scope @key.scope.to_s.should == @scope @@ -64,13 +64,13 @@ describe Redistat::Key do @key.label.to_s.should == @label @key.label_hash == @label_hash end - + describe "Grouping" do before(:each) do @label = "message/public/offensive" @key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour}) end - + it "should create a group of keys from label group" do label = 'message/public/offensive' result = [ "message/public/offensive", @@ -81,49 +81,49 @@ describe Redistat::Key do key.groups.map { |k| k.label.to_s }.should == result end - + it "should know it's parent" do @key.parent.should be_a(Redistat::Key) @key.parent.label.to_s.should == 'message/public' Redistat::Key.new(@scope, 'hello', @date).parent.should be_nil end - + it "should update label index and return children" do db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}").should == [] @key.children.should have(0).items - + @key.update_index # indexing 'message/publish/offensive' Redistat::Key.new("PageViews", "message/public/die").update_index # indexing 'message/publish/die' Redistat::Key.new("PageViews", "message/public/live").update_index # indexing 'message/publish/live' - + members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}") # checking 'message/public' members.should have(3).item members.should include('offensive') members.should include('live') members.should include('die') - + key = @key.parent key.children.first.should be_a(Redistat::Key) key.children.should have(3).item key.children.map { |k| k.label.me }.should == members - + members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{key.label.parent}") # checking 'message' members.should have(1).item members.should include('public') - + key = key.parent key.children.should have(1).item key.children.map { |k| k.label.me }.should == members - + members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}") # checking '' members.should have(1).item members.should include('message') - + key.parent.should be_nil key = Redistat::Key.new("PageViews") key.children.should have(1).item key.children.map { |k| k.label.me }.should include('message') end end - -end \ No newline at end of file + +end diff --git a/spec/label_spec.rb b/spec/label_spec.rb index 7ef6f2d..3d46a7b 100644 --- a/spec/label_spec.rb +++ b/spec/label_spec.rb @@ -2,29 +2,29 @@ require "spec_helper" describe Redistat::Label do include Redistat::Database - + before(:each) do db.flushdb @name = "about_us" @label = Redistat::Label.new(@name) end - + it "should initialize properly and SHA1 hash the label name" do @label.name.should == @name @label.hash.should == Digest::SHA1.hexdigest(@name) end - + it "should store a label hash lookup key" do label = Redistat::Label.new(@name, {:hashed_label => true}).save label.saved?.should be_true db.hget(Redistat::KEY_LABELS, label.hash).should == @name - + name = "contact_us" label = Redistat::Label.create(name, {:hashed_label => true}) label.saved?.should be_true db.hget(Redistat::KEY_LABELS, label.hash).should == name end - + it "should join labels" do include Redistat label = Label.join('email', 'message', 'public') @@ -37,18 +37,18 @@ describe Redistat::Label do label.should be_a(Label) label.to_s.should == 'email/message/public' end - + describe "Grouping" do before(:each) do @name = "message/public/offensive" @label = Redistat::Label.new(@name) end - + it "should know it's parent label group" do @label.parent.to_s.should == 'message/public' Redistat::Label.new('hello').parent.should be_nil end - + it "should separate label names into groups" do @label.name.should == @name @label.groups.map { |l| l.to_s }.should == [ "message/public/offensive", @@ -67,5 +67,5 @@ describe Redistat::Label do @label.groups.map { |l| l.to_s }.should == [ "message" ] end end - -end \ No newline at end of file + +end diff --git a/spec/model_helper.rb b/spec/model_helper.rb index 4328052..f2dbf93 100644 --- a/spec/model_helper.rb +++ b/spec/model_helper.rb @@ -2,29 +2,29 @@ require "redistat" class ModelHelper1 include Redistat::Model - - + + end class ModelHelper2 include Redistat::Model - + depth :day store_event true hashed_label true - + end class ModelHelper3 include Redistat::Model - + connect_to :port => 8379, :db => 14 - + end class ModelHelper4 include Redistat::Model - + scope "FancyHelper" - -end \ No newline at end of file + +end diff --git a/spec/model_spec.rb b/spec/model_spec.rb index 7d8404f..cc5fbfb 100644 --- a/spec/model_spec.rb +++ b/spec/model_spec.rb @@ -3,7 +3,7 @@ require "model_helper" describe Redistat::Model do include Redistat::Database - + before(:each) do @time = Time.utc(2010, 8, 28, 12, 0, 0) ModelHelper1.redis.flushdb @@ -11,12 +11,12 @@ describe Redistat::Model do ModelHelper3.redis.flushdb ModelHelper4.redis.flushdb end - + it "should should name itself correctly" do ModelHelper1.send(:name).should == "ModelHelper1" ModelHelper2.send(:name).should == "ModelHelper2" end - + it "should return a Finder" do two_hours_ago = 2.hours.ago one_hour_ago = 1.hour.ago @@ -27,18 +27,18 @@ describe Redistat::Model do finder.options[:from].should == two_hours_ago finder.options[:till].should == one_hour_ago end - + it "should #find_event" do Redistat::Event.should_receive(:find).with('ModelHelper1', 1) ModelHelper1.find_event(1) end - + it "should listen to model-defined options" do ModelHelper2.depth.should == :day ModelHelper2.store_event.should == true ModelHelper2.hashed_label.should == true ModelHelper2.scope.should be_nil - + ModelHelper1.depth.should == nil ModelHelper1.store_event.should == nil ModelHelper1.hashed_label.should == nil @@ -54,134 +54,134 @@ describe Redistat::Model do ModelHelper1.depth.should == nil ModelHelper1.store_event.should == nil ModelHelper1.hashed_label.should == nil - + ModelHelper4.scope.should == "FancyHelper" ModelHelper4.send(:name).should == "FancyHelper" end - + it "should store and fetch stats" do ModelHelper1.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4)) ModelHelper1.store("sheep.black", {:count => 2, :weight => 156}, @time) - + stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1)) stats.total["count"].should == 2 stats.total["weight"].should == 156 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)) stats.total[:count].should == 8 stats.total[:weight].should == 617 stats.first.should == stats.total - + ModelHelper1.store("sheep.white", {:count => 5, :weight => 393}, @time.hours_ago(4)) ModelHelper1.store("sheep.white", {:count => 4, :weight => 316}, @time) - + stats = ModelHelper1.fetch("sheep.white", @time.hours_ago(2), @time.hours_since(1)) stats.total[:count].should == 4 stats.total[:weight].should == 316 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep.white", @time.hours_ago(5), @time.hours_since(1)) stats.total[:count].should == 9 stats.total[:weight].should == 709 stats.first.should == stats.total end - + it "should store and fetch grouping enabled stats" do ModelHelper1.store("sheep/black", {:count => 6, :weight => 461}, @time.hours_ago(4)) ModelHelper1.store("sheep/black", {:count => 2, :weight => 156}, @time) ModelHelper1.store("sheep/white", {:count => 5, :weight => 393}, @time.hours_ago(4)) ModelHelper1.store("sheep/white", {:count => 4, :weight => 316}, @time) - + stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(2), @time.hours_since(1)) stats.total["count"].should == 2 stats.total["weight"].should == 156 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(5), @time.hours_since(1)) stats.total[:count].should == 8 stats.total[:weight].should == 617 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(2), @time.hours_since(1)) stats.total[:count].should == 4 stats.total[:weight].should == 316 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(5), @time.hours_since(1)) stats.total[:count].should == 9 stats.total[:weight].should == 709 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep", @time.hours_ago(2), @time.hours_since(1)) stats.total[:count].should == 6 stats.total[:weight].should == 472 stats.first.should == stats.total - + stats = ModelHelper1.fetch("sheep", @time.hours_ago(5), @time.hours_since(1)) stats.total[:count].should == 17 stats.total[:weight].should == 1326 stats.first.should == stats.total end - + it "should connect to different Redis servers on a per-model basis" do ModelHelper3.redis.client.db.should == 14 - + ModelHelper3.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4), :label_indexing => false) ModelHelper3.store("sheep.black", {:count => 2, :weight => 156}, @time, :label_indexing => false) - + db.keys("*").should be_empty ModelHelper1.redis.keys("*").should be_empty db("ModelHelper3").keys("*").should have(5).items ModelHelper3.redis.keys("*").should have(5).items - + stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1), :label_indexing => false) stats.total["count"].should == 2 stats.total["weight"].should == 156 stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false) stats.total[:count].should == 8 stats.total[:weight].should == 617 - + ModelHelper3.connect_to(:port => 8379, :db => 13) ModelHelper3.redis.client.db.should == 13 - + stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false) stats.total.should == {} - + ModelHelper3.connect_to(:port => 8379, :db => 14) ModelHelper3.redis.client.db.should == 14 - + stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false) stats.total[:count].should == 8 stats.total[:weight].should == 617 end - + describe "Write Buffer" do before(:each) do Redistat.buffer_size = 20 end - + after(:each) do Redistat.buffer_size = 0 end - + it "should buffer calls in memory before committing to Redis" do 14.times do ModelHelper1.store("sheep.black", {:count => 1, :weight => 461}, @time.hours_ago(4)) end ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {} - + 5.times do ModelHelper1.store("sheep.black", {:count => 1, :weight => 156}, @time) end ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {} - + ModelHelper1.store("sheep.black", {:count => 1, :weight => 156}, @time) stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)) stats.total["count"].should == 20 stats.total["weight"].should == 7390 end - + it "should force flush buffer when #flush(true) is called" do ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {} 14.times do @@ -189,16 +189,11 @@ describe Redistat::Model do end ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)).total.should == {} Redistat.buffer.flush(true) - + stats = ModelHelper1.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1)) stats.total["count"].should == 14 stats.total["weight"].should == 6454 end end - + end - - - - - diff --git a/spec/options_spec.rb b/spec/options_spec.rb index b00cd7d..ceece58 100644 --- a/spec/options_spec.rb +++ b/spec/options_spec.rb @@ -1,36 +1,36 @@ require "spec_helper" describe Redistat::Options do - + before(:each) do @helper = OptionsHelper.new @helper.parse_options(:wtf => 'dude', :foo => 'booze') end - + it "should #parse_options" do @helper.options[:hello].should == 'world' @helper.options[:foo].should == 'booze' @helper.options[:wtf].should == 'dude' @helper.raw_options.should_not have_key(:hello) end - + it "should create option_accessors" do @helper.hello.should == 'world' @helper.hello('woooo') @helper.hello.should == 'woooo' end - + end class OptionsHelper include Redistat::Options - + option_accessor :hello - + def default_options { :hello => 'world', :foo => 'bar' } end - - -end \ No newline at end of file + + +end diff --git a/spec/result_spec.rb b/spec/result_spec.rb index d069e12..c29bfbc 100644 --- a/spec/result_spec.rb +++ b/spec/result_spec.rb @@ -1,14 +1,14 @@ require "spec_helper" describe Redistat::Result do - + 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 result = Redistat::Result.new result[:world].should be_nil @@ -17,5 +17,5 @@ describe Redistat::Result do result.set_or_incr(:world, 8) result[:world].should == 11 end - -end \ No newline at end of file + +end diff --git a/spec/scope_spec.rb b/spec/scope_spec.rb index 2bec816..78cf8fa 100644 --- a/spec/scope_spec.rb +++ b/spec/scope_spec.rb @@ -2,20 +2,20 @@ require "spec_helper" describe Redistat::Scope do include Redistat::Database - + before(:all) do db.flushdb end - + before(:each) do @name = "PageViews" @scope = Redistat::Scope.new(@name) end - + it "should initialize properly" do @scope.to_s.should == @name end - + it "should increment next_id" do scope = Redistat::Scope.new("Visitors") @scope.next_id.should == 1 @@ -23,5 +23,5 @@ describe Redistat::Scope do @scope.next_id.should == 2 scope.next_id.should == 2 end - -end \ No newline at end of file + +end diff --git a/spec/summary_spec.rb b/spec/summary_spec.rb index fb032c7..2f92910 100644 --- a/spec/summary_spec.rb +++ b/spec/summary_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" describe Redistat::Summary do include Redistat::Database - + before(:each) do db.flushdb @scope = "PageViews" @@ -11,27 +11,27 @@ describe Redistat::Summary do @key = Redistat::Key.new(@scope, @label, @date, {:depth => :day}) @stats = {"views" => 3, "visitors" => 2} end - + it "should update a single summary properly" do Redistat::Summary.send(:update_fields, @key, @stats, :hour) summary = db.hgetall(@key.to_s(:hour)) summary.should have(2).items summary["views"].should == "3" summary["visitors"].should == "2" - + Redistat::Summary.send(:update_fields, @key, @stats, :hour) summary = db.hgetall(@key.to_s(:hour)) summary.should have(2).items summary["views"].should == "6" summary["visitors"].should == "4" - + Redistat::Summary.send(:update_fields, @key, {"views" => -4, "visitors" => -3}, :hour) summary = db.hgetall(@key.to_s(:hour)) summary.should have(2).items summary["views"].should == "2" summary["visitors"].should == "1" 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| @@ -45,7 +45,7 @@ describe Redistat::Summary do end end end - + it "should update summaries even if no label is set" do key = Redistat::Key.new(@scope, nil, @date, {:depth => :day}) Redistat::Summary.send(:update_fields, key, @stats, :hour) @@ -54,7 +54,7 @@ describe Redistat::Summary do summary["views"].should == "3" summary["visitors"].should == "2" end - + it "should inject stats key grouping summaries" do hash = { "count/hello" => 3, "count/world" => 7, "death/bomb" => 4, "death/unicorn" => 3, @@ -64,7 +64,7 @@ describe Redistat::Summary do "death" => 7, "death/bomb" => 4, "death/unicorn" => 3, "od" => 15, :"od/sugar" => 7, :"od/meth" => 8 } end - + it "should properly store key group summaries" do stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4} Redistat::Summary.update_all(@key, stats, :hour) @@ -75,7 +75,7 @@ describe Redistat::Summary do summary["visitors/eu"].should == "2" summary["visitors/us"].should == "4" end - + it "should not store key group summaries when option is disabled" do stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4} Redistat::Summary.update_all(@key, stats, :hour, {:enable_grouping => false}) @@ -85,7 +85,7 @@ describe Redistat::Summary do summary["visitors/eu"].should == "2" summary["visitors/us"].should == "4" end - + it "should store label-based grouping enabled stats" do stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4} label = "views/about_us" @@ -96,37 +96,29 @@ describe Redistat::Summary do key.groups[1].label.to_s.should == "views" child1 = key.groups[0] parent = key.groups[1] - + label = "views/contact" key = Redistat::Key.new(@scope, label, @date) Redistat::Summary.update_all(key, stats, :hour) - + key.groups[0].label.to_s.should == "views/contact" key.groups[1].label.to_s.should == "views" child2 = key.groups[0] - + summary = db.hgetall(child1.to_s(:hour)) summary["views"].should == "3" summary["visitors/eu"].should == "2" summary["visitors/us"].should == "4" - + summary = db.hgetall(child2.to_s(:hour)) summary["views"].should == "3" summary["visitors/eu"].should == "2" summary["visitors/us"].should == "4" - + summary = db.hgetall(parent.to_s(:hour)) summary["views"].should == "6" summary["visitors/eu"].should == "4" summary["visitors/us"].should == "8" end - + end - - - - - - - - diff --git a/spec/synchronize_spec.rb b/spec/synchronize_spec.rb index 56e8f26..e859166 100644 --- a/spec/synchronize_spec.rb +++ b/spec/synchronize_spec.rb @@ -4,27 +4,27 @@ describe Redistat::Synchronize do it { should respond_to(:monitor) } it { should respond_to(:thread_safe) } it { should respond_to(:thread_safe=) } - + describe "instanciated class with Redistat::Synchronize included" do subject { SynchronizeSpecHelper.new } it { should respond_to(:monitor) } it { should respond_to(:thread_safe) } it { should respond_to(:thread_safe=) } it { should respond_to(:synchronize) } - + end - + describe "#synchronize method" do - + before(:each) do Redistat::Synchronize.instance_variable_set("@thread_safe", nil) @obj = SynchronizeSpecHelper.new end - + it "should share single Monitor object across all objects" do @obj.monitor.should == Redistat::Synchronize.monitor end - + it "should share thread_safe option across all objects" do obj2 = SynchronizeSpecHelper.new Redistat::Synchronize.thread_safe.should be_false @@ -35,14 +35,14 @@ describe Redistat::Synchronize do @obj.thread_safe.should be_true obj2.thread_safe.should be_true end - + it "should not synchronize when thread_safe is disabled" do # monitor receives :synchronize twice cause #thread_safe is _always_ synchronized Redistat::Synchronize.monitor.should_receive(:synchronize).twice @obj.thread_safe.should be_false # first #synchronize call @obj.synchronize { 'foo' } # one #synchronize call while checking #thread_safe end - + it "should synchronize when thread_safe is enabled" do Monitor.class_eval { # we're stubbing synchronize to ensure it's being called correctly, but still need it :P @@ -56,7 +56,7 @@ describe Redistat::Synchronize do @obj.synchronize { 'foo' } # two synchronize calls, once while checking thread_safe, once to call black end end - + end class SynchronizeSpecHelper diff --git a/spec/thread_safety_spec.rb b/spec/thread_safety_spec.rb index ec2b62d..7cefcc5 100644 --- a/spec/thread_safety_spec.rb +++ b/spec/thread_safety_spec.rb @@ -2,13 +2,13 @@ require "spec_helper" describe "Thread-Safety" do include Redistat::Database - + before(:each) do db.flushdb end - + #TODO should have more comprehensive thread-safe tests - + it "should incr in multiple threads" do threads = [] 50.times do @@ -19,7 +19,7 @@ describe "Thread-Safety" do threads.each { |t| t.join } db.get("spec:incr").should == "50" end - + it "should store event in multiple threads" do class ThreadSafetySpec include Redistat::Model @@ -35,5 +35,5 @@ describe "Thread-Safety" do result.total[:count].should == 50 result.total[:rand].should <= 250 end - -end \ No newline at end of file + +end