redistat 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.md
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ .bundle/*
23
+ .yardoc/*
24
+ spec/db/*
25
+ doc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org/'
2
+
3
+ gem 'activesupport', '>= 2.3.0'
4
+ gem 'json', '>= 1.0.0'
5
+ gem 'redis', '>= 2.0.0'
6
+ gem 'time_ext', '>= 0.2.6'
7
+
8
+ group :development do
9
+ gem 'rspec', '>= 2.0.1'
10
+ gem 'yard', '>= 0.6.1'
11
+ gem 'i18n'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.0.3)
5
+ diff-lcs (1.1.2)
6
+ i18n (0.4.2)
7
+ json (1.4.6)
8
+ redis (2.1.1)
9
+ rspec (2.1.0)
10
+ rspec-core (~> 2.1.0)
11
+ rspec-expectations (~> 2.1.0)
12
+ rspec-mocks (~> 2.1.0)
13
+ rspec-core (2.1.0)
14
+ rspec-expectations (2.1.0)
15
+ diff-lcs (~> 1.1.2)
16
+ rspec-mocks (2.1.0)
17
+ time_ext (0.2.6)
18
+ activesupport (>= 2.3.0)
19
+ yard (0.6.3)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ activesupport (>= 2.3.0)
26
+ i18n
27
+ json (>= 1.0.0)
28
+ redis (>= 2.0.0)
29
+ rspec (>= 2.0.1)
30
+ time_ext (>= 0.2.6)
31
+ yard (>= 0.6.1)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Jim Myhrberg.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Redistat
2
+
3
+ A Redis-backed statistics storage and querying library written in Ruby.
4
+
5
+ ## Early Beta
6
+
7
+ Currently this is an early beta release. Readme and documentation is forthcoming.
8
+
9
+ For now, please check `spec/model_spec.rb` and `spec/model_helper.rb` to get started with how to use Redistat.
10
+
11
+
12
+ ## Note on Patches/Pull Requests
13
+
14
+ * Fork the project.
15
+ * Make your feature addition or bug fix.
16
+ * Add tests for it. This is important so I don't break it in a
17
+ future version unintentionally.
18
+ * Commit, do not mess with rakefile, version, or history.
19
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
20
+ * Send me a pull request. Bonus points for topic branches.
21
+
22
+
23
+ ## License and Copyright
24
+
25
+ Copyright (c) 2010 Jim Myhrberg.
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining
28
+ a copy of this software and associated documentation files (the
29
+ "Software"), to deal in the Software without restriction, including
30
+ without limitation the rights to use, copy, modify, merge, publish,
31
+ distribute, sublicense, and/or sell copies of the Software, and to
32
+ permit persons to whom the Software is furnished to do so, subject to
33
+ the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be
36
+ included in all copies or substantial portions of the Software.
37
+
38
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
41
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
42
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
43
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
44
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,71 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = 'redistat'
8
+ gem.summary = 'A Redis-backed statistics storage and querying library written in Ruby.'
9
+ gem.description = 'A Redis-backed statistics storage and querying library written in Ruby.'
10
+ gem.email = 'contact@jimeh.me'
11
+ gem.homepage = 'http://github.com/jimeh/redistat'
12
+ gem.authors = ['Jim Myhrberg']
13
+ gem.add_dependency 'activesupport', '>= 2.3.0'
14
+ gem.add_dependency 'json', '>= 1.0.0'
15
+ gem.add_dependency 'redis', '>= 2.0.0'
16
+ gem.add_dependency 'time_ext', '>= 0.2.6'
17
+ gem.add_development_dependency 'rspec', '>= 2.0.1'
18
+ gem.add_development_dependency 'yard', '>= 0.6.1'
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
23
+ end
24
+
25
+
26
+ # Rspec
27
+ require 'rspec/core/rake_task'
28
+ RSpec::Core::RakeTask.new(:spec) do |spec|
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ end
31
+
32
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov = true
35
+ end
36
+
37
+ task :spec => :check_dependencies
38
+
39
+ task :default => [:start, :spec, :stop]
40
+
41
+
42
+ # Start/stop Redis test server
43
+ REDIS_DIR = File.expand_path(File.join("..", "spec"), __FILE__)
44
+ REDIS_CNF = File.join(REDIS_DIR, "redis-test.conf")
45
+ REDIS_PID = File.join(REDIS_DIR, "db", "redis.pid")
46
+
47
+ desc "Start the Redis test server"
48
+ task :start do
49
+ unless File.exists?(REDIS_PID)
50
+ system "redis-server #{REDIS_CNF}"
51
+ end
52
+ end
53
+
54
+ desc "Stop the Redis test server"
55
+ task :stop do
56
+ if File.exists?(REDIS_PID)
57
+ system "kill #{File.read(REDIS_PID)}"
58
+ system "rm #{REDIS_PID}"
59
+ end
60
+ end
61
+
62
+
63
+ # YARD Documentation
64
+ begin
65
+ require 'yard'
66
+ YARD::Rake::YardocTask.new
67
+ rescue LoadError
68
+ task :yardoc do
69
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
70
+ end
71
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/lib/redistat.rb ADDED
@@ -0,0 +1,104 @@
1
+
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'active_support/hash_with_indifferent_access' if !Hash.respond_to?(:with_indifferent_access) # Active Support 2.x and 3.x
5
+ require 'redis'
6
+ require 'date'
7
+ require 'time'
8
+ require 'time_ext'
9
+ require 'json'
10
+ require 'digest/sha1'
11
+
12
+ require 'redistat/collection'
13
+ require 'redistat/database'
14
+ require 'redistat/date'
15
+ require 'redistat/event'
16
+ require 'redistat/finder'
17
+ require 'redistat/finder/date_set'
18
+ require 'redistat/key'
19
+ require 'redistat/label'
20
+ require 'redistat/model'
21
+ require 'redistat/result'
22
+ require 'redistat/scope'
23
+ require 'redistat/summary'
24
+
25
+ require 'redistat/core_ext/date'
26
+ require 'redistat/core_ext/time'
27
+ require 'redistat/core_ext/fixnum'
28
+
29
+ module Redistat
30
+
31
+ KEY_NEXT_ID = ".next_id"
32
+ KEY_EVENT = ".event:"
33
+ KEY_LEBELS = "Redistat.lables:"
34
+ KEY_EVENT_IDS = ".event_ids"
35
+
36
+ class InvalidOptions < ArgumentError; end
37
+
38
+ # Provides access to the Redis database. This is shared accross all models and instances.
39
+ def redis
40
+ threaded[:redis] ||= connection(*options)
41
+ end
42
+
43
+ def redis=(connection)
44
+ threaded[:redis] = connection
45
+ end
46
+
47
+ def threaded
48
+ Thread.current[:redistat] ||= {}
49
+ end
50
+
51
+ # Connect to a redis database.
52
+ #
53
+ # @param options [Hash] options to create a message with.
54
+ # @option options [#to_s] :host ('127.0.0.1') Host of the redis database.
55
+ # @option options [#to_s] :port (6379) Port number.
56
+ # @option options [#to_s] :db (0) Database number.
57
+ # @option options [#to_s] :timeout (0) Database timeout in seconds.
58
+ # @example Connect to a database in port 6380.
59
+ # Redistat.connect(:port => 6380)
60
+ def connect(*options)
61
+ self.redis = nil
62
+ @options = options
63
+ end
64
+
65
+ # Return a connection to Redis.
66
+ #
67
+ # This is a wapper around Redis.new(options)
68
+ def connection(*options)
69
+ Redis.new(*options)
70
+ end
71
+
72
+ def options
73
+ @options = [] unless defined? @options
74
+ @options
75
+ end
76
+
77
+ # Clear the database.
78
+ def flush
79
+ redis.flushdb
80
+ end
81
+
82
+ module_function :connect, :connection, :flush, :redis, :redis=, :options, :threaded
83
+
84
+ end
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
@@ -0,0 +1,16 @@
1
+ module Redistat
2
+ class Collection < ::Array
3
+
4
+ attr_accessor :from
5
+ attr_accessor :till
6
+ attr_accessor :depth
7
+ attr_accessor :total
8
+
9
+ def initialize(options = {})
10
+ @from = options[:from] ||= nil
11
+ @till = options[:till] ||= nil
12
+ @depth = options[:depth] ||= nil
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ class Date
2
+ include Redistat::DateHelper
3
+
4
+ def to_time
5
+ Time.parse(self.to_s)
6
+ end
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ class Fixnum
2
+ include Redistat::DateHelper
3
+
4
+ def to_time
5
+ Time.at(self)
6
+ end
7
+
8
+ end
@@ -0,0 +1,3 @@
1
+ class Time
2
+ include Redistat::DateHelper
3
+ end
@@ -0,0 +1,10 @@
1
+ module Redistat
2
+ module Database
3
+ def self.included(base)
4
+ base.extend(Database)
5
+ end
6
+ def db
7
+ Redistat.redis
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,93 @@
1
+ module Redistat
2
+ class Date
3
+
4
+ attr_accessor :year
5
+ attr_accessor :month
6
+ attr_accessor :day
7
+ attr_accessor :hour
8
+ attr_accessor :min
9
+ attr_accessor :sec
10
+ attr_accessor :usec
11
+ attr_accessor :depth
12
+
13
+ DEPTHS = [:year, :month, :day, :hour, :min, :sec, :usec]
14
+
15
+ def initialize(input, depth = nil)
16
+ @depth = depth
17
+ if input.is_a?(::Time)
18
+ from_time(input)
19
+ elsif input.is_a?(::Date)
20
+ from_date(input)
21
+ elsif input.is_a?(::String)
22
+ from_string(input)
23
+ elsif input.is_a?(::Fixnum)
24
+ from_integer(input)
25
+ end
26
+ end
27
+
28
+ def to_t
29
+ ::Time.local(@year, @month, @day, @hour, @min, @sec, @usec)
30
+ end
31
+ alias :to_time :to_t
32
+
33
+ def to_d
34
+ ::Date.civil(@year, @month, @day)
35
+ end
36
+ alias :to_date :to_d
37
+
38
+ def to_i
39
+ to_time.to_i
40
+ end
41
+ alias :to_integer :to_i
42
+
43
+ def to_s(depth = nil)
44
+ depth ||= @depth ||= :sec
45
+ output = ""
46
+ DEPTHS.each_with_index do |current, i|
47
+ break if self.send(current).nil?
48
+ if current != :usec
49
+ output << self.send(current).to_s.rjust((i <= 0) ? 4 : 2, '0')
50
+ else
51
+ output << "." + self.send(current).to_s.rjust(6, '0')
52
+ end
53
+ break if current == depth
54
+ end
55
+ output
56
+ end
57
+ alias :to_string :to_s
58
+
59
+ private
60
+
61
+ def from_time(input)
62
+ DEPTHS.each do |k|
63
+ send("#{k}=", input.send(k))
64
+ end
65
+ end
66
+
67
+ def from_date(input)
68
+ [:year, :month, :day].each do |k|
69
+ send("#{k}=", input.send(k))
70
+ end
71
+ [:hour, :min, :sec, :usec].each do |k|
72
+ send("#{k}=", 0)
73
+ end
74
+ end
75
+
76
+ def from_integer(input)
77
+ from_time(::Time.at(input))
78
+ end
79
+
80
+ def from_string(input)
81
+ input += "19700101000000"[input.size..-1] if input =~ /^\d\d\d[\d]+$/i
82
+ from_time(::Time.parse(input))
83
+ end
84
+
85
+ end
86
+
87
+ module DateHelper
88
+ def to_redistat(depth = nil)
89
+ Redistat::Date.new(self, depth)
90
+ end
91
+ alias :to_rs :to_redistat
92
+ end
93
+ end