cache 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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