From b1570698df617b963ef7dc227057dc13ce379470 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 13 Mar 2013 23:39:11 -0700 Subject: [PATCH] Initial spike It makes a new Redis object. But does it actually work? --- README.md | 24 ++++-- Rakefile | 3 + celluloid-redis.gemspec | 2 + lib/celluloid/redis.rb | 9 +-- lib/celluloid/redis/redis_ext.rb | 28 +++++++ lib/redis/connection/celluloid.rb | 101 ++++++++++++++++++++++++ spec/redis/connection/celluloid_spec.rb | 8 ++ spec/spec_helper.rb | 2 + tasks/rspec.rake | 7 ++ 9 files changed, 172 insertions(+), 12 deletions(-) create mode 100644 lib/celluloid/redis/redis_ext.rb create mode 100644 lib/redis/connection/celluloid.rb create mode 100644 spec/redis/connection/celluloid_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 tasks/rspec.rake diff --git a/README.md b/README.md index 63efb3a..b6e5861 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,26 @@ Or install it yourself as: $ gem install celluloid-redis +Require it in your Ruby application with: + + require 'celluloid/redis' + ## Usage -TODO: Write usage instructions here +When instantiating the client object, specify `:celluloid`: + +```ruby +redis = Redis.new(:driver => :celluloid) +``` ## Contributing -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +* Fork this repository on github +* Make your changes and send us a pull request +* If we like them we'll merge them +* If we've accepted a patch, feel free to ask for commit access + +## License + +Copyright (c) 2013 Tony Arcieri. Distributed under the MIT License. See +LICENSE.txt for further details. \ No newline at end of file diff --git a/Rakefile b/Rakefile index 2995527..6e77132 100644 --- a/Rakefile +++ b/Rakefile @@ -1 +1,4 @@ require "bundler/gem_tasks" +Dir["tasks/**/*.rake"].each { |task| load task } + +task :default => :spec \ No newline at end of file diff --git a/celluloid-redis.gemspec b/celluloid-redis.gemspec index af30be4..a086127 100644 --- a/celluloid-redis.gemspec +++ b/celluloid-redis.gemspec @@ -23,4 +23,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" + spec.add_development_dependency "rspec" + spec.add_development_dependency "guard-rspec" end diff --git a/lib/celluloid/redis.rb b/lib/celluloid/redis.rb index c599d84..e0ec131 100644 --- a/lib/celluloid/redis.rb +++ b/lib/celluloid/redis.rb @@ -1,7 +1,4 @@ -require "celluloid/redis/version" +require "redis" -module Celluloid - module Redis - # Your code goes here... - end -end +require "celluloid/redis/version" +require "celluloid/redis/redis_ext" \ No newline at end of file diff --git a/lib/celluloid/redis/redis_ext.rb b/lib/celluloid/redis/redis_ext.rb new file mode 100644 index 0000000..76a72f4 --- /dev/null +++ b/lib/celluloid/redis/redis_ext.rb @@ -0,0 +1,28 @@ +class Redis + class Client + # Well this is really sad. redis-rb does not provide extensible driver + # support. Instead they couple everything together though this method. + # This leaves us no choice but to monkeypatch + def _parse_driver(driver) + driver = driver.to_s if driver.is_a?(Symbol) + + if driver.kind_of?(String) + case driver + when "ruby" + require "redis/connection/ruby" + driver = Connection::Ruby + when "celluloid" + require "redis/connection/celluloid" + driver = Connection::Celluloid + when "hiredis" + require "redis/connection/hiredis" + driver = Connection::Hiredis + else + raise "Unknown driver: #{driver}" + end + end + + driver + end + end +end \ No newline at end of file diff --git a/lib/redis/connection/celluloid.rb b/lib/redis/connection/celluloid.rb new file mode 100644 index 0000000..416d529 --- /dev/null +++ b/lib/redis/connection/celluloid.rb @@ -0,0 +1,101 @@ +require "redis/connection/registry" +require "redis/connection/command_helper" +require "redis/errors" +require "celluloid/io" + +class Redis + module Connection + class Celluloid + include Redis::Connection::CommandHelper + + MINUS = "-".freeze + PLUS = "+".freeze + COLON = ":".freeze + DOLLAR = "$".freeze + ASTERISK = "*".freeze + + def self.connect(config) + if config[:scheme] == "unix" + sock = ::Celluloid::IO::UNIXSocket.connect(config[:path], config[:timeout]) + else + sock = ::Celluloid::IO::TCPSocket.connect(config[:host], config[:port], config[:timeout]) + end + + new(sock) + end + + def initialize(sock) + @sock = sock + end + + def connected? + !!@sock + end + + def disconnect + @sock.close rescue nil + ensure + @sock = nil + end + + def timeout=(timeout) + if @sock.respond_to?(:timeout=) + @sock.timeout = timeout + end + end + + def write(command) + @sock.write(build_command(command)) + end + + def read + line = @sock.gets + reply_type = line.slice!(0, 1) + format_reply(reply_type, line) + + rescue Errno::EAGAIN + raise TimeoutError + end + + def format_reply(reply_type, line) + case reply_type + when MINUS then format_error_reply(line) + when PLUS then format_status_reply(line) + when COLON then format_integer_reply(line) + when DOLLAR then format_bulk_reply(line) + when ASTERISK then format_multi_bulk_reply(line) + else raise ProtocolError.new(reply_type) + end + end + + def format_error_reply(line) + CommandError.new(line.strip) + end + + def format_status_reply(line) + line.strip + end + + def format_integer_reply(line) + line.to_i + end + + def format_bulk_reply(line) + bulklen = line.to_i + return if bulklen == -1 + reply = encode(@sock.read(bulklen)) + @sock.read(2) # Discard CRLF. + reply + end + + def format_multi_bulk_reply(line) + n = line.to_i + return if n == -1 + + Array.new(n) { read } + end + end + end +end + +Redis::Connection.drivers << Redis::Connection::Celluloid \ No newline at end of file diff --git a/spec/redis/connection/celluloid_spec.rb b/spec/redis/connection/celluloid_spec.rb new file mode 100644 index 0000000..e9bc8d6 --- /dev/null +++ b/spec/redis/connection/celluloid_spec.rb @@ -0,0 +1,8 @@ +require "spec_helper" + +describe Redis::Connection::Celluloid do + it "connects to Redis" do + connection = Redis.new(:driver => :celluloid) + connection.should be_a Redis + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..7455898 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,2 @@ +require "celluloid/redis" +require "redis/connection/celluloid" \ No newline at end of file diff --git a/tasks/rspec.rake b/tasks/rspec.rake new file mode 100644 index 0000000..a089676 --- /dev/null +++ b/tasks/rspec.rake @@ -0,0 +1,7 @@ +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new + +RSpec::Core::RakeTask.new(:rcov) do |task| + task.rcov = true +end \ No newline at end of file