From dc162e0c89cbacd494148d98334090a3a89117cb Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sun, 28 Nov 2010 10:10:58 +0000 Subject: [PATCH] initial work to being able to use per-model redis configurations --- lib/redistat.rb | 70 +++++++++++++------------------------- lib/redistat/connection.rb | 67 ++++++++++++++++++++++++++++++++++++ lib/redistat/database.rb | 2 +- spec/_redistat_spec.rb | 34 ------------------ spec/connection_spec.rb | 61 +++++++++++++++++++++++++++++++++ spec/database_spec.rb | 10 ++++++ spec/spec_helper.rb | 2 +- 7 files changed, 164 insertions(+), 82 deletions(-) create mode 100644 lib/redistat/connection.rb delete mode 100644 spec/_redistat_spec.rb create mode 100644 spec/connection_spec.rb create mode 100644 spec/database_spec.rb diff --git a/lib/redistat.rb b/lib/redistat.rb index 4c151ee..e18c076 100644 --- a/lib/redistat.rb +++ b/lib/redistat.rb @@ -10,6 +10,7 @@ require 'json' require 'digest/sha1' require 'redistat/collection' +require 'redistat/connection' require 'redistat/database' require 'redistat/date' require 'redistat/event' @@ -34,51 +35,28 @@ module Redistat KEY_EVENT_IDS = ".event_ids" class InvalidOptions < ArgumentError; end - - # Provides access to the Redis database. This is shared accross all models and instances. - def redis - threaded[:redis] ||= connection(*options) - end - - def redis=(connection) - threaded[:redis] = connection - end - - def threaded - Thread.current[:redistat] ||= {} - end - - # Connect to a redis database. - # - # @param options [Hash] options to create a message with. - # @option options [#to_s] :host ('127.0.0.1') Host of the redis database. - # @option options [#to_s] :port (6379) Port number. - # @option options [#to_s] :db (0) Database number. - # @option options [#to_s] :timeout (0) Database timeout in seconds. - # @example Connect to a database in port 6380. - # Redistat.connect(:port => 6380) - def connect(*options) - self.redis = nil - @options = options - end - - # Return a connection to Redis. - # - # This is a wapper around Redis.new(options) - def connection(*options) - Redis.new(*options) - end - - def options - @options = [] unless defined? @options - @options - end - - # Clear the database. - def flush - redis.flushdb - end + class RedisServerIsTooOld < Exception; end - module_function :connect, :connection, :flush, :redis, :redis=, :options, :threaded - + class << self + + 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.flush instead." + connection.flushdb + end + + end end diff --git a/lib/redistat/connection.rb b/lib/redistat/connection.rb new file mode 100644 index 0000000..76a04a0 --- /dev/null +++ b/lib/redistat/connection.rb @@ -0,0 +1,67 @@ +module Redistat + module Connection + + REQUIRED_SERVER_VERSION = "1.3.10" + + class << self + + def get(ref = nil) + ref ||= :default + connections[references[ref]] || create + end + + def add(conn, ref = nil) + ref ||= :default + check_redis_version(conn) + references[ref] = conn.client.id + connections[conn.client.id] = conn + end + + def create(options = {}) + ref = options.delete(:ref) || :default + options.reverse_merge!(default_options) + conn = (connections[connection_id(options)] ||= connection(options)) + references[ref] = conn.client.id + conn + end + + def connections + threaded[:connections] ||= {} + end + + def references + threaded[:references] ||= {} + end + + def threaded + Thread.current[:redistat] ||= {} + end + + private + + def check_redis_version(conn) + raise RedisServerIsTooOld if conn.info["redis_version"] < REQUIRED_SERVER_VERSION + conn + end + + def connection(options) + check_redis_version(Redis.new(options)) + end + + def connection_id(options = {}) + options.reverse_merge!(default_options) + "redis://#{options[:host]}:#{options[:port]}/#{options[:db]}" + end + + def default_options + { + :host => '127.0.0.1', + :port => 6379, + :db => 0, + :timeout => 5 + } + end + + end + end +end \ No newline at end of file diff --git a/lib/redistat/database.rb b/lib/redistat/database.rb index fee7f39..7276270 100644 --- a/lib/redistat/database.rb +++ b/lib/redistat/database.rb @@ -4,7 +4,7 @@ module Redistat base.extend(Database) end def db - Redistat.redis + Redistat.connection end end end \ No newline at end of file diff --git a/spec/_redistat_spec.rb b/spec/_redistat_spec.rb deleted file mode 100644 index 01018a2..0000000 --- a/spec/_redistat_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -require "spec_helper" - -describe Redistat do - include Redistat::Database - - before(:each) do - db.flushdb - end - - it "should have a valid Redis client instance" do - db.should_not be_nil - end - - it "should be connected to the testing server" do - db.client.port.should == 8379 - db.client.host.should == "127.0.0.1" - end - - it "should be able to set and get data" do - db.set("hello", "world") - db.get("hello").should == "world" - db.del("hello").should be_true - end - - it "should be able to store hashes to Redis" do - db.hset("key", "field", "1") - db.hget("key", "field").should == "1" - db.hincrby("key", "field", 1) - db.hget("key", "field").should == "2" - db.hincrby("key", "field", -1) - db.hget("key", "field").should == "1" - end - -end \ No newline at end of file diff --git a/spec/connection_spec.rb b/spec/connection_spec.rb new file mode 100644 index 0000000..acc57d4 --- /dev/null +++ b/spec/connection_spec.rb @@ -0,0 +1,61 @@ +require "spec_helper" +include Redistat + +describe Redistat::Connection do + + it "should have a valid Redis client instance" do + Redistat.redis.should_not be_nil + end + + it "should have initialized custom testing connection" do + redis = Redistat.redis + redis.client.host.should == '127.0.0.1' + redis.client.port.should == 8379 + redis.client.db.should == 15 + end + + it "should be able to set and get data" do + redis = Redistat.redis + 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 = Redistat.redis + redis.hset("hash", "field", "1") + redis.hget("hash", "field").should == "1" + redis.hincrby("hash", "field", 1) + redis.hget("hash", "field").should == "2" + redis.hincrby("hash", "field", -1) + 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.port.should == 8379 + Redistat.connect(:port => 6379, :db => 15, :ref => "Custom") + Redistat.redis.client.port.should == 8379 + Redistat.redis("Custom").client.port.should == 6379 + end + + it "should be able to overwrite default and custom refs" do + Redistat.redis.client.port.should == 8379 + Redistat.connect(:port => 6379, :db => 15) + Redistat.redis.client.port.should == 6379 + + Redistat.redis("Custom").client.port.should == 6379 + Redistat.connect(:port => 8379, :db => 15, :ref => "Custom") + Redistat.redis("Custom").client.port.should == 8379 + + # 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 + +end \ No newline at end of file diff --git a/spec/database_spec.rb b/spec/database_spec.rb new file mode 100644 index 0000000..d7e8051 --- /dev/null +++ b/spec/database_spec.rb @@ -0,0 +1,10 @@ +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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e5e1627..dfeccb4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,5 +8,5 @@ require 'rspec' require 'rspec/autorun' # use the test Redistat instance -Redistat.connect({:port => 8379, :db => 15}) +Redistat.connect(:port => 8379, :db => 15) Redistat.flush