redis-store-1.9.0/0000755000004100000410000000000013704151265014015 5ustar www-datawww-dataredis-store-1.9.0/.travis.yml0000644000004100000410000000211413704151265016124 0ustar www-datawww-datalanguage: ruby sudo: false cache: bundler notifications: webhooks: https://www.travisbuddy.com on_success: never before_install: - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter rvm: - 2.3 - 2.4 - 2.5 - 2.6 - 2.7 - ruby-head - jruby-head gemfile: - gemfiles/redis_4_0_x.gemfile - gemfiles/redis_4_1_x.gemfile - gemfiles/redis_4_x.gemfile before_script: "./cc-test-reporter before-build" after_script: - "./cc-test-reporter after-build --exit-code $EXIT_CODE" - "./cc-test-reporter format-coverage -t simplecov -o coverage/codeclimate.json" - if [[ "$TRAVIS_TEST_RESULT" == 0 ]]; then ./cc-test-reporter upload-coverage; fi matrix: allow_failures: - rvm: jruby-head - rvm: ruby-head deploy: provider: rubygems api_key: secure: vhwP2VNfVYgppPNis7asqMnWuIcURr2e99uhYeHS4Sc+hIozu2QzAAekDrVpEDpeaEubtmTi19UcV4dZbDrQ0M+buE8LJEpItz73yK++J75Rzyh/bsGnWTy2FIvedLrH+jBNf28I9p8XNWkQxVaTc/r/v6BX3mmyV/jVoTBz9es= gem: redis-store on: tags: true repo: redis-store/redis-store redis-store-1.9.0/test/0000755000004100000410000000000013704151265014774 5ustar www-datawww-dataredis-store-1.9.0/test/redis/0000755000004100000410000000000013704151265016102 5ustar www-datawww-dataredis-store-1.9.0/test/redis/store/0000755000004100000410000000000013704151265017236 5ustar www-datawww-dataredis-store-1.9.0/test/redis/store/interface_test.rb0000644000004100000410000000123513704151265022563 0ustar www-datawww-datarequire 'test_helper' class InterfacedRedis < Redis include Redis::Store::Interface end describe Redis::Store::Interface do before do @r = InterfacedRedis.new end it "should get an element" do lambda { @r.get("key", :option => true) } # .wont_raise ArgumentError end it "should set an element" do lambda { @r.set("key", "value", :option => true) } # .wont_raise ArgumentError end it "should setnx an element" do lambda { @r.setnx("key", "value", :option => true) } # .wont_raise ArgumentError end it "should setex an element" do lambda { @r.setex("key", 1, "value", :option => true) } # .wont_raise ArgumentError end end redis-store-1.9.0/test/redis/store/factory_test.rb0000644000004100000410000002457413704151265022305 0ustar www-datawww-datarequire 'test_helper' require 'json' describe "Redis::Store::Factory" do describe ".create" do describe "when not given any arguments" do it "instantiates Redis::Store" do store = Redis::Store::Factory.create store.must_be_kind_of(Redis::Store) store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0") end end describe "when given a Hash" do it "uses specified host" do store = Redis::Store::Factory.create :host => "localhost" store.to_s.must_equal("Redis Client connected to localhost:6379 against DB 0") end it "uses specified port" do store = Redis::Store::Factory.create :host => "localhost", :port => 6380 store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 0") end it "uses specified scheme" do store = Redis::Store::Factory.create :scheme => "rediss" store.instance_variable_get(:@client).scheme.must_equal('rediss') end it "uses specified path" do store = Redis::Store::Factory.create :path => "/var/run/redis.sock" store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0") end it "uses specified db" do store = Redis::Store::Factory.create :host => "localhost", :port => 6380, :db => 13 store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 13") end it "uses specified namespace" do store = Redis::Store::Factory.create :namespace => "theplaylist" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end it "uses specified key_prefix as namespace" do store = Redis::Store::Factory.create :key_prefix => "theplaylist" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end it "uses specified password" do store = Redis::Store::Factory.create :password => "secret" store.instance_variable_get(:@client).password.must_equal("secret") end it 'uses empty password' do store = Redis::Store::Factory.create :password => '' store.instance_variable_get(:@client).password.must_equal('') end it 'uses nil password' do store = Redis::Store::Factory.create :password => nil assert_nil(store.instance_variable_get(:@client).password) end it "disables serialization" do store = Redis::Store::Factory.create :serializer => nil store.instance_variable_get(:@serializer).must_be_nil store.instance_variable_get(:@options)[:raw].must_equal(true) end it "configures pluggable serialization backend" do store = Redis::Store::Factory.create :serializer => JSON store.instance_variable_get(:@serializer).must_equal(JSON) store.instance_variable_get(:@options)[:raw].must_equal(false) end describe "defaults" do it "defaults to localhost if no host specified" do store = Redis::Store::Factory.create store.instance_variable_get(:@client).host.must_equal('127.0.0.1') end it "defaults to 6379 if no port specified" do store = Redis::Store::Factory.create store.instance_variable_get(:@client).port.must_equal(6379) end it "defaults to redis:// if no scheme specified" do store = Redis::Store::Factory.create store.instance_variable_get(:@client).scheme.must_equal('redis') end end describe 'with stdout disabled' do before do @original_stderr = $stderr @original_stdout = $stdout $stderr = Tempfile.new('stderr') $stdout = Tempfile.new('stdout') end it "disables marshalling and provides deprecation warning" do store = Redis::Store::Factory.create :marshalling => false store.instance_variable_get(:@serializer).must_be_nil store.instance_variable_get(:@options)[:raw].must_equal(true) end it "enables marshalling but provides warning to use :serializer instead" do store = Redis::Store::Factory.create :marshalling => true store.instance_variable_get(:@serializer).must_equal(Marshal) store.instance_variable_get(:@options)[:raw].must_equal(false) end after do $stderr = @original_stderr $stdout = @original_stdout end end it "should instantiate a Redis::DistributedStore store" do store = Redis::Store::Factory.create( { :host => "localhost", :port => 6379 }, { :host => "localhost", :port => 6380 } ) store.must_be_kind_of(Redis::DistributedStore) store.nodes.map { |node| node.to_s }.must_equal([ "Redis Client connected to localhost:6379 against DB 0", "Redis Client connected to localhost:6380 against DB 0", ]) end end describe "when given a String" do it "uses specified host" do store = Redis::Store::Factory.create "redis://127.0.0.1" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0") end it "uses specified port" do store = Redis::Store::Factory.create "redis://127.0.0.1:6380" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 0") end it "uses specified scheme" do store = Redis::Store::Factory.create "rediss://127.0.0.1:6380" store.instance_variable_get(:@client).scheme.must_equal('rediss') end it "correctly defaults to redis:// when relative scheme specified" do store = Redis::Store::Factory.create "//127.0.0.1:6379" store.instance_variable_get(:@client).scheme.must_equal('redis') end it "uses specified path" do store = Redis::Store::Factory.create "unix:///var/run/redis.sock" store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0") end it "uses specified db" do store = Redis::Store::Factory.create "redis://127.0.0.1:6380/13" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 13") end it "uses specified namespace" do store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0/theplaylist" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end it "uses specified via query namespace" do store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0?namespace=theplaylist" store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end it "uses specified namespace with path" do store = Redis::Store::Factory.create "unix:///var/run/redis.sock?db=2&namespace=theplaylist" store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 2 with namespace theplaylist") end it "uses specified password" do store = Redis::Store::Factory.create "redis://:secret@127.0.0.1:6379/0/theplaylist" store.instance_variable_get(:@client).password.must_equal("secret") end it 'uses specified password with special characters' do store = Redis::Store::Factory.create 'redis://:pwd%40123@127.0.0.1:6379/0/theplaylist' store.instance_variable_get(:@client).password.must_equal('pwd@123') end it 'uses empty password' do store = Redis::Store::Factory.create 'redis://:@127.0.0.1:6379/0/theplaylist' store.instance_variable_get(:@client).password.must_equal('') end it 'uses nil password' do store = Redis::Store::Factory.create 'redis://127.0.0.1:6379/0/theplaylist' assert_nil(store.instance_variable_get(:@client).password) end it "correctly uses specified ipv6 host" do store = Redis::Store::Factory.create "redis://[::1]:6380" store.to_s.must_equal("Redis Client connected to [::1]:6380 against DB 0") store.instance_variable_get('@options')[:host].must_equal("::1") end it "instantiates Redis::DistributedStore" do store = Redis::Store::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380" store.must_be_kind_of(Redis::DistributedStore) store.nodes.map { |node| node.to_s }.must_equal([ "Redis Client connected to 127.0.0.1:6379 against DB 0", "Redis Client connected to 127.0.0.1:6380 against DB 0", ]) end end describe 'when given host Hash and options Hash' do it 'instantiates Redis::Store and merges options' do store = Redis::Store::Factory.create( { :host => '127.0.0.1', :port => '6379' }, { :namespace => 'theplaylist' } ) end it 'instantiates Redis::DistributedStore and merges options' do store = Redis::Store::Factory.create( { :host => '127.0.0.1', :port => '6379' }, { :host => '127.0.0.1', :port => '6380' }, { :namespace => 'theplaylist' } ) store.nodes.map { |node| node.to_s }.must_equal([ "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist", "Redis Client connected to 127.0.0.1:6380 against DB 0 with namespace theplaylist" ]) end end describe 'when given host String and options Hash' do it 'instantiates Redis::Store and merges options' do store = Redis::Store::Factory.create "redis://127.0.0.1", :namespace => 'theplaylist' store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end it 'instantiates Redis::DistributedStore and merges options' do store = Redis::Store::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380", :namespace => 'theplaylist' store.nodes.map { |node| node.to_s }.must_equal([ "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist", "Redis Client connected to 127.0.0.1:6380 against DB 0 with namespace theplaylist", ]) end it 'instantiates Redis::Store and sets namespace from String' do store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0/theplaylist", :expire_after => 5 store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist") end end end end redis-store-1.9.0/test/redis/store/namespace_test.rb0000644000004100000410000002237513704151265022567 0ustar www-datawww-datarequire 'test_helper' describe "Redis::Store::Namespace" do def setup @namespace = "theplaylist" @store = Redis::Store.new :namespace => @namespace, :serializer => nil @client = @store.instance_variable_get(:@client) @rabbit = "bunny" @default_store = Redis::Store.new @other_namespace = 'other' @other_store = Redis::Store.new :namespace => @other_namespace end def teardown @store.flushdb @store.quit @default_store.flushdb @default_store.quit @other_store.flushdb @other_store.quit end it "only decorates instances that need to be namespaced" do store = Redis::Store.new client = store.instance_variable_get(:@client) client.expects(:call).with([:get, "rabbit"]) store.get("rabbit") end it "doesn't namespace a key which is already namespaced" do @store.send(:interpolate, "#{@namespace}:rabbit").must_equal("#{@namespace}:rabbit") end it "should only delete namespaced keys" do @default_store.set 'abc', 'cba' @store.set 'def', 'fed' @store.flushdb @store.get('def').must_be_nil @default_store.get('abc').must_equal('cba') end it 'should allow to change namespace on the fly' do @default_store.set 'abc', 'cba' @other_store.set 'foo', 'bar' @default_store.keys.sort.must_equal ['abc', 'other:foo'] @default_store.with_namespace(@other_namespace) do @default_store.keys.must_equal ['foo'] @default_store.get('foo').must_equal('bar') end end it "should not try to delete missing namespaced keys" do empty_store = Redis::Store.new :namespace => 'empty' empty_store.flushdb empty_store.keys.must_be_empty end it "should work with dynamic namespace" do $ns = "ns1" dyn_store = Redis::Store.new :namespace => -> { $ns } dyn_store.set 'key', 'x' $ns = "ns2" dyn_store.set 'key', 'y' $ns = "ns3" dyn_store.set 'key', 'z' dyn_store.flushdb r3 = dyn_store.get 'key' $ns = "ns2" r2 = dyn_store.get 'key' $ns = "ns1" r1 = dyn_store.get 'key' r1.must_equal('x') && r2.must_equal('y') && r3.must_be_nil end it "namespaces setex and ttl" do @store.flushdb @other_store.flushdb @store.setex('foo', 30, 'bar') @store.ttl('foo').must_be_close_to(30) @store.get('foo').must_equal('bar') @other_store.ttl('foo').must_equal(-2) @other_store.get('foo').must_be_nil end describe 'method calls' do let(:store) { Redis::Store.new :namespace => @namespace, :serializer => nil } let(:client) { store.instance_variable_get(:@client) } it "should namespace get" do client.expects(:call).with([:get, "#{@namespace}:rabbit"]).once store.get("rabbit") end it "should namespace set" do client.expects(:call).with([:set, "#{@namespace}:rabbit", @rabbit]) store.set "rabbit", @rabbit end it "should namespace setnx" do client.expects(:call).with([:setnx, "#{@namespace}:rabbit", @rabbit]) store.setnx "rabbit", @rabbit end it "should namespace del with single key" do client.expects(:call).with([:del, "#{@namespace}:rabbit"]) store.del "rabbit" end it "should namespace del with multiple keys" do client.expects(:call).with([:del, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]) store.del "rabbit", "white_rabbit" end it "should namespace keys" do store.set "rabbit", @rabbit store.keys("rabb*").must_equal [ "rabbit" ] end it "should namespace scan when a pattern is given" do store.set "rabbit", @rabbit cursor = "0" keys = [] begin cursor, matched_keys = store.scan(cursor, match: "rabb*") keys = keys.concat(matched_keys) unless matched_keys.empty? end until cursor == "0" keys.must_equal [ "rabbit" ] end it "should namespace exists" do client.expects(:call).with([:exists, "#{@namespace}:rabbit"]) store.exists "rabbit" end it "should namespace incrby" do client.expects(:call).with([:incrby, "#{@namespace}:counter", 1]) store.incrby "counter", 1 end it "should namespace decrby" do client.expects(:call).with([:decrby, "#{@namespace}:counter", 1]) store.decrby "counter", 1 end it "should namespace mget" do client.expects(:call).with([:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]).returns(%w[ foo bar ]) store.mget "rabbit", "white_rabbit" do |result| result.must_equal(%w[ foo bar ]) end end it "should namespace mapped_mget" do client.expects(:process).with([[:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]]).returns(%w[ foo bar ]) result = store.mapped_mget "rabbit", "white_rabbit" result.keys.must_equal %w[ rabbit white_rabbit ] result["rabbit"].must_equal "foo" result["white_rabbit"].must_equal "bar" end it "should namespace expire" do client.expects(:call).with([:expire, "#{@namespace}:rabbit", 60]).once store.expire("rabbit", 60) end it "should namespace ttl" do client.expects(:call).with([:ttl, "#{@namespace}:rabbit"]).once store.ttl("rabbit") end it "should namespace watch" do client.expects(:call).with([:watch, "#{@namespace}:rabbit"]).once store.watch("rabbit") end it "wraps flushdb with appropriate KEYS * calls" do client.expects(:call).with([:flushdb]).never client.expects(:call).with([:keys, "#{@namespace}:*"]).once.returns(["rabbit"]) client.expects(:call).with([:del, "#{@namespace}:rabbit"]).once store.flushdb end it "skips flushdb wrapping if the namespace is nil" do client.expects(:call).with([:flushdb]) client.expects(:call).with([:keys]).never store.with_namespace(nil) do store.flushdb end end it "should namespace hdel" do client.expects(:call).with([:hdel, "#{@namespace}:rabbit", "key1", "key2"]).once store.hdel("rabbit", "key1", "key2") end it "should namespace hget" do client.expects(:call).with([:hget, "#{@namespace}:rabbit", "key"]).once store.hget("rabbit", "key") end it "should namespace hgetall" do client.expects(:call).with([:hgetall, "#{@namespace}:rabbit"]).once store.hgetall("rabbit") end it "should namespace hexists" do client.expects(:call).with([:hexists, "#{@namespace}:rabbit", "key"]).once results = store.hexists("rabbit", "key") end it "should namespace hincrby" do client.expects(:call).with([:hincrby, "#{@namespace}:rabbit", "key", 1]).once store.hincrby("rabbit", "key", 1) end it "should namespace hincrbyfloat" do client.expects(:call).with([:hincrby, "#{@namespace}:rabbit", "key", 1.5]).once store.hincrby("rabbit", "key", 1.5) end it "should namespace hkeys" do client.expects(:call).with([:hkeys, "#{@namespace}:rabbit"]) store.hkeys("rabbit") end it "should namespace hlen" do client.expects(:call).with([:hlen, "#{@namespace}:rabbit"]) store.hlen("rabbit") end it "should namespace hmget" do client.expects(:call).with([:hmget, "#{@namespace}:rabbit", "key1", "key2"]) store.hmget("rabbit", "key1", "key2") end it "should namespace hmset" do client.expects(:call).with([:hmset, "#{@namespace}:rabbit", "key", @rabbit]) store.hmset("rabbit", "key", @rabbit) end it "should namespace hset" do client.expects(:call).with([:hset, "#{@namespace}:rabbit", "key", @rabbit]) store.hset("rabbit", "key", @rabbit) end it "should namespace hsetnx" do client.expects(:call).with([:hsetnx, "#{@namespace}:rabbit", "key", @rabbit]) store.hsetnx("rabbit", "key", @rabbit) end it "should namespace hvals" do client.expects(:call).with([:hvals, "#{@namespace}:rabbit"]) store.hvals("rabbit") end it "should namespace hscan" do client.expects(:call).with([:hscan, "#{@namespace}:rabbit", 0]) store.hscan("rabbit", 0) end it "should namespace hscan_each with block" do client.call([:hset, "#{@namespace}:rabbit", "key1", @rabbit]) client.expects(:call).with([:hscan, "#{@namespace}:rabbit", 0]).returns(["0", ["key1"]]) results = [] store.hscan_each("rabbit") do |key| results << key end results.must_equal(["key1"]) end it "should namespace hscan_each without block" do client.call([:hset, "#{@namespace}:rabbit", "key1", @rabbit]) client.expects(:call).with([:hscan, "#{@namespace}:rabbit", 0]).returns(["0", ["key1"]]) results = store.hscan_each("rabbit").to_a results.must_equal(["key1"]) end it "should namespace zincrby" do client.expects(:call).with([:zincrby, "#{@namespace}:rabbit", 1.0, "member"]) store.zincrby("rabbit", 1.0, "member") end it "should namespace zscore" do client.expects(:call).with([:zscore, "#{@namespace}:rabbit", "member"]) store.zscore("rabbit", "member") end it "should namespace zadd" do client.expects(:call).with([:zadd, "#{@namespace}:rabbit", 1.0, "member"]) store.zadd("rabbit", 1.0, "member") end it "should namespace zrem" do client.expects(:call).with([:zrem, "#{@namespace}:rabbit", "member"]) store.zrem("rabbit", "member") end end end redis-store-1.9.0/test/redis/store/redis_version_test.rb0000644000004100000410000000145013704151265023475 0ustar www-datawww-datarequire 'test_helper' describe "Redis::RedisVersion" do def setup @store = Redis::Store.new end def teardown @store.quit end describe '#redis_version' do it 'returns redis version' do @store.redis_version.to_s.must_match(/^\d{1}\.\d{1,}\.\d{1,}$/) end end describe '#supports_redis_version?' do it 'returns true if redis version is greater or equal to required version' do @store.stubs(:redis_version).returns('2.8.19') @store.supports_redis_version?('2.6.0').must_equal(true) @store.supports_redis_version?('2.8.19').must_equal(true) @store.supports_redis_version?('2.8.20').must_equal(false) @store.supports_redis_version?('2.9.0').must_equal(false) @store.supports_redis_version?('3.0.0').must_equal(false) end end end redis-store-1.9.0/test/redis/store/version_test.rb0000644000004100000410000000021613704151265022306 0ustar www-datawww-datarequire 'test_helper' describe Redis::Store::VERSION do it 'returns current version' do Redis::Store::VERSION.wont_equal nil end end redis-store-1.9.0/test/redis/store/ttl_test.rb0000644000004100000410000000745413704151265021437 0ustar www-datawww-datarequire 'test_helper' class MockRedis def initialize @sets = [] @setexes = [] @setnxes = [] @expires = [] end def set(*a) @sets << a end def has_set?(*a) @sets.include?(a) end def setex(*a) @setexes << a end def has_setex?(*a) @setexes.include?(a) end def setnx(*a) @setnxes << a end def has_setnx?(*a) @setnxes.include?(a) end def multi(&block) instance_eval do def setnx(*a) @setnxes << a end block.call end end alias_method :pipelined, :multi def expire(*a) @expires << a end def has_expire?(*a) @expires.include?(a) end end class MockTtlStore < MockRedis include Redis::Store::Ttl end describe MockTtlStore do let(:key) { 'hello' } let(:mock_value) { 'value' } let(:options) { { :expire_after => 3600 } } let(:redis) { MockTtlStore.new } describe '#set' do describe 'without options' do it 'must call super with key and value' do redis.set(key, mock_value) redis.has_set?(key, mock_value, nil).must_equal true end end describe 'with options' do it 'must call setex with proper expiry and set raw to true' do redis.set(key, mock_value, options) redis.has_setex?(key, options[:expire_after], mock_value, :raw => true).must_equal true end end describe 'with nx and ex option' do it 'must call super with key and value and options' do set_options = { nx: true, ex: 3600 } redis.set(key, mock_value, set_options) redis.has_set?(key, mock_value, set_options).must_equal true end end end describe '#setnx' do describe 'without expiry' do it 'must call super with key and value' do redis.setnx(key, mock_value) redis.has_setnx?(key, mock_value) end it 'must not call expire' do redis.expects(:expire).never redis.setnx(key, mock_value) end end describe 'with expiry' do it 'uses the mutli command to chain commands' do redis.expects(:multi) redis.setnx(key, mock_value, options) end it 'must call setnx with key and value and set raw to true' do redis.setnx(key, mock_value, options) redis.has_setnx?(key, mock_value, :raw => true).must_equal true end it 'must call expire' do redis.setnx(key, mock_value, options) redis.has_expire?(key, options[:expire_after]).must_equal true end describe 'avoiding multi commands' do let(:options) { { :expire_after => 3600, :avoid_multi_commands => true } } it 'uses the redis pipelined feature to chain commands' do redis.expects(:pipelined) redis.setnx(key, mock_value, options) end it 'must call setnx with key and value and set raw to true' do redis.setnx(key, mock_value, options) redis.has_setnx?(key, mock_value, :raw => true).must_equal true end it 'must call expire' do redis.setnx(key, mock_value, options) redis.has_expire?(key, options[:expire_after]).must_equal true end end describe 'using a redis cluster' do let(:options) { { :expire_after => 3600, :cluster => %w[redis://127.0.0.1:6379/0] } } it 'uses the redis pipelined feature to chain commands' do redis.expects(:pipelined) redis.setnx(key, mock_value, options) end it 'must call setnx with key and value and set raw to true' do redis.setnx(key, mock_value, options) redis.has_setnx?(key, mock_value, :raw => true).must_equal true end it 'must call expire' do redis.setnx(key, mock_value, options) redis.has_expire?(key, options[:expire_after]).must_equal true end end end end end redis-store-1.9.0/test/redis/store/serialization_test.rb0000644000004100000410000001311513704151265023500 0ustar www-datawww-datarequire 'test_helper' describe "Redis::Serialization" do def setup @store = Redis::Store.new serializer: Marshal @rabbit = OpenStruct.new :name => "bunny" @white_rabbit = OpenStruct.new :color => "white" @store.set "rabbit", @rabbit @store.del "rabbit2" end def teardown @store.flushdb @store.quit end it "unmarshals on get" do @store.get("rabbit").must_equal(@rabbit) end it "marshals on set" do @store.set "rabbit", @white_rabbit @store.get("rabbit").must_equal(@white_rabbit) end it "marshals on multi set" do @store.mset("rabbit", @white_rabbit, "rabbit2", @rabbit) @store.get("rabbit").must_equal(@white_rabbit) @store.get("rabbit2").must_equal(@rabbit) end if RUBY_VERSION.match /1\.9/ it "doesn't unmarshal on get if raw option is true" do @store.get("rabbit", :raw => true).must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF") end else it "doesn't unmarshal on get if raw option is true" do @store.get("rabbit", :raw => true).must_include("\x04\bU:\x0FOpenStruct{\x06:\tname") end end it "doesn't marshal set if raw option is true" do @store.set "rabbit", @white_rabbit, :raw => true @store.get("rabbit", :raw => true).must_equal(%(#)) end it "doesn't marshal multi set if raw option is true" do @store.mset("rabbit", @white_rabbit, "rabbit2", @rabbit, :raw => true) @store.get("rabbit", :raw => true).must_equal(%(#)) @store.get("rabbit2", :raw => true).must_equal(%(#)) end it "doesn't unmarshal if get returns an empty string" do @store.set "empty_string", "" @store.get("empty_string").must_equal("") # TODO use a meaningful Exception # lambda { @store.get("empty_string").must_equal("") }.wont_raise Exception end it "doesn't set an object if already exist" do @store.setnx "rabbit", @white_rabbit @store.get("rabbit").must_equal(@rabbit) end it "marshals on set unless exists" do @store.setnx "rabbit2", @white_rabbit @store.get("rabbit2").must_equal(@white_rabbit) end it "doesn't marshal on set unless exists if raw option is true" do @store.setnx "rabbit2", @white_rabbit, :raw => true @store.get("rabbit2", :raw => true).must_equal(%(#)) end it "marshals on set expire" do @store.setex "rabbit2", 1, @white_rabbit @store.get("rabbit2").must_equal(@white_rabbit) sleep 2 @store.get("rabbit2").must_be_nil end it "marshals setex (over a distributed store)" do @store = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ] @store.setex "rabbit", 50, @white_rabbit @store.get("rabbit").must_equal(@white_rabbit) end it "doesn't marshal setex if raw option is true (over a distributed store)" do @store = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ] @store.setex "rabbit", 50, @white_rabbit, :raw => true @store.get("rabbit", :raw => true).must_equal(%(#)) end it "unmarshals on multi get" do @store.set "rabbit2", @white_rabbit @store.mget "rabbit", "rabbit2" do |rabbits| rabbit, rabbit2 = rabbits rabbits.length.must_equal(2) rabbit.must_equal(@rabbit) rabbit2.must_equal(@white_rabbit) end end it "unmarshals on mapped_mget" do @store.set "rabbit2", @white_rabbit result = @store.mapped_mget("rabbit", "rabbit2") result.keys.must_equal %w[ rabbit rabbit2 ] result["rabbit"].must_equal @rabbit result["rabbit2"].must_equal @white_rabbit end if RUBY_VERSION.match /1\.9/ it "doesn't unmarshal on multi get if raw option is true" do @store.set "rabbit2", @white_rabbit @store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2| rabbit.must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF") rabbit2.must_equal("\x04\bU:\x0FOpenStruct{\x06:\ncolorI\"\nwhite\x06:\x06EF") end end else it "doesn't unmarshal on multi get if raw option is true" do @store.set "rabbit2", @white_rabbit @store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2| rabbit.must_include("\x04\bU:\x0FOpenStruct{\x06:\tname") rabbit2.must_include("\x04\bU:\x0FOpenStruct{\x06:\ncolor") end end end describe "binary safety" do it "marshals objects" do utf8_key = [51339].pack("U*") ascii_rabbit = OpenStruct.new(:name => [128].pack("C*")) @store.set(utf8_key, ascii_rabbit) @store.get(utf8_key).must_equal(ascii_rabbit) end it "gets and sets raw values" do utf8_key = [51339].pack("U*") ascii_string = [128].pack("C*") @store.set(utf8_key, ascii_string, :raw => true) @store.get(utf8_key, :raw => true).bytes.to_a.must_equal(ascii_string.bytes.to_a) end it "marshals objects on setnx" do utf8_key = [51339].pack("U*") ascii_rabbit = OpenStruct.new(:name => [128].pack("C*")) @store.del(utf8_key) @store.setnx(utf8_key, ascii_rabbit) @store.get(utf8_key).must_equal(ascii_rabbit) end it "gets and sets raw values on setnx" do utf8_key = [51339].pack("U*") ascii_string = [128].pack("C*") @store.del(utf8_key) @store.setnx(utf8_key, ascii_string, :raw => true) @store.get(utf8_key, :raw => true).bytes.to_a.must_equal(ascii_string.bytes.to_a) end end if defined?(Encoding) end redis-store-1.9.0/test/redis/distributed_store_test.rb0000644000004100000410000000643413704151265023233 0ustar www-datawww-datarequire 'test_helper' describe "Redis::DistributedStore" do def setup @dmr = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ] @rabbit = OpenStruct.new :name => "bunny" @white_rabbit = OpenStruct.new :color => "white" @dmr.set "rabbit", @rabbit end def teardown @dmr.ring.nodes.each { |server| server.flushdb } end it "accepts connection params" do dmr = Redis::DistributedStore.new [ :host => "localhost", :port => "6380", :db => "1" ] dmr.ring.nodes.size == 1 mr = dmr.ring.nodes.first mr.to_s.must_equal("Redis Client connected to localhost:6380 against DB 1") end it "forces reconnection" do @dmr.nodes.each do |node| node.expects(:reconnect) end @dmr.reconnect end it "sets an object" do @dmr.set "rabbit", @white_rabbit @dmr.get("rabbit").must_equal(@white_rabbit) end it "gets an object" do @dmr.get("rabbit").must_equal(@rabbit) end it "mget" do @dmr.set "rabbit2", @white_rabbit begin @dmr.mget "rabbit", "rabbit2" do |rabbits| rabbit, rabbit2 = rabbits rabbits.length.must_equal(2) rabbit.must_equal(@rabbit) rabbit2.must_equal(@white_rabbit) end rescue Redis::Distributed::CannotDistribute # Not supported on redis-rb < 4, and hence Ruby < 2.2. end end it "mapped_mget" do @dmr.set "rabbit2", @white_rabbit begin result = @dmr.mapped_mget("rabbit", "rabbit2") result.keys.must_equal %w[ rabbit rabbit2 ] result["rabbit"].must_equal @rabbit result["rabbit2"].must_equal @white_rabbit rescue Redis::Distributed::CannotDistribute # Not supported on redis-rb < 4, and hence Ruby < 2.2. end end it "passes through ring replica options" do dmr = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ], replicas: 1024 dmr.ring.replicas.must_equal 1024 end it "uses a custom ring object" do my_ring = Redis::HashRing.new dmr = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ], ring: my_ring dmr.ring.must_equal my_ring dmr.ring.nodes.length.must_equal 2 end describe '#redis_version' do it 'returns redis version' do @dmr.nodes.first.expects(:redis_version) @dmr.redis_version end end describe '#supports_redis_version?' do it 'returns redis version' do @dmr.nodes.first.expects(:supports_redis_version?).with('2.8.0') @dmr.supports_redis_version?('2.8.0') end end describe "namespace" do it "uses namespaced key" do @dmr = Redis::DistributedStore.new [ { :host => "localhost", :port => "6380", :db => 0 }, { :host => "localhost", :port => "6381", :db => 0 } ], :namespace => "theplaylist" @dmr.expects(:node_for).with("theplaylist:rabbit").returns(@dmr.nodes.first) @dmr.get "rabbit" end end end redis-store-1.9.0/test/redis/store_test.rb0000644000004100000410000000326013704151265020623 0ustar www-datawww-datarequire 'test_helper' describe Redis::Store do def setup @store = Redis::Store.new @client = @store.instance_variable_get(:@client) end def teardown @store.flushdb @store.quit end it "returns useful informations about the server" do @store.to_s.must_equal("Redis Client connected to #{@client.host}:#{@client.port} against DB #{@client.db}") end it "must force reconnection" do @client.expects(:reconnect) @store.reconnect end describe '#set' do describe 'with expiry' do let(:options) { { :expire_after => 3600 } } it 'must not double marshall' do Marshal.expects(:dump).once @store.set('key', 'value', options) end end describe 'with ex and nx' do let(:key) { 'key' } let(:mock_value) { 'value' } let(:options) { { nx: true, ex: 3600 } } it 'must pass on options' do Marshal.expects(:dump).times(4) # without options no ex or nx will be set @store.del(key) @store.set(key, mock_value, {}).must_equal 'OK' @store.set(key, mock_value, {}).must_equal 'OK' @store.ttl(key).must_equal -1 # with ex and nx options, the key can only be set once and a ttl will be set @store.del(key) @store.set(key, mock_value, options).must_equal true @store.set(key, mock_value, options).must_equal false @store.ttl(key).must_equal 3600 end end end describe '#setnx' do describe 'with expiry' do let(:options) { { :expire_after => 3600 } } it 'must not double marshall' do Marshal.expects(:dump).once @store.setnx('key', 'value', options) end end end end redis-store-1.9.0/test/test_helper.rb0000644000004100000410000000072013704151265017636 0ustar www-datawww-datarequire 'bundler/setup' require 'minitest/autorun' require 'mocha/setup' require 'redis' require 'redis-store' require 'pry' $DEBUG = ENV["DEBUG"] === "true" Redis::DistributedStore.send(:class_variable_set, :@@timeout, 30) # http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/ module Kernel def suppress_warnings original_verbosity = $VERBOSE $VERBOSE = nil result = yield $VERBOSE = original_verbosity result end end redis-store-1.9.0/CODEOWNERS0000644000004100000410000000001113704151265015400 0ustar www-datawww-data* @tubbo redis-store-1.9.0/README.md0000644000004100000410000000351313704151265015276 0ustar www-datawww-data# Redis stores for Ruby frameworks __Redis Store__ provides a full set of stores (*Cache*, *I18n*, *Session*, *HTTP Cache*) for modern Ruby frameworks like: __Ruby on Rails__, __Sinatra__, __Rack__, __Rack::Cache__ and __I18n__. It supports object marshalling, timeouts, single or multiple nodes, and namespaces. Please check the *README* file of each gem for usage and installation guidelines. ## Redis Installation ### Option 1: Homebrew MacOS X users should use [Homebrew](https://github.com/mxcl/homebrew) to install Redis: ```shell brew install redis ``` ### Option 2: From Source Download and install Redis from [the download page](http://redis.io//download) and follow the instructions. ## Running tests ```ruby git clone git://github.com/redis-store/redis-store.git cd redis-store bundle install bundle exec rake ``` If you are on **Snow Leopard** you have to run `env ARCHFLAGS="-arch x86_64" ruby ci/run.rb` ## Contributors https://github.com/redis-store/redis-store/graphs/contributors ## Versioning The **redis-store** family of gems uses [Semantic Versioning](http://semver.org), meaning gems depending on **redis-store** can be reliably inclusive of any version between the current and the next major. We recommend the following dependency in your library's gemspec: ```ruby s.add_dependency 'redis-store', '>= 1.4', '< 2' ``` ## Status [![Gem Version](https://badge.fury.io/rb/redis-store.svg)](http://badge.fury.io/rb/redis-store) [![Build Status](https://secure.travis-ci.org/redis-store/redis-store.svg?branch=master)](http://travis-ci.org/redis-store/redis-store?branch=master) [![Code Climate](https://codeclimate.com/github/redis-store/redis-store.svg)](https://codeclimate.com/github/redis-store/redis-store) ## Copyright 2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license. redis-store-1.9.0/gemfiles/0000755000004100000410000000000013704151265015610 5ustar www-datawww-dataredis-store-1.9.0/gemfiles/redis_4_0_x.gemfile0000644000004100000410000000016413704151265021242 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "redis", "~> 4.0.0" gemspec path: "../" redis-store-1.9.0/gemfiles/redis_4_x.gemfile0000644000004100000410000000016213704151265021021 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "redis", "~> 4.0" gemspec path: "../" redis-store-1.9.0/gemfiles/redis_4_1_x.gemfile0000644000004100000410000000016413704151265021243 0ustar www-datawww-data# This file was generated by Appraisal source "https://rubygems.org" gem "redis", "~> 4.1.0" gemspec path: "../" redis-store-1.9.0/CHANGELOG.md0000644000004100000410000005577513704151265015651 0ustar www-datawww-data# Changelog ## 1.9.0 Breaking Changes * As a factor of updates for Redis v4.2.x, support for Ruby 2.1 and 2.2 has been dropped. These Ruby versions are end-of-life anyway. Fixed * [Compatibility with Redis client v4.2.x](https://github.com/redis-store/redis-store/pull/333) Added * [Support for edge Ruby's keyword arguments](https://github.com/redis-store/redis-store/pull/334) ## 1.8.2 Breaking Changes * None Added * [Add namespace to zincrby and zscore](https://github.com/redis-store/redis-store/pull/323) * [Add namespace to zadd and zrem](https://github.com/redis-store/redis-store/pull/326) Fixed * None ## 1.8.1 Breaking Changes * None Added * None Fixed * [Add namespace to remaining hash methods](https://github.com/redis-store/redis-store/pull/321) ## 1.8.0 Breaking Changes * None Added * [Redis Cluster Support](https://github.com/redis-store/redis-store/pull/318) Fixed * None ## 1.6.0 Breaking Changes * None Added * [SSL/TLS Support with the rediss:// URI scheme](https://github.com/redis-store/redis-store/pull/306) * [Use Code Style Guide For New Contributions](https://github.com/redis-store/redis-store/pull/309) Fixed * None ## 1.5.0 Breaking Changes * None Added * [Support for Redis v4 and above](https://github.com/redis-store/redis-store/pull/292) * [Support for distributed mget/read_multi in Redis v4](https://github.com/redis-store/redis-store/pull/282) * [Tests for Namespace#flushdb](https://github.com/redis-store/redis-store/pull/299) * [Support for UNIX Socket path connections](https://github.com/redis-store/redis-store/pull/298) * [HashRing configuration for DistributedStore](https://github.com/redis-store/redis-store/pull/304) Fixed * [Inefficient use of KEYS when calling FLUSHDB without a namespace](https://github.com/redis-store/redis-store/pull/297) ## 1.4.1 Breaking Changes * None Added * [Support for Redis client library v4](https://github.com/redis-store/redis-store/issues/277) Fixed * None ## 1.4.0 Breaking Changes * None Added * Pluggable backend for serializing data in/out of Redis, eventually replacing `:marshalling` in v2. Fixed * Conventional `Marshal.dump` usage allowing potential security vulnerability (CVE-2017-1000248) ## 1.3.0 Breaking Changes * None Added * Add support for marshalling mset Fixed * Set :raw => true if marshalling * Forward new Hash, not nil, when options are unset ## 1.2.0 Breaking Changes * None Added * Allow changing namespaces on the fly * Begin testing against ruby 2.3.0 Fixed * Use batched deletes for flushdb with a namespace * pass set command options to redis * bump rbx 2 * fix setex marshalling for distributed store * changes to new url * :warning: shadowing outer local variable - key, pattern, value * :warning: `*' interpreted as argument prefix * Removed duplicated method ttl ## 1.1.7 Breaking Changes * None Added * Added redis_version and supports_redis_version? methods to Store and DistributedStore Fixed * Handle minor and patch version correctly as they may be multiple digits *1.1.6 (July 16, 2015)* https://github.com/redis-store/redis-store/compare/v1.1.5...v1.1.6 *1.1.5 (June 8, 2015)* https://github.com/redis-store/redis-store/compare/v1.1.4...v1.1.5 *1.1.4 (August 20, 2013)* * Bump version v1.1.4 * Release redis-rails 4.0.0 * Release redis-actionpack 4.0.0 * Release redis-activesupport 4.0.0 * Release redis-sinatra 1.4.0 * Release redis-rack-cache 1.2.2 * Release redis-i18n 0.6.5 * Release redis-rack 1.5.0 * New versions of the AS, AP and Rails gems [Alexey Vasiliev] * fix gems for Rails 4 [Alexey Vasiliev] * JRuby testing, remove 1.8.7 from tests (unsupported), fix some tests [Alexey Vasiliev] * Change configurations for the Rails dummy app. * use @default_options when calling @pool.set to avoid infinite-ttl session leak, fixes #179 [Sean Walbran] * Test against Rails 4 not master [Rafael Mendonça França] * Make possible to work with rack 1.5 [Rafael Mendonça França] * Add support pluralization support to Redis i18n [Joachim Filip Ignacy Bartosik] * Fixes #189 [Fabrizio Regini] * fix CI script [Fabrizio Regini] * Redis::Factory => Redis::Store::Factory * Added performance warning, per #186. [Brian P O'Rourke] * Fix: read_multi was returning ActiveSupport::Cache::Entry instead of deserialized value [Miles D Goodings] * Fix: can't modify frozen String errors in Redis::Store::Marshalling [Miles D Goodings] * Add expire method and tests [Han Chang] * Run against Rails 4 and Ruby 2.0 [Steve Klabnik] * Clean up README files to be more clear and helpful [Matthew Beale] * Bundler 1.2.0 is now out, don't require the RC on the CI server * Relaxed the requirement for the Redis gem (>= 2.2). Updated development dependencies. * Ensure Redis 2.6 compat *1.1.3 (October 6, 2012)* * Bump version v1.1.3 * Invoke namespaced commands only when keys are present. *1.1.2 (September 4, 2012)* * Bump version v1.1.2 [Matt Horan] * Override flushdb for namespaced datastore [Gregory Marcilhacy] *1.1.1 (June 26, 2012)* * Bump version v1.1.1 * README, CHANGELOG * Bumped redis-sinatra 1.3.3 * Bumped redis-rack 1.4.2 * Bumped redis-i18n 0.6.1 * Relaxing dependencies * Relax requirement on redis (use >= 2.2.0) Because resque still depends on redis 2.x and sidekiq on redis 3.x, using >= 2.2.0 instead of ~> 3.0.0 allows compatibility with both. [Lukas Westermann] * Use default value for port, otherwise factory_test.rb:65 fails (port = 0) [Lukas Westermann] * Use redis 3.x [Lukas Westermann] * Adding examples for rails cache store config with URLs [aliix] * Bumped redis-rack-cache 1.2 * Bump: [Matt Horan] - redis-rails 3.2.3 - redis-actionpack 3.2.3 - redis-activesupport 3.2.3 * Loosen actionpack version requirement for possible Rails 3.2.3 compatibility [Filip Tepper] * Add Rails 3.2.2 support for redis-actionpack, redis-activesupport, redis-rails [Jack Chu] * Bumped redis-rack 1.4.1 * Bumped: - redis-rack 1.4.0 - redis-activesupport 3.2.1 - redis-actionpack 3.2.1 - redis-rails 3.2.1 * Bump redis-sinatra 1.3.2 *1.1.0 (February 14, 2012)* * Bump version v1.1.0 * Prepare stable releases - redis-store 1.1.0 - redis-actionpack 3.1.3 - redis-activesupport 3.1.3 - redis-i18n 0.6.0 - redis-rack-cache 1.1 - redis-rack 1.3.5 - redis-rails 3.1.3 - redis-sinatra 1.3.1 * Replace minitest-rails with mini_specunit [Matt Horan] * Bumped: [Matt Horan] - redis-actionpack 3.1.3.rc4 - redis-activesupport 3.1.3.rc2 - redis-i18n 0.6.0.rc2 - redis-rack-cache 1.1.rc3 - redis-rails 3.1.3.rc4 - redis-sinatra 1.3.1.rc2 * Remove redis-actionpack dependency on redis-rack-cache [Matt Horan] *1.1.0 [rc2] (February 3, 2012)* * Bump version v1.1.0.rc2 * Bumped: [Matt Horan] - redis-store 1.1.0.rc2 - redis-actionpack 3.1.3.rc3 - redis-rails 3.1.3.rc3 * README, CHANGELOG * Don't clobber :redis_server if provided to ActionDispatch::Session::RedisStore [Matt Horan] * Support :servers option to ActionDispatch::Session::RedisStore [Matt Horan] * Add missing assertions [Matt Horan] * Integrate against a distributed Redis store [Matt Horan] * Remove duplicated logic for merging default Redis server with options [Matt Horan] * Rename ActionDispatch::Session::RedisSessionStore to RedisStore in keeping with documentation and MemCacheStore [Matt Horan] * Test auto-load of unloaded class [Matt Horan] * Replace assert_response with must_be [Matt Horan] * Pending upstream fix [Matt Horan] * Additional tests for rack-actionpack, borrowed from MemCacheStoreTest [Matt Horan] * Test redis-actionpack with dummy Rails application [Matt Horan] * Use Rack::Session::Redis API in RedisSessionStore [Matt Horan] * Quiet warnings [Matt Horan] * Remove superfluous tests [Matt Horan] * Cleanup Redis::Store::Ttl setnx and set tests with help from @mike-burns [Matt Horan] * Verify Ttl#setnx sets raw => true if expiry is provided [Matt Horan] * Fix redis-rack spec [Matt Horan] * Previous fix for double marshal just disabled expiry. Instead, call setnx from Ttl module with :raw => true so that Marshal.dump [Matt Horan] * Test and fix for double marshal [Matt Horan] * Cleanup Redis::Store::Ttl spec [Matt Horan] * Fix Redis::Rack version require [Matt Horan] * Redis::Store::Ttl extends Redis#set with TTL support [Matt Horan] * Specs for Redis::Store::Ttl [Matt Horan] * Bumped: - redis-rack-cache 1.1.rc2 - redis-actionpack 3.1.3.rc2 - redis-rails 3.1.3.rc2 * Ensure TTL is an integer - Rails cache returns a float when used with race_condition_ttl [Matt Williams] *1.1.0 [rc] (December 30, 2011)* * Bump version v1.1.0.rc * Prepare RCs * redis-store 1.1.0.rc * CHANGELOG * Use strict dependencies. * READMEs and Licenses * redis-actionpack now depends on redis-rack-cache * Redis::Factory.convert_to_redis_client_options => Redis::Factory.resolve. * Don't use autoload * Make redis-rack-cache tests to pass again * Target Rack::Cache 1.1 for redis-rack-cache * Target Rack 1.4.0 for redis-rack * Gemspecs, dependencies and versions * Make redis-rails tests to pass again * redis-actionpack dependencies * redis-activesupport dependencies * Fix for redis-rack tests * Fix for redis-activesupport tests * Make redis-sinatra tests to pass again * Make redis-actionpack tests to pass again * Install bundler 1.1 RC on travis-ci.org [Michael Klishin] * Make redis-rack tests to pass again * Added SETEX support to Interface and Marshalling * Make redis-i18n tests to pass again * Make redis-activesupport tests to pass again * More tests for redis-store core * Redis::Factory is created with general options and not the redis_server [Julien Kirch] * Moved README.md * Split gems in subdirectories * Moved everything under redis-store * Use bundler 1.1.rc * Better Ruby idiom on File.expand_path * Moved Rake test tasks into lib/tasks/redis.tasks.rb, in order to DRY Rake * Testing: Use relative paths when referring to pid files * Autoload modules * Moved Rake test tasks under lib/ in order to make them accessible to all * Let the Redis::DistributedStore test to pass * Let Redis Rake tasks to work again * Run tests without dtach * Switch from RSpec to MiniTest::Unit * Removed all the references to Rails, Merb, Sinatra, Rack, i18n, Rack::Session and Rack::Cache * Gemfile is now depending on the gemspec. Removed Jewler. *1.0.0 (September 1, 2011)* * Bump version v1.0.0 * Avoid encoding issues when sending strings to Redis. [Damian Janowski] * Fixed a bug that caused all the users to share the same session (with a session_id of 0 or 1) [Mathieu Ravaux] * ActiveSupport cache stores reply to read_multi with a hash, not an array. [Matt Griffin] * Rack::Session && Rack::Cache store can be created with options [aligo] * add destroy_session [aligo] * compatible with rails 3.1. rely on Rack::Session::Redis stores API. [aligo] * Fixed Marshalling semantic *1.0.0 [rc1] (June 5, 2011)* * Bump version v1.0.0.rc1 * Re-implement the delete_entry because it s needed by the ActiveSupport::Cache [Cyril Mougel] * Change readme documentation for rack-cache to use single redis database with namespace support per Redis maintainers recommendation [Travis D. Warlick, Jr.] * Rack-Cache entity and meta store base classes should use the Redis::Factory.convert_to_redis_client_options method for DRYness and for namespace support [Travis D. Warlick, Jr.] * Modify #fetch for cache stores to return the yielded value instead of OK [Rune Botten] * Minor revisions to Readme language and organization [Jeff Casimir] * Re-implement the delete_entry because it s needed by the ActiveSupport::Cache implementation in Rails 3 [Cyril Mougel] * Refactor delete_matched [Andrei Kulakov] *1.0.0 [beta5] (April 2, 2011)* * Bump version v1.0.0.beta5 * Introducing Rails.cache.reconnect, useful for Unicorn environments. Closes #21 * Namespaced i18n backend should strip namespace when lists available locales. Closes #62 * how to configure Redis session store in Sinatra [Christian von Kleist] * gracefully handle Connection Refused errors, allows database fall-back on fetch [Michael Kintzer] * Sinatra's API must have changed, its registered not register. [Michael D'Auria] *1.0.0 [beta4] (December 15, 2010)* * Bump version v1.0.0.beta4 * Force Rails cache store when ActiveSupport is detected * Make sure to accept options when :servers isn't passed * Always force session store loading when using Rails * Make it compatible with Rails 3 sessions store [Andre Medeiros] * Better Rails 3 detection [Andre Medeiros] * Added support for password in Redis URI resolution [Jacob Gyllenstierna] * fix deleting values from session hash [Calvin Yu] * Use defensive design when build options for a store * ActiveSupport cache store doesn't accept any argument in Rails 2 * Updated dependencies *1.0.0 [beta3] (September 10, 2010)* * Bump version v1.0.0.beta3 * Updated gemspec * Made compatible with Ruby 1.9.2 * Made compatible with Rails 3 * Making the redis-store rails session store compatible with Rails 2.3.9. [Aaron Gibralter] * Updated to v2.3.9 the development dependencies for Rails 2.x * Added password support * Set default URI string for Rack session store according to redis gem * Require redis:// scheme as mandatory part of URI string * Updated locked dependencies * Added namespace support for Redis::DistrubutedStore * Specs for Interface module * Moved a spec to reflect lib/ structure * Made specs run again with bundler-1.0.0.rc.2 * Prepare for bundler-1.0.0.rc.1 * Use tmp/ for Redis database dumps * README, gemspec * Lookup for scoped keys * Introducing I18n::Backend::Redis * Don't pollute Redis namespace. closes #16 * Don't look twice for Rails module * Fixed loading ActionDispatch::Session issue with Rails 3 * ActiveSupport cache now uses new Rails 3 namespace API * Let Rack::Cache entity store to use plain Redis client * CHANGELOG * Gemspec * Redis::DistributedMarshaled => Redis::DistributedStore * Extracted expiration logic in Redis::Ttl * Introducing Redis::Store and extracted marshalling logic into Redis::Marshalling * CHANGELOG * Gemspec * Removed superfluous specs. Documentation. * Made the specs pass with Ruby 1.9.2 and Rails 3 * Made the specs pass with Ruby 1.9.2 * Prepare specs for Ruby 1.9.2 * Made the specs pass for Rails 3 * Namespaced keys for ActiveSupport::Cache::RedisStore * Got RedisSessionStore working again with namespace * Delegate MarshaledClient#to_s decoration to Redis::Namespace * Redis::Namespace * Accept :namespace option when instantiate a store * Test against merb-1.1.0 for now * Updated Rake tasks for Redis installation * Advanced configurations for Rails in README. closes #8 * Locked gems * Changed the gemspec according to the new directories structure * Changed directories structure, according to the ActiveSupport loading policies * Typo in CHANGELOG *1.0.0 [beta2] (June 12, 2010)* * Bump version v1.0.0.beta2 * Added committers names to CHANGELOG * Added CHANGELOG * Rake namespace: redis_cluster => redis:cluster * Fixed Rails 3 failing spec * Added ActiveSupport::Cache::RedisStore#read_multi * Enabled notifications for ActiveSupport::Cache::RedisStore * Moved spec * Use consistent Rails 3 check in session store * Make sure of use top-level module * Updated Rails 2.x development dependencies *1.0.0 [beta1] (June 9, 2010)* * Bump version v1.0.0.beta1 * Made specs pass for Ruby 1.9.1 * Updated instructions to test against Rails 3.x * Updated copyright year * Prepare for v1.0.0.beta1 * Use Rails v3.0.0.beta4 * Require redis >= 2.0.0 gem in Gemfile * Updated instructions for Rails 2 session store * Added instructions for Rails 3 configuration * Check against Rails#version instead of Rails::VERSION::STRING * Added redis gem as dependency * Changed spec_helper.rb according to the new Rails 3 check * Fix the rails3 check [Bruno Michel] * Added bundler cleanup Rake task * Fixed ActiveSupport::Cache::RedisStore#fetch * Re-enabled redis:console Rake task * Don't use Rspec#have with ActiveSupport 3 * Fixed Rails 2 regression for ActiveSupport::Cache::RedisStore#delete_matched * Fixed issues for ActiveSupport::Cache::RedisStore #delete_matched, #read, #rwrite * Rails 3 namespace * Use Rails edge instead of 3.0.0.beta3 * Made the specs run again * Updated Gemfile development/test dependencies for rails3. * Updated README instructions * Updated test configuration files, according to redis-2.0.0-rc1 defaults * Made specs pass with redis-2.0.0 gem * Don't support the old redis-rb namespace * Import the whole redis-rb old Rake tasks * Updated redis-rb dependency *0.3.8 [Final] (May 21, 2010)* * Fixed gemspec executable issue * Updated .gemspec * Version bump to 0.3.8 * Started namespace migration for redis-2.0.0 * Merge branch 'master' of http://github.com/akahn/redis-store * Fixed dependency issues. [Brian Takita] * Removed methopara because it require ruby 1.9.1. [Brian Takita] * Merge branch 'master' of http://github.com/dsander/redis-store [Brian Takita] * Moved RedisSessionStore to rack session directory. [Brian Takita] * Got RedisSessionStore working with passing specs. [Brian Takita] * Using modified version of RedisSessionStore (http://github.com/mattmatt/redis-session-store). Still needs testing. [Brian Takita] * Using redis 1.0.5. [Brian Takita] * Ignoring gem files and gemspecs with a prefix. [Brian Takita] * Added git and jeweler to dependencies. [Brian Takita] * Ignoring .bundle and rubymine files. [Brian Takita] * Added ability to add a prefix to the gem name via the GEM_PREFIX environment variable. [Brian Takita] * Fixed marshalling issues with the new Redis api. Fixed redis-server configurations for the latest version of redis-server. Added redis_cluster:start and redis_cluster:stop rake tasks. Spec suite passes. [Brian Takita] * Fixed redis deprecation warnings. [Brian Takita] * Using redis 1.0.4. Loading redis.tasks.rb from redis gem using Bundler. Fixed redis test configurations. [Brian Takita] * Supports redis 1.0.5 [Dominik Sander] * Add Rack::Session::Redis usage for Sinatra to README [Alexander Kahn] * Updated development and testing dependencies * Made compatible with rack-cache-0.5.2 *0.3.7 [Final] (November 15, 2009)* * Version bump to 0.3.7 * Version bump to 0.3.7 * Updated spec instructions in README * Jeweler generated redis-store.gemspec * Removed no longer used Rake tasks. Added Gemcutter support via Jeweler. * Typo * Let Rcov task run with the Redis cluster started * Make spec suite pass again * README.textile -> README.md * Re-enabled Merb specs * Added *.rdb in .gitignore * Run detached Redis instances for spec suite * Start detached Redis server for specs * Added Gemfile, removed rubygems dependecy for testing. * Added *.swp to .gitignore * Added jeweler rake tasks * Make it work in classic Sinatra apps. [Dmitriy Timokhin] * Updated README with new instructions about redis-rb *0.3.6 [Final] (June 18, 2009)* * Prepare for v0.3.6 * Updated README with new version * Changed Redis config files for specs * Updated README instructions * New filelist in gemspec * Fixed typo in spec * Don't try to unmarshal empty strings * Running specs according to the DEBUG env var * Added specs for uncovered Merb Cache API * Added rcov Rake task * Fix README * Fix typo in README * Updated README instructions * Removed RedisError catching * Declaring for now RedisError in spec_helper.rb * Removed unnecessary classes * Fix specs for DistributedMarshaledRedis * Fix some specs * Made Server#notify_observers private * Ensure to select the correct database after the socket connection * Reverted socket pooling. Ensure to always return an active socket. * Lowering default timeout from 10 to 0.1 *0.3.5 [Final] (May 7, 2009)* * Prepare for v0.3.5 * Totally replace ezmobius-redis-rb Server implementation * Fixed default Server timeout to 1 second * Little refactoring * Ensure Server#active? always returns a boolean and never raise an exception * Made configurable connection pool timeout and size * Socket connection pooling * Updated README *0.3.0 [Final] (May 3, 2009)* * Prepare for v0.3.0 * README formatting issues * README formatting (again) * README formatting * Updated Rack::Session instructions for Sinatra * Make Rack::Session implementation working with Merb * Added instructions for Rack::Session * Expiration support for Rack::Session * Ensure to test Rails and Sinatra expiration implementations with both MarshaledRedis and DistrbutedMarshaledRedis * Expiration support for Merb::Cache * Use full qualified class names in specs. Minor spec fix. * Ported for foreword compatibility the expiration implementation from ezmobius/redis-rb * Little spec cleanup * Full support for Rack::Session * Extracted some logic into RedisFactory * Initial support for Rack::Session *0.2.0 [Final] (April 30, 2009)* * Prepare for v0.2.0 * Links in README * Maybe someday I will use the right formatting rules at first attempt * Still formatting README * Formatting for README * Updated instructions for Rack::Cache * Don't require any cache store if no Ruby framework is detected * Implemented EntityStore for Rack::Cache * Added REDIS constant for Rack::Cache::Metastore * MetaStore implementation for Rack::Cache *0.1.0 [Final] (April 30, 2009)* * Prepare for v0.1.0 * Sinatra cache support *0.0.3 [Final] (April 30, 2009)* * Prepare for v0.0.3 * Updated instructions for Merb * Hack for Merb cyclic dependency * Renaming main lib * Merb store #writable always returns true. Added pending test. * Merb store #fetch refactoring * Updated Redis installation instructions * Implemented #fetch for Merb store * Implemented #exists?, #delete and #delete_all for Merb cache store * Renamed project name in Rakefile * Updated project name in README * Updated README with Merb instructions * Changed name in gemspec * New gemspec * Initial cache store support for Merb * Moving files around * Don't complain about missing db in tmp/ *0.0.2 [Final] (April 16, 2009)* * Prepare for v0.0.2 * Updated file list in gemspec * Updated README instructions * Re-enabled spec for RedisStore#fetch * Update rdoc * Fix RedisStore#clear when use a cluster * Test RedisStore both with single server and with a cluster * Fix port in DistributedMarshaledRedis spec * Don't slave Redis cluster node * Changed Redis cluster configuration * Added configuration for Redis cluster * Use a distributed system if the store uses more than one server * Accept params for client connection *0.0.1 [Final] (April 11, 2009)* * Added :unless_exist option to #write * Added failing specs for :expires_in option * Made optional args compatible with the Cache interface * Implemented #delete_matched, #clear, #stats * Implemented #delete, #exist?, #increment, #decrement * Introduced RedisStore * Initial import redis-store-1.9.0/.rubocop.yml0000644000004100000410000000566213704151265016300 0ustar www-datawww-data--- AllCops: TargetRubyVersion: 2.4 # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop # to ignore them, so only the ones explicitly set in this file are enabled. DisabledByDefault: true Exclude: - '**/vendor/**/*' # Prefer &&/|| over and/or. Style/AndOr: Enabled: true # Do not use braces for hash literals when they are the last argument of a # method call. Style/BracesAroundHashParameters: Enabled: true EnforcedStyle: context_dependent # Align comments with method definitions. Layout/CommentIndentation: Enabled: true Layout/ElseAlignment: Enabled: true Layout/EmptyLineAfterMagicComment: Enabled: true # In a regular class definition, no empty lines around the body. Layout/EmptyLinesAroundClassBody: Enabled: true # In a regular method definition, no empty lines around the body. Layout/EmptyLinesAroundMethodBody: Enabled: true # In a regular module definition, no empty lines around the body. Layout/EmptyLinesAroundModuleBody: Enabled: true Layout/FirstParameterIndentation: Enabled: true # Method definitions after `private` or `protected` isolated calls need one # extra level of indentation. Layout/IndentationConsistency: Enabled: true EnforcedStyle: rails # Two spaces, no tabs (for indentation). Layout/IndentationWidth: Enabled: true Layout/LeadingCommentSpace: Enabled: true Layout/SpaceAfterColon: Enabled: true Layout/SpaceAfterComma: Enabled: true Layout/SpaceAroundEqualsInParameterDefault: Enabled: true Layout/SpaceAroundKeyword: Enabled: true Layout/SpaceAroundOperators: Enabled: true Layout/SpaceBeforeComma: Enabled: true Layout/SpaceBeforeFirstArg: Enabled: true Style/DefWithParentheses: Enabled: true # Defining a method with parameters needs parentheses. Style/MethodDefParentheses: Enabled: true # Use `foo {}` not `foo{}`. Layout/SpaceBeforeBlockBraces: Enabled: true # Use `foo { bar }` not `foo {bar}`. Layout/SpaceInsideBlockBraces: Enabled: true # Use `{ a: 1 }` not `{a:1}`. Layout/SpaceInsideHashLiteralBraces: Enabled: true Layout/SpaceInsideParens: Enabled: true # Detect hard tabs, no hard tabs. Layout/Tab: Enabled: true # Blank lines should not have any spaces. Layout/TrailingBlankLines: Enabled: true # No trailing whitespace. Layout/TrailingWhitespace: Enabled: true # Use quotes for string literals when they are enough. Style/UnneededPercentQ: Enabled: true # Align `end` with the matching keyword or starting expression except for # assignments, where it should be aligned with the LHS. Layout/EndAlignment: Enabled: true EnforcedStyleAlignWith: variable AutoCorrect: true # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg. Lint/RequireParentheses: Enabled: true Style/RedundantReturn: Enabled: true AllowMultipleReturnValues: true Style/Semicolon: Enabled: true AllowAsExpressionSeparator: true # Prefer Foo.method over Foo::method Style/ColonMethodCall: Enabled: true redis-store-1.9.0/Appraisals0000644000004100000410000000024713704151265016042 0ustar www-datawww-data appraise "redis_4_0_x" do gem "redis", "~> 4.0.0" end appraise "redis_4_1_x" do gem "redis", "~> 4.1.0" end appraise "redis_4_x" do gem "redis", "~> 4.0" end redis-store-1.9.0/.gitignore0000644000004100000410000000013713704151265016006 0ustar www-datawww-dataGemfile.lock *.gem tmp/ stdout # Gemfile locks generated by Appraisals gemfiles/*.gemfile.lock redis-store-1.9.0/.codeclimate.yml0000644000004100000410000000010513704151265017063 0ustar www-datawww-data--- plugins: rubocop: enabled: true fixme: enabled: true redis-store-1.9.0/Rakefile0000644000004100000410000000047213704151265015465 0ustar www-datawww-datarequire 'bundler/setup' require 'rake' require 'bundler/gem_tasks' require 'redis-store/testing/tasks' require 'appraisal' require 'rubocop/rake_task' RuboCop::RakeTask.new :lint if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"] task :default do sh "appraisal install && rake appraisal default" end end redis-store-1.9.0/lib/0000755000004100000410000000000013704151265014563 5ustar www-datawww-dataredis-store-1.9.0/lib/redis-store.rb0000644000004100000410000000002613704151265017346 0ustar www-datawww-datarequire 'redis/store' redis-store-1.9.0/lib/redis/0000755000004100000410000000000013704151265015671 5ustar www-datawww-dataredis-store-1.9.0/lib/redis/store/0000755000004100000410000000000013704151265017025 5ustar www-datawww-dataredis-store-1.9.0/lib/redis/store/interface.rb0000644000004100000410000000134113704151265021311 0ustar www-datawww-dataclass Redis class Store < self module Interface def get(key, options = nil) super(key) end REDIS_SET_OPTIONS = %i(ex px nx xx keepttl).freeze private_constant :REDIS_SET_OPTIONS def set(key, value, options = nil) if options && REDIS_SET_OPTIONS.any? { |k| options.key?(k) } kwargs = REDIS_SET_OPTIONS.each_with_object({}) { |key, h| h[key] = options[key] if options.key?(key) } super(key, value, **kwargs) else super(key, value) end end def setnx(key, value, options = nil) super(key, value) end def setex(key, expiry, value, options = nil) super(key, expiry, value) end end end end redis-store-1.9.0/lib/redis/store/version.rb0000644000004100000410000000010113704151265021027 0ustar www-datawww-dataclass Redis class Store < self VERSION = '1.9.0' end end redis-store-1.9.0/lib/redis/store/serialization.rb0000644000004100000410000000334113704151265022230 0ustar www-datawww-dataclass Redis class Store < self module Serialization def set(key, value, options = nil) _marshal(value, options) { |v| super encode(key), encode(v), options } end def setnx(key, value, options = nil) _marshal(value, options) { |v| super encode(key), encode(v), options } end def setex(key, expiry, value, options = nil) _marshal(value, options) { |v| super encode(key), expiry, encode(v), options } end def get(key, options = nil) _unmarshal super(key), options end def mget(*keys, &blk) options = keys.pop if keys.last.is_a?(Hash) super(*keys) do |reply| reply.map! { |value| _unmarshal value, options } blk ? blk.call(reply) : reply end end def mset(*args) options = args.pop if args.length.odd? updates = [] args.each_slice(2) do |(key, value)| updates << encode(key) _marshal(value, options) { |v| updates << encode(v) } end super(*updates) end private def _marshal(val, options) yield marshal?(options) ? @serializer.dump(val) : val end def _unmarshal(val, options) unmarshal?(val, options) ? @serializer.load(val) : val end def marshal?(options) !(options && options[:raw]) end def unmarshal?(result, options) result && result.size > 0 && marshal?(options) end if defined?(Encoding) def encode(string) key = string.to_s.dup key.force_encoding(Encoding::BINARY) end else def encode(string) string end end end end end redis-store-1.9.0/lib/redis/store/namespace.rb0000644000004100000410000001167013704151265021313 0ustar www-datawww-dataclass Redis class Store < self module Namespace FLUSHDB_BATCH_SIZE = 1000 def set(key, *args) namespace(key) { |k| super(k, *args) } end def setex(key, *args) namespace(key) { |k| super(k, *args) } end def setnx(key, *args) namespace(key) { |k| super(k, *args) } end def ttl(key, options = nil) namespace(key) { |k| super(k) } end def get(key, *args) namespace(key) { |k| super(k, *args) } end def exists(*keys) super(*keys.map { |key| interpolate(key) }) end def exists?(*keys) super(*keys.map { |key| interpolate(key) }) end def incrby(key, increment) namespace(key) { |k| super(k, increment) } end def decrby(key, increment) namespace(key) { |k| super(k, increment) } end def keys(pattern = "*") namespace(pattern) { |p| super(p).map { |key| strip_namespace(key) } } end def scan(cursor, match: nil, **kwargs) if match namespace(match) do |pattern| cursor, keys = super(cursor, match: pattern, **kwargs) [ cursor, keys.map{ |key| strip_namespace(key) } ] end else super(cursor, **kwargs) end end def del(*keys) super(*keys.map { |key| interpolate(key) }) if keys.any? end def unlink(*keys) super(*keys.map { |key| interpolate(key) }) if keys.any? end def watch(*keys) super(*keys.map { |key| interpolate(key) }) if keys.any? end def mget(*keys, &blk) options = (keys.pop if keys.last.is_a? Hash) || {} if keys.any? # Serialization gets extended before Namespace does, so we need to pass options further if singleton_class.ancestors.include? Serialization super(*keys.map { |key| interpolate(key) }, options, &blk) else super(*keys.map { |key| interpolate(key) }, &blk) end end end def expire(key, ttl) namespace(key) { |k| super(k, ttl) } end def hdel(key, *fields) namespace(key) { |k| super(k, *fields) } end def hget(key, field) namespace(key) { |k| super(k, field) } end def hgetall(key) namespace(key) { |k| super(k) } end def hexists(key, field) namespace(key) { |k| super(k, field) } end def hincrby(key, field, increment) namespace(key) { |k| super(k, field, increment) } end def hincrbyfloat(key, field, increment) namespace(key) { |k| super(k, field, increment) } end def hkeys(key) namespace(key) { |k| super(k) } end def hlen(key) namespace(key) { |k| super(k) } end def hmget(key, *fields, &blk) namespace(key) { |k| super(k, *fields, &blk) } end def hmset(key, *attrs) namespace(key) { |k| super(k, *attrs) } end def hset(key, *args) namespace(key) { |k| super(k, *args) } end def hsetnx(key, field, val) namespace(key) { |k| super(k, field, val) } end def hvals(key) namespace(key) { |k| super(k) } end def hscan(key, *args) namespace(key) { |k| super(k, *args) } end def hscan_each(key, *args) namespace(key) { |k| super(k, *args) } end def zincrby(key, increment, member) namespace(key) { |k| super(k, increment, member) } end def zscore(key, member) namespace(key) { |k| super(k, member) } end def zadd(key, *args) namespace(key) { |k| super(k, *args) } end def zrem(key, member) namespace(key) { |k| super(k, member) } end if respond_to?(:ruby2_keywords, true) ruby2_keywords :set, :setex, :setnx, :hscan, :hscan_each end def to_s if namespace_str "#{super} with namespace #{namespace_str}" else super end end def flushdb return super unless namespace_str keys.each_slice(FLUSHDB_BATCH_SIZE) { |key_slice| del(*key_slice) } end def with_namespace(ns) old_ns = @namespace @namespace = ns yield self ensure @namespace = old_ns end private def namespace(key) yield interpolate(key) end def namespace_str @namespace.is_a?(Proc) ? @namespace.call : @namespace end def interpolate(key) return key unless namespace_str key.match(namespace_regexp) ? key : "#{namespace_str}:#{key}" end def strip_namespace(key) return key unless namespace_str key.gsub namespace_regexp, "" end def namespace_regexp @namespace_regexps ||= {} @namespace_regexps[namespace_str] ||= %r{^#{namespace_str}\:} end end end end redis-store-1.9.0/lib/redis/store/factory.rb0000644000004100000410000000546613704151265021034 0ustar www-datawww-datarequire 'uri' class Redis class Store < self class Factory DEFAULT_PORT = 6379 def self.create(*options) new(options).create end def initialize(*options) @addresses = [] @options = {} extract_addresses_and_options(options) end def create if @addresses.empty? @addresses << {} end if @addresses.size > 1 ::Redis::DistributedStore.new @addresses, @options else ::Redis::Store.new @addresses.first.merge(@options) end end def self.resolve(uri) #:api: private if uri.is_a?(Hash) extract_host_options_from_hash(uri) else extract_host_options_from_uri(uri) end end def self.extract_host_options_from_hash(options) options = normalize_key_names(options) if host_options?(options) options else nil end end def self.normalize_key_names(options) options = options.dup if options.key?(:key_prefix) && !options.key?(:namespace) options[:namespace] = options.delete(:key_prefix) # RailsSessionStore end options[:raw] = case when options.key?(:serializer) options[:serializer].nil? when options.key?(:marshalling) !options[:marshalling] else false end options end def self.host_options?(options) options.keys.any? { |n| [:host, :db, :port, :path].include?(n) } end def self.extract_host_options_from_uri(uri) uri = URI.parse(uri) if uri.scheme == "unix" options = { :path => uri.path } else _, db, namespace = if uri.path uri.path.split(/\//) end options = { :scheme => uri.scheme, :host => uri.hostname, :port => uri.port || DEFAULT_PORT, :password => uri.password.nil? ? nil : CGI.unescape(uri.password.to_s) } options[:db] = db.to_i if db options[:namespace] = namespace if namespace end if uri.query query = Hash[URI.decode_www_form(uri.query)] query.each do |(key, value)| options[key.to_sym] = value end end options end private def extract_addresses_and_options(*options) options.flatten.compact.each do |token| resolved = self.class.resolve(token) if resolved @addresses << resolved else @options.merge!(self.class.normalize_key_names(token)) end end end end end end redis-store-1.9.0/lib/redis/store/ttl.rb0000644000004100000410000000215313704151265020156 0ustar www-datawww-dataclass Redis class Store < self module Ttl def set(key, value, options = nil) if ttl = expires_in(options) setex(key, ttl.to_i, value, :raw => true) else super(key, value, options) end end def setnx(key, value, options = nil) if ttl = expires_in(options) setnx_with_expire(key, value, ttl.to_i, options) else super(key, value) end end protected def setnx_with_expire(key, value, ttl, options = {}) with_multi_or_pipelined(options) do setnx(key, value, :raw => true) expire(key, ttl) end end private def expires_in(options) if options # Rack::Session Merb Rails/Sinatra options[:expire_after] || options[:expires_in] || options[:expire_in] end end def with_multi_or_pipelined(options, &block) return pipelined(&block) if options.key?(:cluster) || options[:avoid_multi_commands] multi(&block) end end end end redis-store-1.9.0/lib/redis/store/redis_version.rb0000644000004100000410000000044213704151265022225 0ustar www-datawww-dataclass Redis class Store < self module RedisVersion def redis_version info('server')['redis_version'] end def supports_redis_version?(version) (redis_version.split(".").map(&:to_i) <=> version.split(".").map(&:to_i)) >= 0 end end end end redis-store-1.9.0/lib/redis/distributed_store.rb0000644000004100000410000000276613704151265021767 0ustar www-datawww-datarequire 'redis/distributed' class Redis class DistributedStore < Distributed @@timeout = 5 attr_reader :ring def initialize(addresses, options = {}) _extend_namespace options @ring = options[:ring] || Redis::HashRing.new([], options[:replicas] || Redis::HashRing::POINTS_PER_SERVER) addresses.each do |address| @ring.add_node(::Redis::Store.new _merge_options(address, options)) end end def nodes ring.nodes end def reconnect nodes.each { |node| node.reconnect } end def set(key, value, options = nil) node_for(key).set(key, value, options) end def get(key, options = nil) node_for(key).get(key, options) end def setnx(key, value, options = nil) node_for(key).setnx(key, value, options) end def redis_version nodes.first.redis_version unless nodes.empty? end def supports_redis_version?(version) if nodes.empty? false else nodes.first.supports_redis_version?(version) end end def setex(key, expiry, value, options = nil) node_for(key).setex(key, expiry, value, options) end private def _extend_namespace(options) @namespace = options[:namespace] extend ::Redis::Store::Namespace if @namespace end def _merge_options(address, options) address.merge( :timeout => options[:timeout] || @@timeout, :namespace => options[:namespace] ) end end end redis-store-1.9.0/lib/redis/store.rb0000644000004100000410000000325613704151265017360 0ustar www-datawww-datarequire 'redis' require 'redis/store/factory' require 'redis/distributed_store' require 'redis/store/namespace' require 'redis/store/serialization' require 'redis/store/version' require 'redis/store/redis_version' require 'redis/store/ttl' require 'redis/store/interface' require 'redis/store/redis_version' class Redis class Store < self include Ttl, Interface, RedisVersion def initialize(options = {}) super unless options[:marshalling].nil? puts %( DEPRECATED: You are passing the :marshalling option, which has been replaced with `serializer: Marshal` to support pluggable serialization backends. To disable serialization (much like disabling marshalling), pass `serializer: nil` in your configuration. The :marshalling option will be removed for redis-store 2.0. ) end @serializer = options.key?(:serializer) ? options[:serializer] : Marshal unless options[:marshalling].nil? @serializer = options[:marshalling] ? Marshal : nil end _extend_marshalling options _extend_namespace options end def reconnect @client.reconnect end def to_s "Redis Client connected to #{location} against DB #{@client.db}" end def location if @client.path @client.path else h = @client.host h = "[#{h}]" if h.include?(":") "#{h}:#{@client.port}" end end private def _extend_marshalling(options) extend Serialization unless @serializer.nil? end def _extend_namespace(options) @namespace = options[:namespace] extend Namespace end end end redis-store-1.9.0/Gemfile0000644000004100000410000000012713704151265015310 0ustar www-datawww-datasource 'https://rubygems.org' if RUBY_VERSION < '2' gem 'redis', '< 4' end gemspec redis-store-1.9.0/.github/0000755000004100000410000000000013704151265015355 5ustar www-datawww-dataredis-store-1.9.0/.github/auto-assign-issues.yml0000644000004100000410000000002513704151265021640 0ustar www-datawww-dataassignees: - tubbo redis-store-1.9.0/MIT-LICENSE0000644000004100000410000000204513704151265015452 0ustar www-datawww-dataCopyright (c) 2009 - 2011 Luca Guidi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. redis-store-1.9.0/redis-store.gemspec0000644000004100000410000000245513704151265017630 0ustar www-datawww-data# -*- encoding: utf-8 -*- $:.push File.expand_path('../lib', __FILE__) require 'redis/store/version' Gem::Specification.new do |s| s.name = 'redis-store' s.version = Redis::Store::VERSION s.authors = ['Luca Guidi'] s.email = ['me@lucaguidi.com'] s.homepage = 'http://redis-store.org/redis-store' s.summary = 'Redis stores for Ruby frameworks' s.description = 'Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks.' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } s.require_paths = ["lib"] s.license = 'MIT' s.add_dependency 'redis', '>= 4', '< 5' s.add_development_dependency 'rake', '>= 12.3.3' s.add_development_dependency 'bundler' s.add_development_dependency 'mocha', '~> 0.14.0' s.add_development_dependency 'minitest', '~> 5' s.add_development_dependency 'git', '~> 1.2' s.add_development_dependency 'pry-nav', '~> 0.2.4' s.add_development_dependency 'pry', '~> 0.10.4' s.add_development_dependency 'redis-store-testing' s.add_development_dependency 'appraisal', '~> 2.0' s.add_development_dependency 'rubocop', '~> 0.54' end