redis-store-1.3.0/0000755000004100000410000000000012776263072014017 5ustar www-datawww-dataredis-store-1.3.0/Rakefile0000644000004100000410000000014712776263072015466 0ustar www-datawww-datarequire 'bundler/setup' require 'rake' require 'bundler/gem_tasks' require 'redis-store/testing/tasks' redis-store-1.3.0/CHANGELOG0000644000004100000410000005000412776263072015230 0ustar www-datawww-data*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.3.0/Gemfile0000644000004100000410000000004612776263072015312 0ustar www-datawww-datasource 'https://rubygems.org' gemspec redis-store-1.3.0/MIT-LICENSE0000644000004100000410000000204512776263072015454 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.3.0/redis-store.gemspec0000644000004100000410000000220312776263072017621 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 = %q{Redis stores for Ruby frameworks} s.description = %q{Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks.} s.rubyforge_project = 'redis-store' 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', '>= 2.2' s.add_development_dependency 'rake', '~> 10' s.add_development_dependency 'bundler', '~> 1.3' 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 'redis-store-testing' end redis-store-1.3.0/.travis.yml0000644000004100000410000000047712776263072016140 0ustar www-datawww-datalanguage: ruby sudo: false cache: bundler before_install: gem install bundler script: 'bundle exec rake' rvm: - 1.9.3 - 2.0.0 - 2.1 - 2.2 - 2.3.0 - ruby-head - rbx-2 - jruby-19mode - jruby-head bundler_args: '--path vendor/bundle' matrix: allow_failures: - rvm: jruby-head - rvm: ruby-head redis-store-1.3.0/lib/0000755000004100000410000000000012776263072014565 5ustar www-datawww-dataredis-store-1.3.0/lib/redis-store.rb0000644000004100000410000000042612776263072017354 0ustar www-datawww-datarequire 'redis' require 'redis/store' require 'redis/store/factory' require 'redis/distributed_store' require 'redis/store/namespace' require 'redis/store/marshalling' require 'redis/store/version' require 'redis/store/redis_version' class Redis class Store < self end end redis-store-1.3.0/lib/redis/0000755000004100000410000000000012776263072015673 5ustar www-datawww-dataredis-store-1.3.0/lib/redis/distributed_store.rb0000644000004100000410000000264612776263072021766 0ustar www-datawww-datarequire 'redis/distributed' class Redis class DistributedStore < Distributed @@timeout = 5 attr_reader :ring def initialize(addresses, options = { }) nodes = addresses.map do |address| ::Redis::Store.new _merge_options(address, options) end _extend_namespace options @ring = Redis::HashRing.new nodes 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.3.0/lib/redis/store/0000755000004100000410000000000012776263072017027 5ustar www-datawww-dataredis-store-1.3.0/lib/redis/store/namespace.rb0000644000004100000410000000510112776263072021305 0ustar www-datawww-dataclass Redis class Store < self module Namespace FLUSHDB_BATCH_SIZE = 1000 def set(key, val, options = nil) namespace(key) { |k| super(k, val, options) } end def setex(key, ttl, val, options = nil) namespace(key) { |k| super(k, ttl, val, options) } end def setnx(key, val, options = nil) namespace(key) { |k| super(k, val, options) } end def ttl(key, options = nil) namespace(key) { |k| super(k) } end def get(key, options = nil) namespace(key) { |k| super(k, options) } end def exists(key) namespace(key) { |k| super(k) } 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 del(*keys) super(*keys.map {|key| interpolate(key) }) if keys.any? end def mget(*keys) options = (keys.pop if keys.last.is_a? Hash) || {} if keys.any? # Marshalling gets extended before Namespace does, so we need to pass options further if singleton_class.ancestors.include? Marshalling super(*keys.map {|key| interpolate(key) }, options) else super(*keys.map {|key| interpolate(key) }) end end end def expire(key, ttl) namespace(key) { |k| super(k, ttl) } end def to_s if namespace_str "#{super} with namespace #{namespace_str}" else super end end def flushdb 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.3.0/lib/redis/store/interface.rb0000644000004100000410000000062412776263072021316 0ustar www-datawww-dataclass Redis class Store < self module Interface def get(key, options = nil) super(key) end def set(key, value, options = nil) super(key, value, options || {}) 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.3.0/lib/redis/store/redis_version.rb0000644000004100000410000000044312776263072022230 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.3.0/lib/redis/store/marshalling.rb0000644000004100000410000000323012776263072021653 0ustar www-datawww-dataclass Redis class Store < self module Marshalling 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) options = keys.pop if keys.last.is_a?(Hash) super(*keys).map do |result| _unmarshal result, options 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) ? Marshal.dump(val) : val end def _unmarshal(val, options) unmarshal?(val, options) ? Marshal.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.3.0/lib/redis/store/factory.rb0000644000004100000410000000442312776263072021026 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] = !options[:marshalling] options end def self.host_options?(options) if options.keys.any? {|n| [:host, :db, :port].include?(n) } options else nil # just to be clear end end def self.extract_host_options_from_uri(uri) uri = URI.parse(uri) _, db, namespace = if uri.path uri.path.split(/\//) end options = { :host => uri.hostname, :port => uri.port || DEFAULT_PORT, :password => uri.password } options[:db] = db.to_i if db options[:namespace] = namespace if namespace 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.3.0/lib/redis/store/version.rb0000644000004100000410000000010112776263072021031 0ustar www-datawww-dataclass Redis class Store < self VERSION = '1.3.0' end end redis-store-1.3.0/lib/redis/store/ttl.rb0000644000004100000410000000160012776263072020154 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) else super(key, value) end end protected def setnx_with_expire(key, value, ttl) multi 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 end end end redis-store-1.3.0/lib/redis/store.rb0000644000004100000410000000145512776263072017361 0ustar www-datawww-datarequire '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 _extend_marshalling options _extend_namespace options end def reconnect @client.reconnect end def to_s h = @client.host "Redis Client connected to #{/:/ =~ h ? '['+h+']' : h}:#{@client.port} against DB #{@client.db}" end private def _extend_marshalling(options) @marshalling = !(options[:marshalling] === false) # HACK - TODO delegate to Factory extend Marshalling if @marshalling end def _extend_namespace(options) @namespace = options[:namespace] extend Namespace end end end redis-store-1.3.0/test/0000755000004100000410000000000012776263072014776 5ustar www-datawww-dataredis-store-1.3.0/test/test_helper.rb0000644000004100000410000000071112776263072017640 0ustar www-datawww-datarequire 'bundler/setup' require 'minitest/autorun' require 'mocha/setup' require 'redis' require 'redis-store' $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 return result end end redis-store-1.3.0/test/redis/0000755000004100000410000000000012776263072016104 5ustar www-datawww-dataredis-store-1.3.0/test/redis/distributed_store_test.rb0000644000004100000410000000336012776263072023230 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 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.3.0/test/redis/store/0000755000004100000410000000000012776263072017240 5ustar www-datawww-dataredis-store-1.3.0/test/redis/store/version_test.rb0000644000004100000410000000021612776263072022310 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.3.0/test/redis/store/namespace_test.rb0000644000004100000410000001062212776263072022561 0ustar www-datawww-datarequire 'test_helper' describe "Redis::Store::Namespace" do def setup @namespace = "theplaylist" @store = Redis::Store.new :namespace => @namespace, :marshalling => false # TODO remove mashalling option @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_equal(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_equal(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, :marshalling => false} 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 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"]) store.mget "rabbit", "white_rabbit" 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 end end redis-store-1.3.0/test/redis/store/redis_version_test.rb0000644000004100000410000000145212776263072023501 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.3.0/test/redis/store/ttl_test.rb0000644000004100000410000000450112776263072021427 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 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 MockTtlStore.any_instance.expects(:expire).never redis.setnx(key, mock_value) end end describe 'with expiry' do 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 redis-store-1.3.0/test/redis/store/interface_test.rb0000644000004100000410000000123112776263072022561 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.3.0/test/redis/store/marshalling_test.rb0000644000004100000410000001240712776263072023131 0ustar www-datawww-datarequire 'test_helper' describe "Redis::Marshalling" do def setup @store = Redis::Store.new :marshalling => true @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 "doesn't unmarshal on multi get" do @store.set "rabbit2", @white_rabbit rabbits = @store.mget "rabbit", "rabbit2" rabbit, rabbit2 = rabbits rabbits.length.must_equal(2) rabbit.must_equal(@rabbit) 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 rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true rabbit.must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF") rabbit2.must_equal("\x04\bU:\x0FOpenStruct{\x06:\ncolorI\"\nwhite\x06:\x06EF") end else it "doesn't unmarshal on multi get if raw option is true" do @store.set "rabbit2", @white_rabbit rabbit, rabbit2 = @store.mget "rabbit", "rabbit2", :raw => true rabbit.must_include("\x04\bU:\x0FOpenStruct{\x06:\tname") rabbit2.must_include("\x04\bU:\x0FOpenStruct{\x06:\ncolor") 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.3.0/test/redis/store/factory_test.rb0000644000004100000410000001410212776263072022271 0ustar www-datawww-datarequire 'test_helper' 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 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 "allows/disable marshalling" do store = Redis::Store::Factory.create :marshalling => false store.instance_variable_get(:@marshalling).must_equal(false) store.instance_variable_get(:@options)[:raw].must_equal(true) 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 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 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 "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.client.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.3.0/test/redis/store_test.rb0000644000004100000410000000326012776263072020625 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.3.0/.gitignore0000644000004100000410000000003012776263072016000 0ustar www-datawww-dataGemfile.lock *.gem tmp/ redis-store-1.3.0/README.md0000644000004100000410000000315612776263072015303 0ustar www-datawww-data# Redis stores for Ruby frameworks [![Build Status](https://travis-ci.org/redis-store/redis-store.svg?branch=master)](https://travis-ci.org/redis-store/redis-store) __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 gem install bundler bundle exec rake ``` If you are on **Snow Leopard** you have to run `env ARCHFLAGS="-arch x86_64" ruby ci/run.rb` ## Contributors * Matt Horan ([@mhoran](https://github.com/mhoran)) ## Status [![Gem Version](https://badge.fury.io/rb/redis-store.png)](http://badge.fury.io/rb/redis-store) [![Build Status](https://secure.travis-ci.org/redis-store/redis-store.png?branch=master)](http://travis-ci.org/redis-store/redis-store?branch=master) [![Code Climate](https://codeclimate.com/github/redis-store/redis-store.png)](https://codeclimate.com/github/redis-store/redis-store) ## Copyright 2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license