From 0a7abe935ed9cb7f1ee32c1c95e517a2920c04c4 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Thu, 14 Apr 2011 16:53:29 +0100 Subject: [PATCH] thread-safe connection handler --- lib/redistat/connection.rb | 48 +++++++++++++++++++++++++++----------- spec/connection_spec.rb | 5 ++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/redistat/connection.rb b/lib/redistat/connection.rb index 23d9141..10d4c40 100644 --- a/lib/redistat/connection.rb +++ b/lib/redistat/connection.rb @@ -1,29 +1,41 @@ +require 'monitor' + module Redistat module Connection REQUIRED_SERVER_VERSION = "1.3.10" + # TODO: Create a ConnectionPool instance object to replace Connection class + class << self + # TODO: clean/remove all ref-less connections + def get(ref = nil) ref ||= :default - connections[references[ref]] || create + synchronize do + connections[references[ref]] || create + end end def add(conn, ref = nil) ref ||= :default - check_redis_version(conn) - references[ref] = conn.client.id - connections[conn.client.id] = conn + synchronize do + check_redis_version(conn) + references[ref] = conn.client.id + connections[conn.client.id] = conn + end end def create(options = {}) - #TODO clean/remove all ref-less connections - ref = options.delete(:ref) || :default - options.reverse_merge!(default_options) - conn = (connections[connection_id(options)] ||= connection(options)) - references[ref] = conn.client.id - conn + synchronize do + options = options.clone + ref = options.delete(:ref) || :default + options.reverse_merge!(default_options) + conn = (connections[connection_id(options)] ||= connection(options)) + references[ref] = conn.client.id + conn + end end def connections @@ -36,9 +48,12 @@ module Redistat private - def check_redis_version(conn) - raise RedisServerIsTooOld if conn.info["redis_version"] < REQUIRED_SERVER_VERSION - conn + def monitor + @monitor ||= Monitor.new + end + + def synchronize(&block) + monitor.synchronize(&block) end def connection(options) @@ -46,10 +61,15 @@ module Redistat end def connection_id(options = {}) - options.reverse_merge!(default_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', diff --git a/spec/connection_spec.rb b/spec/connection_spec.rb index 04aae55..907a7d1 100644 --- a/spec/connection_spec.rb +++ b/spec/connection_spec.rb @@ -59,4 +59,9 @@ describe Redistat::Connection do 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