Skip to content

Commit

Permalink
Merge branch 'conn' into refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
xuncheng committed Nov 3, 2016
2 parents d01ec36 + fb33807 commit 8ce376d
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 20 deletions.
70 changes: 60 additions & 10 deletions lib/ssdb-attr.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
require "redis"
require "connection_pool"
require 'active_support'
require "active_support/core_ext"
require "active_support/concern"
require "active_support/inflector"
require "ssdb-attr/version"
require "ssdb/attr"

module SSDBAttr
class << self
attr_accessor :pool
attr_accessor :pools
attr_accessor :default_pool_name

#
# Globally setup SSDBAttr
Expand All @@ -24,17 +27,64 @@ class << self
#
# @return [void]
#
def setup(options={})
pool_size = (options[:pool] || 1).to_i
timeout = (options[:timeout] || 2).to_i

SSDBAttr.pool = ConnectionPool.new(size: pool_size, timeout: timeout) do
if options[:url].present?
Redis.new(url: options[:url])
else
Redis.new(host: options[:host], port: options[:port])
def setup(configuration)
raise "SSDB-Attr could not initialize!" if configuration.nil?

SSDBAttr.pools = {}

if configuration.is_a?(Hash)
# Only one and the default connection pool.
conf = configuration.symbolize_keys

pool_name = conf[:name] || :default

SSDBAttr.pools[pool_name.to_sym] = create_pool(configuration)
SSDBAttr.default_pool_name = pool_name
end

if configuration.is_a?(Array)
# Multiple connection pools
configuration.each do |c|
conf = c.symbolize_keys

pool_name = conf[:name]

raise "ssdb-attr: Pool name not specified!" if pool_name.blank?

SSDBAttr.pools[pool_name.to_sym] = create_pool(conf)
SSDBAttr.default_pool_name = pool_name if conf[:default]
end
end

raise "ssdb-attr: No default pool in configuration!" if SSDBAttr.pool.nil?
end

def pool(name=nil)
name = name || SSDBAttr.default_pool_name
SSDBAttr.pools[name.to_sym]
end

def default_pool
SSDBAttr.pools[SSDBAttr.default_pool_name]
end

def create_pool(pool_options)
defaults = { :pool_size => 1, :timeout => 1 }

options = pool_options.reverse_merge(defaults).deep_symbolize_keys

ConnectionPool.new(:size => options[:pool_size], :timeout => options[:timeout]) do
create_conn(options)
end
end

def create_conn(conn_options)
if !conn_options[:url].nil?
Redis.new(:url => conn_options[:url])
else
Redis.new(:host => conn_options[:host], :port => conn_options[:port])
end
end

end
end
17 changes: 13 additions & 4 deletions lib/ssdb/attr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Attr
module ClassMethods
attr_reader :ssdb_attr_names
attr_reader :ssdb_attr_id_field
attr_reader :ssdb_attr_pool_name

#
# 设置获取 SSDB Attr Id 的方式
Expand All @@ -25,6 +26,10 @@ def ssdb_attr_id(field_name)
@ssdb_attr_id_field = field_name
end

def ssdb_attr_pool(pool_name)
@ssdb_attr_pool_name = pool_name
end

#
# Method to define a SSDB attribute in a Ruby Class
#
Expand All @@ -43,7 +48,7 @@ def ssdb_attr(name, type, options = {})

define_method(name) do
instance_variable_get("@#{name}") || begin
val = SSDBAttr.pool.with { |conn| conn.get(ssdb_attr_key(name)) } || options[:default]
val = ssdb_attr_pool.with { |conn| conn.get(ssdb_attr_key(name)) } || options[:default]
instance_variable_set("@#{name}", val)
end
typecaster(instance_variable_get("@#{name}"), type)
Expand Down Expand Up @@ -81,6 +86,10 @@ def reload

private

def ssdb_attr_pool
SSDBAttr.pool(self.class.ssdb_attr_pool_name)
end

#
# Cast the value from SSDB to the correct type.
#
Expand Down Expand Up @@ -121,7 +130,7 @@ def ssdb_attr_key(name)
# @return [void]
#
def clear_ssdb_attrs
SSDBAttr.pool.with do |conn|
ssdb_attr_pool.with do |conn|
self.class.ssdb_attr_names.each { |attr| conn.del(ssdb_attr_key(attr)) }
end
end
Expand All @@ -137,7 +146,7 @@ def save_ssdb_attrs
["#{ssdb_attr_key(attr)}", previous_changes[attr][1]]
end

SSDBAttr.pool.with do |conn|
ssdb_attr_pool.with do |conn|
conn.mset(*params.flatten)
end if params.length > 0
end
Expand All @@ -151,7 +160,7 @@ def save_ssdb_attrs
# @return [void]
#
def reload_ssdb_attrs
values = SSDBAttr.pool.with { |conn| conn.mget(*self.class.ssdb_attr_names) }
values = ssdb_attr_pool.with { |conn| conn.mget(*self.class.ssdb_attr_names) }

self.class.ssdb_attr_names.each_with_index do |attr, index|
instance_variable_set("@#{attr}", values[index])
Expand Down
5 changes: 2 additions & 3 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
require "nulldb"
require "ssdb-attr"

SSDBAttr.setup(:url => "redis://localhost:8888")

# Setup ActiveRecord
ActiveRecord::Base.raise_in_transactional_callbacks = true if ActiveRecord::VERSION::STRING >= "4.2"
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")

# Setup tables for test
tbls = [
{ "posts" => "updated_at DATETIME, saved_at DATETIME, changed_at DATETIME" },
{ "custom_id_fields" => "uuid VARCHAR" }
{ "custom_id_fields" => "uuid VARCHAR" },
{ "custom_pool_names" => "uuid VARCHAR" }
]

tbls.each do |tbl|
Expand Down
128 changes: 125 additions & 3 deletions spec/ssdb-attr_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,131 @@
require 'spec_helper'
# require 'spec_helper'
require "ssdb-attr"

describe SSDBAttr do

describe "#pool" do
it "should fetch the named pool if a connection name is passed" do
options = { :url => "redis://localhost:8888" }

SSDBAttr.setup(options)

pool_dbl = double(ConnectionPool)

expect(SSDBAttr.pools).to receive(:[]).with(:foo).and_return(pool_dbl)
expect(SSDBAttr.pool(:foo)).to eq(pool_dbl)
end

it "should return the default pool if connection name of nil is passed" do
options = { :url => "redis://localhost:8888" }

SSDBAttr.setup(options)

pool_dbl = double(ConnectionPool)

SSDBAttr.default_pool_name = :default_foo

expect(SSDBAttr.pools).to receive(:[]).with(:default_foo).and_return(pool_dbl)
expect(SSDBAttr.pool).to eq(pool_dbl)
end
end

describe "#setup" do
it "should setup a ssdb connection pool" do
expect(SSDBAttr.pool).not_to be_nil
context "with only one pool" do
it "should setup a ssdb connection pool with no name specified" do
options = { :url => "redis://localhost:8888" }

SSDBAttr.setup(options)

expect(SSDBAttr.pools.size).to eq(1)
expect(SSDBAttr.pools[:default]).not_to be_nil
expect(SSDBAttr.default_pool_name).to eq(:default)
end

it "should setup a ssdb connection pool with name specified" do
options = { :url => "redis://localhost:8888", :name => :main }

SSDBAttr.setup(options)

expect(SSDBAttr.pools.size).to eq(1)
expect(SSDBAttr.default_pool_name).to eq(:main)
expect(SSDBAttr.pools[:main]).not_to be_nil
expect(SSDBAttr.default_pool).to eq(SSDBAttr.pools[:main])
end
end

context "with pools" do
it "should raise error if no name specified" do
options = [
{ :url => "redis://localhost:8888" },
{ :url => "redis://localhost:6379" }
]

expect { SSDBAttr.setup(options) }.to raise_error(RuntimeError)
end

it "should raise error if no default specified" do
options = [
{ :url => "redis://localhost:8888", :name => :pool1 },
{ :url => "redis://localhost:6379", :name => :pool2 }
]

expect { SSDBAttr.setup(options) }.to raise_error(RuntimeError)
end

it "should initialize correctly" do
options = [
{ :url => "redis://localhost:8888", :name => :ssdb, :pool_size => 10, :timeout => 2, :default => true },
{ :url => "redis://localhost:6379", :name => :redis, :pool_size => 5, :timeout => 3 }
]

SSDBAttr.setup(options)

expect(SSDBAttr.pools.size).to eq(2)
expect(SSDBAttr.pools[:ssdb]).to be_a(ConnectionPool)
expect(SSDBAttr.pools[:redis]).to be_a(ConnectionPool)
expect(SSDBAttr.default_pool_name).to eq(:ssdb)
expect(SSDBAttr.default_pool).to eq(SSDBAttr.pools[:ssdb])
end
end
end

describe "#create_pool" do
it "will use create a connection pool" do
pool = SSDBAttr.create_pool(:url => "redis://localhost:8888", :pool_size => 10, :timeout => 18)

expect(pool).not_to be_nil
expect(pool).to be_a(ConnectionPool)
expect(pool.instance_variable_get(:@size)).to eq(10)
expect(pool.instance_variable_get(:@timeout)).to eq(18)

conn = pool.with { |conn| conn }
expect(conn).to be_a(Redis)
expect(conn.client.host).to eq("localhost")
expect(conn.client.port).to eq(8888)
end
end

describe "#create_conn" do
context "with url" do
it do
conn = SSDBAttr.create_conn(:url => "redis://localhost:8888")

expect(conn).not_to be_nil
expect(conn).to be_a(Redis)
expect(conn.client.host).to eq("localhost")
expect(conn.client.port).to eq(8888)
end
end

context "with host/port options" do
it do
conn = SSDBAttr.create_conn(:host => "localhost", :port => "8888")

expect(conn).not_to be_nil
expect(conn).to be_a(Redis)
expect(conn.client.host).to eq("localhost")
expect(conn.client.port).to eq(8888)
end
end
end
end
33 changes: 33 additions & 0 deletions spec/ssdb/attr_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,20 @@ class CustomIdField < ActiveRecord::Base
ssdb_attr :content, :string
end

class CustomPoolName < ActiveRecord::Base
include SSDB::Attr

ssdb_attr_pool :foo_pool

ssdb_attr :foo_id, :integer
end

describe SSDB::Attr do

before(:all) do
# Connect to test SSDB server
SSDBAttr.setup(:url => "redis://localhost:8888")

# Clean up SSDB
system('printf "7\nflushdb\n\n4\nping\n\n" | nc 127.0.0.1 8888 -i 1 > /dev/null')

Expand Down Expand Up @@ -196,4 +207,26 @@ class CustomIdField < ActiveRecord::Base
expect(custom_id_field.send(:ssdb_attr_key, "content")).to eq("custom_id_fields:123:content")
end
end

context "CustomPoolName" do

it "should respond to methods" do
expect(CustomPoolName).to respond_to(:ssdb_attr_pool)
end

it "should set SSDBAttr connection for class correct" do
expect(CustomPoolName.ssdb_attr_pool_name).to eq(:foo_pool)
end

describe ".ssdb_attr_pool" do
it do
ccn = CustomPoolName.new

pool_dbl = double(ConnectionPool)

expect(SSDBAttr).to receive(:pool).with(:foo_pool).and_return(pool_dbl)
expect(ccn.send(:ssdb_attr_pool)).to eq(pool_dbl)
end
end
end
end

0 comments on commit 8ce376d

Please sign in to comment.