cache 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ secret.sh
6
+ rdoc/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cache.gemspec
4
+ gemspec
@@ -0,0 +1,56 @@
1
+ = cache
2
+
3
+ A unified cache handling interface, inspired (but simpler than) Perl's Cache::Cache[http://cpan.uwinnipeg.ca/module/Cache::Cache] and CHI[http://cpan.uwinnipeg.ca/module/CHI].
4
+
5
+ == Methods
6
+
7
+ * get
8
+ * set
9
+ * delete
10
+ * flush
11
+
12
+ == Supported clients
13
+
14
+ Supported memcached clients:
15
+
16
+ * memcached[https://github.com/fauna/memcached] (either a Memcached or a Memcached::Rails)
17
+ * dalli[https://github.com/mperham/dalli] (either a Dalli::Client or an ActiveSupport::Cache::DalliStore)
18
+ * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
19
+
20
+ Supported Redis clients:
21
+
22
+ * redis[https://github.com/ezmobius/redis-rb]
23
+
24
+ == Configuration
25
+
26
+ You set your preferred cache client:
27
+
28
+ Cache.config.client = Memcached.new '127.0.0.1:11211'
29
+
30
+ or
31
+
32
+ Cache.config.client = Redis.new
33
+
34
+ or this might even work...
35
+
36
+ Cache.config.client = Rails.cache
37
+
38
+ == TTL
39
+
40
+ 0 means don't expire.
41
+
42
+ == Rationale
43
+
44
+ * I am so tired of rescuing from Memcached::NotFound
45
+ * I am so tired of forgetting whether it's :expires_in or :ttl
46
+ * I don't know why we ever started using read/write instead of get/set.
47
+
48
+ == Currently unsupported
49
+
50
+ * cas
51
+ * fetch
52
+ * incr
53
+
54
+ == Copyright
55
+
56
+ Copyright 2011 Seamus Abshere
@@ -0,0 +1,22 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.pattern = 'test/**/test_*.rb'
9
+ test.verbose = true
10
+ end
11
+
12
+ task :default => :test
13
+
14
+ require 'rake/rdoctask'
15
+ Rake::RDocTask.new do |rdoc|
16
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
17
+
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = "cache #{version}"
20
+ rdoc.rdoc_files.include('README*')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cache/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cache"
7
+ s.version = Cache::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Seamus Abshere"]
10
+ s.email = ["seamus@abshere.net"]
11
+ s.homepage = "https://github.com/seamusabshere/cache"
12
+ s.summary = %q{Wraps memcached, redis, memcache-client, dalli and handles their weirdnesses, including forking}
13
+ s.description = %q{A unified cache handling interface for Ruby, inspired by (but simpler than) Perl's Cache::Cache}
14
+
15
+ s.rubyforge_project = "cache"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'test-unit'
23
+ s.add_development_dependency 'redis'
24
+ s.add_development_dependency 'dalli'
25
+ s.add_development_dependency 'activesupport', '>=2.3.4' # for DalliStore
26
+ s.add_development_dependency 'i18n' # activesupport
27
+ s.add_development_dependency 'memcached'
28
+ s.add_development_dependency 'memcache-client'
29
+ end
@@ -0,0 +1,42 @@
1
+ require 'cache/version'
2
+ module Cache
3
+ autoload :Config, 'cache/config'
4
+ autoload :Storage, 'cache/storage'
5
+
6
+ def self.config #:nodoc:
7
+ Config.instance
8
+ end
9
+
10
+ # Get a value.
11
+ #
12
+ # Example:
13
+ # Cache.get 'hello'
14
+ def self.get(k)
15
+ Storage.instance.get k
16
+ end
17
+
18
+ # Store a value. Note that this will Marshal it.
19
+ #
20
+ # Example:
21
+ # Cache.set 'hello', 'world'
22
+ # Cache.set 'hello', 'world', 80 # seconds til it expires
23
+ def self.set(k, v, ttl = nil)
24
+ Storage.instance.set k, v, ttl
25
+ end
26
+
27
+ # Delete a value.
28
+ #
29
+ # Example:
30
+ # Cache.delete 'hello'
31
+ def self.delete(k)
32
+ Storage.instance.delete k
33
+ end
34
+
35
+ # Flush the cache.
36
+ #
37
+ # Example:
38
+ # Cache.flush
39
+ def self.flush
40
+ Storage.instance.flush
41
+ end
42
+ end
@@ -0,0 +1,45 @@
1
+ require 'singleton'
2
+ module Cache
3
+ # Here's where you set config options.
4
+ #
5
+ # Example:
6
+ # Cache.config.client = Memcached.new '127.0.0.1:11211'
7
+ # Cache.config.default_ttl = 120 # seconds
8
+ #
9
+ # You'd probably put this in your Rails config/initializers, for example.
10
+ class Config
11
+ include ::Singleton
12
+
13
+ # The cache client to use.
14
+ #
15
+ # Supported memcached clients:
16
+ # * memcached[https://github.com/fauna/memcached] (either a Memcached or a Memcached::Rails)
17
+ # * dalli[https://github.com/mperham/dalli] (either a Dalli::Client or an ActiveSupport::Cache::DalliStore)
18
+ # * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
19
+ #
20
+ # Supported Redis clients:
21
+ # * redis[https://github.com/ezmobius/redis-rb]
22
+ #
23
+ # Example:
24
+ # Cache.config.storage = Memcached.new '127.0.0.1:11211'
25
+ def client=(client)
26
+ @client = client
27
+ end
28
+
29
+ def client #:nodoc:
30
+ @client
31
+ end
32
+
33
+ # TTL for method caches. Defaults to 60 seconds.
34
+ #
35
+ # Example:
36
+ # Cache.config.default_ttl = 120 # seconds
37
+ def default_ttl=(seconds)
38
+ @default_ttl = seconds
39
+ end
40
+
41
+ def default_ttl #:nodoc:
42
+ @default_ttl || 60
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,90 @@
1
+ require 'singleton'
2
+ module Cache
3
+ class Storage #:nodoc: all
4
+ include ::Singleton
5
+
6
+ def get(k)
7
+ if defined?(::Memcached) and bare_client.is_a?(::Memcached)
8
+ begin; bare_client.get(k); rescue ::Memcached::NotFound; nil; end
9
+ elsif defined?(::Redis) and bare_client.is_a?(::Redis)
10
+ if cached_v = bare_client.get(k) and cached_v.is_a?(::String)
11
+ ::Marshal.load cached_v
12
+ end
13
+ elsif bare_client.respond_to?(:get)
14
+ bare_client.get k
15
+ elsif bare_client.respond_to?(:read)
16
+ bare_client.read k
17
+ else
18
+ raise "Don't know how to work with #{bare_client.inspect} because it doesn't define get"
19
+ end
20
+ end
21
+
22
+ def set(k, v, ttl)
23
+ ttl ||= Config.instance.default_ttl
24
+ if defined?(::Redis) and bare_client.is_a?(::Redis)
25
+ if ttl == 0
26
+ bare_client.set k, ::Marshal.dump(v)
27
+ else
28
+ bare_client.setex k, ttl, ::Marshal.dump(v)
29
+ end
30
+ elsif bare_client.respond_to?(:set)
31
+ bare_client.set k, v, ttl
32
+ elsif bare_client.respond_to?(:write)
33
+ if ttl == 0
34
+ bare_client.write k, v # never expire
35
+ else
36
+ bare_client.write k, v, :expires_in => ttl
37
+ end
38
+ else
39
+ raise "Don't know how to work with #{bare_client.inspect} because it doesn't define set"
40
+ end
41
+ end
42
+
43
+ def delete(k)
44
+ if defined?(::Memcached) and bare_client.is_a?(::Memcached)
45
+ begin; bare_client.delete(k); rescue ::Memcached::NotFound; nil; end
46
+ elsif defined?(::Redis) and bare_client.is_a?(::Redis)
47
+ bare_client.del k
48
+ elsif bare_client.respond_to?(:delete)
49
+ bare_client.delete k
50
+ else
51
+ raise "Don't know how to work with #{bare_client.inspect} because it doesn't define delete"
52
+ end
53
+ end
54
+
55
+ def flush
56
+ bare_client.send %w{ flush flushdb flush_all clear }.detect { |flush_cmd| bare_client.respond_to? flush_cmd }
57
+ end
58
+
59
+ def bare_client
60
+ if @pid == ::Process.pid
61
+ fork_detected = false
62
+ else
63
+ fork_detected = true
64
+ ::Thread.current[:cache_storage_bare_client] = nil
65
+ @pid = ::Process.pid
66
+ end
67
+ ::Thread.current[:cache_storage_bare_client] ||= fresh_bare_client(fork_detected)
68
+ end
69
+
70
+ def fresh_bare_client(fork_detected)
71
+ if defined?(::Dalli) and Config.instance.client.is_a?(::Dalli::Client)
72
+ Config.instance.client.close if fork_detected
73
+ Config.instance.client
74
+ elsif defined?(::ActiveSupport::Cache::DalliStore) and Config.instance.client.is_a?(::ActiveSupport::Cache::DalliStore)
75
+ Config.instance.client.reset if fork_detected
76
+ Config.instance.client
77
+ elsif defined?(::Memcached) and (Config.instance.client.is_a?(::Memcached) or Config.instance.client.is_a?(::Memcached::Rails))
78
+ Config.instance.client.clone
79
+ elsif defined?(::Redis) and Config.instance.client.is_a?(::Redis)
80
+ Config.instance.client.client.connect if fork_detected
81
+ Config.instance.client
82
+ elsif defined?(::MemCache) and Config.instance.client.is_a?(::MemCache)
83
+ Config.instance.client.reset if fork_detected
84
+ Config.instance.client
85
+ else
86
+ raise "Don't know how to thread/fork #{Config.instance.client.inspect}"
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module Cache
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+ require 'test/unit'
5
+ # require 'ruby-debug'
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'cache'
9
+
10
+ require 'shared_tests'
11
+
12
+ class Test::Unit::TestCase
13
+ end
@@ -0,0 +1,41 @@
1
+ module SharedTests
2
+ def test_get
3
+ assert_equal nil, Cache.get('hello')
4
+ Cache.set 'hello', 'world'
5
+ assert_equal 'world', Cache.get('hello')
6
+ end
7
+
8
+ def test_set
9
+ assert_nothing_raised do
10
+ Cache.set 'hello', 'world'
11
+ end
12
+ end
13
+
14
+ def test_set_with_ttl
15
+ Cache.set 'hello', 'world', 1
16
+ assert_equal 'world', Cache.get('hello')
17
+ sleep 2
18
+ assert_equal nil, Cache.get('hello')
19
+ end
20
+
21
+ def test_set_with_zero_ttl_meaning_eternal
22
+ Cache.set 'hello', 'world', 0
23
+ assert_equal 'world', Cache.get('hello')
24
+ sleep 1
25
+ assert_equal 'world', Cache.get('hello')
26
+ end
27
+
28
+ def test_delete
29
+ Cache.set 'hello', 'world'
30
+ assert_equal 'world', Cache.get('hello')
31
+ Cache.delete 'hello'
32
+ assert_equal nil, Cache.get('hello')
33
+ end
34
+
35
+ def test_flush
36
+ Cache.set 'hello', 'world'
37
+ assert_equal 'world', Cache.get('hello')
38
+ Cache.flush
39
+ assert_equal nil, Cache.get('hello')
40
+ end
41
+ end
@@ -0,0 +1,58 @@
1
+ require 'helper'
2
+
3
+ require 'dalli'
4
+
5
+ class TestDalliStorage < Test::Unit::TestCase
6
+ def setup
7
+ super
8
+ client = Dalli::Client.new ['localhost:11211']
9
+ client.flush
10
+ Cache.config.client = client
11
+ end
12
+
13
+ include SharedTests
14
+
15
+ def get_ring_object_id
16
+ Cache.config.client.instance_variable_get(:@ring).object_id
17
+ end
18
+
19
+ def test_treats_as_thread_safe
20
+ # make sure ring is initialized
21
+ Cache.get 'hi'
22
+
23
+ # get the main thread's ring
24
+ main_thread_ring_id = get_ring_object_id
25
+
26
+ # sanity check that it's not changing every time
27
+ Cache.get 'hi'
28
+ assert_equal main_thread_ring_id, get_ring_object_id
29
+
30
+ # create a new thread and get its ring
31
+ new_thread_ring_id = Thread.new { Cache.get 'hi'; get_ring_object_id }.value
32
+
33
+ # make sure the ring was reinitialized
34
+ assert_equal main_thread_ring_id, new_thread_ring_id
35
+ end
36
+
37
+ def test_treats_as_not_fork_safe
38
+ # make sure ring is initialized
39
+ Cache.get 'hi'
40
+
41
+ # get the main thread's ring
42
+ parent_process_ring_id = get_ring_object_id
43
+
44
+ # sanity check that it's not changing every time
45
+ Cache.get 'hi'
46
+ assert_equal parent_process_ring_id, get_ring_object_id
47
+
48
+ # fork a new process
49
+ pid = Kernel.fork do
50
+ Cache.get 'hi'
51
+ raise "Didn't split!" if parent_process_ring_id == get_ring_object_id
52
+ end
53
+ Process.wait pid
54
+
55
+ # make sure it didn't raise
56
+ assert $?.success?
57
+ end
58
+ end
@@ -0,0 +1,61 @@
1
+ require 'helper'
2
+
3
+ require 'dalli'
4
+ require 'active_support/all'
5
+ require 'active_support/cache/dalli_store'
6
+
7
+ class TestDalliStoreStorage < Test::Unit::TestCase
8
+ def setup
9
+ super
10
+ client = ActiveSupport::Cache::DalliStore.new ['localhost:11211']
11
+ client.clear
12
+ Cache.config.client = client
13
+ end
14
+
15
+ include SharedTests
16
+
17
+ def get_ring_object_id
18
+ hidden_dalli_client = Cache.config.client.instance_variable_get :@data
19
+ hidden_dalli_client.instance_variable_get(:@ring).object_id
20
+ end
21
+
22
+ def test_treats_as_thread_safe
23
+ # make sure ring is initialized
24
+ Cache.get 'hi'
25
+
26
+ # get the main thread's ring
27
+ main_thread_ring_id = get_ring_object_id
28
+
29
+ # sanity check that it's not changing every time
30
+ Cache.get 'hi'
31
+ assert_equal main_thread_ring_id, get_ring_object_id
32
+
33
+ # create a new thread and get its ring
34
+ new_thread_ring_id = Thread.new { Cache.get 'hi'; get_ring_object_id }.value
35
+
36
+ # make sure the ring was reinitialized
37
+ assert_equal main_thread_ring_id, new_thread_ring_id
38
+ end
39
+
40
+ def test_treats_as_not_fork_safe
41
+ # make sure ring is initialized
42
+ Cache.get 'hi'
43
+
44
+ # get the main thread's ring
45
+ parent_process_ring_id = get_ring_object_id
46
+
47
+ # sanity check that it's not changing every time
48
+ Cache.get 'hi'
49
+ assert_equal parent_process_ring_id, get_ring_object_id
50
+
51
+ # fork a new process
52
+ pid = Kernel.fork do
53
+ Cache.get 'hi'
54
+ raise "Didn't split!" if parent_process_ring_id == get_ring_object_id
55
+ end
56
+ Process.wait pid
57
+
58
+ # make sure it didn't raise
59
+ assert $?.success?
60
+ end
61
+ end
@@ -0,0 +1,59 @@
1
+ require 'helper'
2
+
3
+ # the famous memcache-client
4
+ require 'memcache'
5
+
6
+ class TestMemcacheStorage < Test::Unit::TestCase
7
+ def setup
8
+ super
9
+ client = MemCache.new ['localhost:11211']
10
+ client.flush_all
11
+ Cache.config.client = client
12
+ end
13
+
14
+ include SharedTests
15
+
16
+ def get_server_status_ids
17
+ Cache.config.client.instance_variable_get(:@servers).map { |s| s.status.object_id }
18
+ end
19
+
20
+ def test_treats_as_thread_safe
21
+ # make sure servers are connected
22
+ Cache.get 'hi'
23
+
24
+ # get the object ids
25
+ main_thread_server_status_ids = get_server_status_ids
26
+
27
+ # sanity check that it's not changing every time
28
+ Cache.get 'hi'
29
+ assert_equal main_thread_server_status_ids, get_server_status_ids
30
+
31
+ # create a new thread and get its server ids
32
+ new_thread_server_status_ids = Thread.new { Cache.get 'hi'; get_server_status_ids }.value
33
+
34
+ # make sure the server ids was reinitialized
35
+ assert_equal main_thread_server_status_ids, new_thread_server_status_ids
36
+ end
37
+
38
+ def test_treats_as_not_fork_safe
39
+ # make sure server ids is initialized
40
+ Cache.get 'hi'
41
+
42
+ # get the main thread's server ids
43
+ parent_process_server_status_ids = get_server_status_ids
44
+
45
+ # sanity check that it's not changing every time
46
+ Cache.get 'hi'
47
+ assert_equal parent_process_server_status_ids, get_server_status_ids
48
+
49
+ # fork a new process
50
+ pid = Kernel.fork do
51
+ Cache.get 'hi'
52
+ raise "Didn't split!" if parent_process_server_status_ids == get_server_status_ids
53
+ end
54
+ Process.wait pid
55
+
56
+ # make sure it didn't raise
57
+ assert $?.success?
58
+ end
59
+ end
@@ -0,0 +1,58 @@
1
+ require 'helper'
2
+
3
+ require 'memcached'
4
+
5
+ class TestMemcachedRailsStorage < Test::Unit::TestCase
6
+ def setup
7
+ super
8
+ client = Memcached::Rails.new 'localhost:11211'
9
+ client.flush
10
+ Cache.config.client = client
11
+ end
12
+
13
+ include SharedTests
14
+
15
+ def get_bare_client_id
16
+ Cache::Storage.instance.bare_client.object_id
17
+ end
18
+
19
+ def test_treats_as_not_thread_safe
20
+ # make sure bare client is initialized
21
+ Cache.get 'hi'
22
+
23
+ # get the main thread's bare client
24
+ main_thread_bare_client_id = get_bare_client_id
25
+
26
+ # sanity check that it's not changing every time
27
+ Cache.get 'hi'
28
+ assert_equal main_thread_bare_client_id, get_bare_client_id
29
+
30
+ # create a new thread and get its bare client
31
+ new_thread_bare_client_id = Thread.new { Cache.get 'hi'; get_bare_client_id }.value
32
+
33
+ # make sure the bare client was reinitialized
34
+ assert(main_thread_bare_client_id != new_thread_bare_client_id)
35
+ end
36
+
37
+ def test_treats_as_not_fork_safe
38
+ # make sure bare client is initialized
39
+ Cache.get 'hi'
40
+
41
+ # get the main process's bare client
42
+ parent_process_bare_client_id = get_bare_client_id
43
+
44
+ # sanity check that it's not changing every time
45
+ Cache.get 'hi'
46
+ assert_equal parent_process_bare_client_id, get_bare_client_id
47
+
48
+ # fork a new process
49
+ pid = Kernel.fork do
50
+ Cache.get 'hi'
51
+ raise "Didn't split!" if parent_process_bare_client_id == get_bare_client_id
52
+ end
53
+ Process.wait pid
54
+
55
+ # make sure it didn't raise
56
+ assert $?.success?
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require 'helper'
2
+
3
+ require 'memcached'
4
+
5
+ class TestMemcachedStorage < Test::Unit::TestCase
6
+ def setup
7
+ super
8
+ client = Memcached.new 'localhost:11211'
9
+ client.flush
10
+ Cache.config.client = client
11
+ end
12
+
13
+ include SharedTests
14
+
15
+ def get_bare_client_id
16
+ Cache::Storage.instance.bare_client.object_id
17
+ end
18
+
19
+ def test_treats_as_not_thread_safe
20
+ # make sure bare client is initialized
21
+ Cache.get 'hi'
22
+
23
+ # get the main thread's bare client
24
+ main_thread_bare_client_id = get_bare_client_id
25
+
26
+ # sanity check that it's not changing every time
27
+ Cache.get 'hi'
28
+ assert_equal main_thread_bare_client_id, get_bare_client_id
29
+
30
+ # create a new thread and get its bare client
31
+ new_thread_bare_client_id = Thread.new { Cache.get 'hi'; get_bare_client_id }.value
32
+
33
+ # make sure the bare client was reinitialized
34
+ assert(main_thread_bare_client_id != new_thread_bare_client_id)
35
+ end
36
+
37
+ def test_treats_as_not_fork_safe
38
+ # make sure bare client is initialized
39
+ Cache.get 'hi'
40
+
41
+ # get the main process's bare client
42
+ parent_process_bare_client_id = get_bare_client_id
43
+
44
+ # sanity check that it's not changing every time
45
+ Cache.get 'hi'
46
+ assert_equal parent_process_bare_client_id, get_bare_client_id
47
+
48
+ # fork a new process
49
+ pid = Kernel.fork do
50
+ Cache.get 'hi'
51
+ raise "Didn't split!" if parent_process_bare_client_id == get_bare_client_id
52
+ end
53
+ Process.wait pid
54
+
55
+ # make sure it didn't raise
56
+ assert $?.success?
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ require 'helper'
2
+
3
+ if ENV['REDIS_URL']
4
+ require 'redis'
5
+ require 'uri'
6
+
7
+ class TestRedisStorage < Test::Unit::TestCase
8
+ def setup
9
+ super
10
+ uri = URI.parse(ENV["REDIS_URL"])
11
+ client = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
12
+ client.flushdb
13
+ Cache.config.client = client
14
+ end
15
+
16
+ include SharedTests
17
+
18
+ # client DOT client
19
+ def get_redis_client_connection_socket_id
20
+ connection = Cache.config.client.client.instance_variable_get :@connection
21
+ sock = connection.instance_variable_get(:@sock)
22
+ # $stderr.puts sock.inspect
23
+ sock.object_id
24
+ end
25
+
26
+ def test_treats_as_thread_safe
27
+ # make sure ring is initialized
28
+ Cache.get 'hi'
29
+
30
+ # get the main thread's ring
31
+ main_thread_redis_client_connection_socket_id = get_redis_client_connection_socket_id
32
+
33
+ # sanity check that it's not changing every time
34
+ Cache.get 'hi'
35
+ assert_equal main_thread_redis_client_connection_socket_id, get_redis_client_connection_socket_id
36
+
37
+ # create a new thread and get its ring
38
+ new_thread_redis_client_connection_socket_id = Thread.new { Cache.get 'hi'; get_redis_client_connection_socket_id }.value
39
+
40
+ # make sure the ring was reinitialized
41
+ assert_equal main_thread_redis_client_connection_socket_id, new_thread_redis_client_connection_socket_id
42
+ end
43
+
44
+ def test_treats_as_not_fork_safe
45
+ # make sure ring is initialized
46
+ Cache.get 'hi'
47
+
48
+ # get the main thread's ring
49
+ parent_process_redis_client_connection_socket_id = get_redis_client_connection_socket_id
50
+
51
+ # sanity check that it's not changing every time
52
+ Cache.get 'hi'
53
+ assert_equal parent_process_redis_client_connection_socket_id, get_redis_client_connection_socket_id
54
+
55
+ # fork a new process
56
+ pid = Kernel.fork do
57
+ Cache.get 'hi'
58
+ raise "Didn't split!" if parent_process_redis_client_connection_socket_id == get_redis_client_connection_socket_id
59
+ end
60
+ Process.wait pid
61
+
62
+ # make sure it didn't raise
63
+ assert $?.success?
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Seamus Abshere
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-17 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: test-unit
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: redis
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: dalli
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: activesupport
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 11
72
+ segments:
73
+ - 2
74
+ - 3
75
+ - 4
76
+ version: 2.3.4
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: i18n
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: memcached
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ type: :development
106
+ version_requirements: *id006
107
+ - !ruby/object:Gem::Dependency
108
+ name: memcache-client
109
+ prerelease: false
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ type: :development
120
+ version_requirements: *id007
121
+ description: A unified cache handling interface for Ruby, inspired by (but simpler than) Perl's Cache::Cache
122
+ email:
123
+ - seamus@abshere.net
124
+ executables: []
125
+
126
+ extensions: []
127
+
128
+ extra_rdoc_files: []
129
+
130
+ files:
131
+ - .gitignore
132
+ - Gemfile
133
+ - README.rdoc
134
+ - Rakefile
135
+ - cache.gemspec
136
+ - lib/cache.rb
137
+ - lib/cache/config.rb
138
+ - lib/cache/storage.rb
139
+ - lib/cache/version.rb
140
+ - test/helper.rb
141
+ - test/shared_tests.rb
142
+ - test/test_dalli_storage.rb
143
+ - test/test_dalli_store_storage.rb
144
+ - test/test_memcache_storage.rb
145
+ - test/test_memcached_rails_storage.rb
146
+ - test/test_memcached_storage.rb
147
+ - test/test_redis_storage.rb
148
+ has_rdoc: true
149
+ homepage: https://github.com/seamusabshere/cache
150
+ licenses: []
151
+
152
+ post_install_message:
153
+ rdoc_options: []
154
+
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ none: false
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ hash: 3
163
+ segments:
164
+ - 0
165
+ version: "0"
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ hash: 3
172
+ segments:
173
+ - 0
174
+ version: "0"
175
+ requirements: []
176
+
177
+ rubyforge_project: cache
178
+ rubygems_version: 1.3.7
179
+ signing_key:
180
+ specification_version: 3
181
+ summary: Wraps memcached, redis, memcache-client, dalli and handles their weirdnesses, including forking
182
+ test_files:
183
+ - test/helper.rb
184
+ - test/shared_tests.rb
185
+ - test/test_dalli_storage.rb
186
+ - test/test_dalli_store_storage.rb
187
+ - test/test_memcache_storage.rb
188
+ - test/test_memcached_rails_storage.rb
189
+ - test/test_memcached_storage.rb
190
+ - test/test_redis_storage.rb