cache 0.0.1 → 0.0.2
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.
- data/README.rdoc +40 -17
- data/lib/cache.rb +38 -17
- data/lib/cache/config.rb +14 -19
- data/lib/cache/storage.rb +36 -28
- data/lib/cache/version.rb +2 -2
- data/test/helper.rb +4 -0
- data/test/shared_tests.rb +18 -18
- data/test/test_dalli_storage.rb +8 -10
- data/test/test_dalli_store_storage.rb +8 -10
- data/test/test_memcache_storage.rb +8 -10
- data/test/test_memcached_rails_storage.rb +8 -10
- data/test/test_memcached_storage.rb +8 -10
- data/test/test_redis_storage.rb +9 -11
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -2,12 +2,40 @@
|
|
2
2
|
|
3
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
4
|
|
5
|
+
Takes care of exceptions like Memcached::NotFound and also forking/threading.
|
6
|
+
|
7
|
+
== Example
|
8
|
+
|
9
|
+
require 'memcached' # a really fast memcached client gem
|
10
|
+
require 'client' # this gem, which provides a standard interface
|
11
|
+
raw_client = Memcached.new '127.0.0.1:11211'
|
12
|
+
cache = Cache.new raw_client
|
13
|
+
|
14
|
+
or
|
15
|
+
|
16
|
+
require 'redis' # the redis key-value store
|
17
|
+
require 'client' # this gem, which provides a standard interface
|
18
|
+
raw_client = Redis.new
|
19
|
+
cache = Cache.new raw_client
|
20
|
+
|
21
|
+
or
|
22
|
+
|
23
|
+
require 'dalli' # the dalli memcached client used by heroku
|
24
|
+
require 'client' # this gem, which provides a standard interface
|
25
|
+
raw_client = Dalli::Client.new
|
26
|
+
cache = Cache.new raw_client
|
27
|
+
|
28
|
+
Maybe this will even work:
|
29
|
+
|
30
|
+
# Piggyback off the default rails cache
|
31
|
+
cache = Cache.new Rails.cache
|
32
|
+
|
5
33
|
== Methods
|
6
34
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
35
|
+
cache.get 'hello'
|
36
|
+
cache.set 'hello', 'world'
|
37
|
+
cache.delete 'hello'
|
38
|
+
cache.flush
|
11
39
|
|
12
40
|
== Supported clients
|
13
41
|
|
@@ -21,29 +49,24 @@ Supported Redis clients:
|
|
21
49
|
|
22
50
|
* redis[https://github.com/ezmobius/redis-rb]
|
23
51
|
|
24
|
-
==
|
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
|
52
|
+
== TTL
|
33
53
|
|
34
|
-
|
54
|
+
0 means don't expire.
|
35
55
|
|
36
|
-
|
56
|
+
== Forking/threading
|
37
57
|
|
38
|
-
|
58
|
+
When you use a Cache object to wrap Memcached or Redis, you don't have to worry about forking or threading.
|
39
59
|
|
40
|
-
|
60
|
+
For example, you don't have to set up unicorn or PhusionPassenger's <tt>after_fork</tt>.
|
41
61
|
|
42
62
|
== Rationale
|
43
63
|
|
64
|
+
I wanted a common interface to a bunch of great Ruby cache clients so I can develop gems (lock_method, cache_method) that accept any of them.
|
65
|
+
|
44
66
|
* I am so tired of rescuing from Memcached::NotFound
|
45
67
|
* I am so tired of forgetting whether it's :expires_in or :ttl
|
46
68
|
* I don't know why we ever started using read/write instead of get/set.
|
69
|
+
* I don't like how you have to manually handle after_fork for Redis, Memcached, etc.
|
47
70
|
|
48
71
|
== Currently unsupported
|
49
72
|
|
data/lib/cache.rb
CHANGED
@@ -1,42 +1,63 @@
|
|
1
1
|
require 'cache/version'
|
2
|
-
|
2
|
+
class Cache
|
3
3
|
autoload :Config, 'cache/config'
|
4
4
|
autoload :Storage, 'cache/storage'
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
# Create a new Cache object by passing it a client of your choice.
|
7
|
+
#
|
8
|
+
# Supported memcached clients:
|
9
|
+
# * memcached[https://github.com/fauna/memcached] (either a Memcached or a Memcached::Rails)
|
10
|
+
# * dalli[https://github.com/mperham/dalli] (either a Dalli::Client or an ActiveSupport::Cache::DalliStore)
|
11
|
+
# * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
|
12
|
+
#
|
13
|
+
# Supported Redis clients:
|
14
|
+
# * redis[https://github.com/ezmobius/redis-rb]
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# raw_client = Memcached.new('127.0.0.1:11211')
|
18
|
+
# cache = Cache.new raw_client
|
19
|
+
def initialize(client)
|
20
|
+
config.client = client
|
21
|
+
end
|
22
|
+
|
23
|
+
def config #:nodoc:
|
24
|
+
@config ||= Config.new self
|
25
|
+
end
|
26
|
+
|
27
|
+
def storage #:nodoc:
|
28
|
+
@storage ||= Storage.new self
|
8
29
|
end
|
9
30
|
|
10
31
|
# Get a value.
|
11
32
|
#
|
12
33
|
# Example:
|
13
|
-
#
|
14
|
-
def
|
15
|
-
|
34
|
+
# cache.get 'hello'
|
35
|
+
def get(k)
|
36
|
+
storage.get k
|
16
37
|
end
|
17
38
|
|
18
39
|
# Store a value. Note that this will Marshal it.
|
19
40
|
#
|
20
41
|
# Example:
|
21
|
-
#
|
22
|
-
#
|
23
|
-
def
|
24
|
-
|
42
|
+
# cache.set 'hello', 'world'
|
43
|
+
# cache.set 'hello', 'world', 80 # seconds til it expires
|
44
|
+
def set(k, v, ttl = nil)
|
45
|
+
storage.set k, v, ttl
|
25
46
|
end
|
26
47
|
|
27
48
|
# Delete a value.
|
28
49
|
#
|
29
50
|
# Example:
|
30
|
-
#
|
31
|
-
def
|
32
|
-
|
51
|
+
# cache.delete 'hello'
|
52
|
+
def delete(k)
|
53
|
+
storage.delete k
|
33
54
|
end
|
34
55
|
|
35
56
|
# Flush the cache.
|
36
57
|
#
|
37
58
|
# Example:
|
38
|
-
#
|
39
|
-
def
|
40
|
-
|
59
|
+
# cache.flush
|
60
|
+
def flush
|
61
|
+
storage.flush
|
41
62
|
end
|
42
63
|
end
|
data/lib/cache/config.rb
CHANGED
@@ -1,39 +1,34 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# Here's where you set config options.
|
1
|
+
class Cache
|
2
|
+
# Here's where config options are kept.
|
4
3
|
#
|
5
4
|
# Example:
|
6
|
-
#
|
7
|
-
# Cache.config.default_ttl = 120 # seconds
|
8
|
-
#
|
9
|
-
# You'd probably put this in your Rails config/initializers, for example.
|
5
|
+
# cache.config.default_ttl = 120 # seconds
|
10
6
|
class Config
|
11
|
-
|
7
|
+
|
8
|
+
attr_reader :parent
|
9
|
+
|
10
|
+
def initialize(parent) #:nodoc:
|
11
|
+
@parent = parent
|
12
|
+
end
|
12
13
|
|
13
14
|
# The cache client to use.
|
14
15
|
#
|
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
|
-
# * redis[https://github.com/ezmobius/redis-rb]
|
16
|
+
# Note that you normally just set this when you initialize a Cache object.
|
22
17
|
#
|
23
18
|
# Example:
|
24
|
-
#
|
25
|
-
def client=(client)
|
19
|
+
# cache.config.client = Memcached.new '127.0.0.1:11211'
|
20
|
+
def client=(client) #:nodoc:
|
26
21
|
@client = client
|
27
22
|
end
|
28
23
|
|
29
24
|
def client #:nodoc:
|
30
|
-
@client
|
25
|
+
@client || raise("You didn't select a cache client")
|
31
26
|
end
|
32
27
|
|
33
28
|
# TTL for method caches. Defaults to 60 seconds.
|
34
29
|
#
|
35
30
|
# Example:
|
36
|
-
#
|
31
|
+
# cache.config.default_ttl = 120 # seconds
|
37
32
|
def default_ttl=(seconds)
|
38
33
|
@default_ttl = seconds
|
39
34
|
end
|
data/lib/cache/storage.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
-
|
2
|
-
module Cache
|
1
|
+
class Cache
|
3
2
|
class Storage #:nodoc: all
|
4
|
-
|
5
|
-
|
3
|
+
|
4
|
+
attr_reader :parent
|
5
|
+
|
6
|
+
def initialize(parent)
|
7
|
+
@parent = parent
|
8
|
+
@pid = ::Process.pid
|
9
|
+
@thread_object_id = ::Thread.current.object_id
|
10
|
+
end
|
11
|
+
|
6
12
|
def get(k)
|
7
13
|
if defined?(::Memcached) and bare_client.is_a?(::Memcached)
|
8
14
|
begin; bare_client.get(k); rescue ::Memcached::NotFound; nil; end
|
@@ -20,7 +26,7 @@ module Cache
|
|
20
26
|
end
|
21
27
|
|
22
28
|
def set(k, v, ttl)
|
23
|
-
ttl ||=
|
29
|
+
ttl ||= parent.config.default_ttl
|
24
30
|
if defined?(::Redis) and bare_client.is_a?(::Redis)
|
25
31
|
if ttl == 0
|
26
32
|
bare_client.set k, ::Marshal.dump(v)
|
@@ -56,35 +62,37 @@ module Cache
|
|
56
62
|
bare_client.send %w{ flush flushdb flush_all clear }.detect { |flush_cmd| bare_client.respond_to? flush_cmd }
|
57
63
|
end
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
fork_detected = true
|
64
|
-
::Thread.current[:cache_storage_bare_client] = nil
|
65
|
+
private
|
66
|
+
|
67
|
+
def fork_detected?
|
68
|
+
if @pid != ::Process.pid
|
65
69
|
@pid = ::Process.pid
|
66
70
|
end
|
67
|
-
::Thread.current[:cache_storage_bare_client] ||= fresh_bare_client(fork_detected)
|
68
71
|
end
|
69
72
|
|
70
|
-
def
|
71
|
-
if
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
73
|
+
def new_thread_detected?
|
74
|
+
if @thread_object_id != ::Thread.current.object_id
|
75
|
+
@thread_object_id = ::Thread.current.object_id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def bare_client
|
80
|
+
fork_detected = fork_detected?
|
81
|
+
new_thread_detected = new_thread_detected?
|
82
|
+
if defined?(::Dalli) and parent.config.client.is_a?(::Dalli::Client)
|
83
|
+
parent.config.client.close if fork_detected
|
84
|
+
elsif defined?(::ActiveSupport::Cache::DalliStore) and parent.config.client.is_a?(::ActiveSupport::Cache::DalliStore)
|
85
|
+
parent.config.client.reset if fork_detected
|
86
|
+
elsif defined?(::Memcached) and (parent.config.client.is_a?(::Memcached) or parent.config.client.is_a?(::Memcached::Rails))
|
87
|
+
parent.config.client = parent.config.client.clone if fork_detected or new_thread_detected
|
88
|
+
elsif defined?(::Redis) and parent.config.client.is_a?(::Redis)
|
89
|
+
parent.config.client.client.connect if fork_detected
|
90
|
+
elsif defined?(::MemCache) and parent.config.client.is_a?(::MemCache)
|
91
|
+
parent.config.client.reset if fork_detected
|
85
92
|
else
|
86
|
-
raise "Don't know how to thread/fork #{
|
93
|
+
raise "Don't know how to thread/fork #{parent.config.client.inspect}"
|
87
94
|
end
|
95
|
+
parent.config.client
|
88
96
|
end
|
89
97
|
end
|
90
98
|
end
|
data/lib/cache/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.0.
|
1
|
+
class Cache
|
2
|
+
VERSION = "0.0.2"
|
3
3
|
end
|
data/test/helper.rb
CHANGED
data/test/shared_tests.rb
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
module SharedTests
|
2
2
|
def test_get
|
3
|
-
assert_equal nil,
|
4
|
-
|
5
|
-
assert_equal 'world',
|
3
|
+
assert_equal nil, @cache.get('hello')
|
4
|
+
@cache.set 'hello', 'world'
|
5
|
+
assert_equal 'world', @cache.get('hello')
|
6
6
|
end
|
7
7
|
|
8
8
|
def test_set
|
9
9
|
assert_nothing_raised do
|
10
|
-
|
10
|
+
@cache.set 'hello', 'world'
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_set_with_ttl
|
15
|
-
|
16
|
-
assert_equal 'world',
|
15
|
+
@cache.set 'hello', 'world', 1
|
16
|
+
assert_equal 'world', @cache.get('hello')
|
17
17
|
sleep 2
|
18
|
-
assert_equal nil,
|
18
|
+
assert_equal nil, @cache.get('hello')
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_set_with_zero_ttl_meaning_eternal
|
22
|
-
|
23
|
-
assert_equal 'world',
|
22
|
+
@cache.set 'hello', 'world', 0
|
23
|
+
assert_equal 'world', @cache.get('hello')
|
24
24
|
sleep 1
|
25
|
-
assert_equal 'world',
|
25
|
+
assert_equal 'world', @cache.get('hello')
|
26
26
|
end
|
27
27
|
|
28
28
|
def test_delete
|
29
|
-
|
30
|
-
assert_equal 'world',
|
31
|
-
|
32
|
-
assert_equal nil,
|
29
|
+
@cache.set 'hello', 'world'
|
30
|
+
assert_equal 'world', @cache.get('hello')
|
31
|
+
@cache.delete 'hello'
|
32
|
+
assert_equal nil, @cache.get('hello')
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_flush
|
36
|
-
|
37
|
-
assert_equal 'world',
|
38
|
-
|
39
|
-
assert_equal nil,
|
36
|
+
@cache.set 'hello', 'world'
|
37
|
+
assert_equal 'world', @cache.get('hello')
|
38
|
+
@cache.flush
|
39
|
+
assert_equal nil, @cache.get('hello')
|
40
40
|
end
|
41
41
|
end
|
data/test/test_dalli_storage.rb
CHANGED
@@ -4,31 +4,29 @@ require 'dalli'
|
|
4
4
|
|
5
5
|
class TestDalliStorage < Test::Unit::TestCase
|
6
6
|
def setup
|
7
|
+
@client = Dalli::Client.new ['localhost:11211']
|
7
8
|
super
|
8
|
-
client = Dalli::Client.new ['localhost:11211']
|
9
|
-
client.flush
|
10
|
-
Cache.config.client = client
|
11
9
|
end
|
12
10
|
|
13
11
|
include SharedTests
|
14
12
|
|
15
13
|
def get_ring_object_id
|
16
|
-
|
14
|
+
@cache.config.client.instance_variable_get(:@ring).object_id
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_treats_as_thread_safe
|
20
18
|
# make sure ring is initialized
|
21
|
-
|
19
|
+
@cache.get 'hi'
|
22
20
|
|
23
21
|
# get the main thread's ring
|
24
22
|
main_thread_ring_id = get_ring_object_id
|
25
23
|
|
26
24
|
# sanity check that it's not changing every time
|
27
|
-
|
25
|
+
@cache.get 'hi'
|
28
26
|
assert_equal main_thread_ring_id, get_ring_object_id
|
29
27
|
|
30
28
|
# create a new thread and get its ring
|
31
|
-
new_thread_ring_id = Thread.new {
|
29
|
+
new_thread_ring_id = Thread.new { @cache.get 'hi'; get_ring_object_id }.value
|
32
30
|
|
33
31
|
# make sure the ring was reinitialized
|
34
32
|
assert_equal main_thread_ring_id, new_thread_ring_id
|
@@ -36,18 +34,18 @@ class TestDalliStorage < Test::Unit::TestCase
|
|
36
34
|
|
37
35
|
def test_treats_as_not_fork_safe
|
38
36
|
# make sure ring is initialized
|
39
|
-
|
37
|
+
@cache.get 'hi'
|
40
38
|
|
41
39
|
# get the main thread's ring
|
42
40
|
parent_process_ring_id = get_ring_object_id
|
43
41
|
|
44
42
|
# sanity check that it's not changing every time
|
45
|
-
|
43
|
+
@cache.get 'hi'
|
46
44
|
assert_equal parent_process_ring_id, get_ring_object_id
|
47
45
|
|
48
46
|
# fork a new process
|
49
47
|
pid = Kernel.fork do
|
50
|
-
|
48
|
+
@cache.get 'hi'
|
51
49
|
raise "Didn't split!" if parent_process_ring_id == get_ring_object_id
|
52
50
|
end
|
53
51
|
Process.wait pid
|
@@ -6,32 +6,30 @@ require 'active_support/cache/dalli_store'
|
|
6
6
|
|
7
7
|
class TestDalliStoreStorage < Test::Unit::TestCase
|
8
8
|
def setup
|
9
|
+
@client = ActiveSupport::Cache::DalliStore.new ['localhost:11211']
|
9
10
|
super
|
10
|
-
client = ActiveSupport::Cache::DalliStore.new ['localhost:11211']
|
11
|
-
client.clear
|
12
|
-
Cache.config.client = client
|
13
11
|
end
|
14
12
|
|
15
13
|
include SharedTests
|
16
14
|
|
17
15
|
def get_ring_object_id
|
18
|
-
hidden_dalli_client =
|
16
|
+
hidden_dalli_client = @cache.config.client.instance_variable_get :@data
|
19
17
|
hidden_dalli_client.instance_variable_get(:@ring).object_id
|
20
18
|
end
|
21
19
|
|
22
20
|
def test_treats_as_thread_safe
|
23
21
|
# make sure ring is initialized
|
24
|
-
|
22
|
+
@cache.get 'hi'
|
25
23
|
|
26
24
|
# get the main thread's ring
|
27
25
|
main_thread_ring_id = get_ring_object_id
|
28
26
|
|
29
27
|
# sanity check that it's not changing every time
|
30
|
-
|
28
|
+
@cache.get 'hi'
|
31
29
|
assert_equal main_thread_ring_id, get_ring_object_id
|
32
30
|
|
33
31
|
# create a new thread and get its ring
|
34
|
-
new_thread_ring_id = Thread.new {
|
32
|
+
new_thread_ring_id = Thread.new { @cache.get 'hi'; get_ring_object_id }.value
|
35
33
|
|
36
34
|
# make sure the ring was reinitialized
|
37
35
|
assert_equal main_thread_ring_id, new_thread_ring_id
|
@@ -39,18 +37,18 @@ class TestDalliStoreStorage < Test::Unit::TestCase
|
|
39
37
|
|
40
38
|
def test_treats_as_not_fork_safe
|
41
39
|
# make sure ring is initialized
|
42
|
-
|
40
|
+
@cache.get 'hi'
|
43
41
|
|
44
42
|
# get the main thread's ring
|
45
43
|
parent_process_ring_id = get_ring_object_id
|
46
44
|
|
47
45
|
# sanity check that it's not changing every time
|
48
|
-
|
46
|
+
@cache.get 'hi'
|
49
47
|
assert_equal parent_process_ring_id, get_ring_object_id
|
50
48
|
|
51
49
|
# fork a new process
|
52
50
|
pid = Kernel.fork do
|
53
|
-
|
51
|
+
@cache.get 'hi'
|
54
52
|
raise "Didn't split!" if parent_process_ring_id == get_ring_object_id
|
55
53
|
end
|
56
54
|
Process.wait pid
|
@@ -5,31 +5,29 @@ require 'memcache'
|
|
5
5
|
|
6
6
|
class TestMemcacheStorage < Test::Unit::TestCase
|
7
7
|
def setup
|
8
|
+
@client = MemCache.new ['localhost:11211']
|
8
9
|
super
|
9
|
-
client = MemCache.new ['localhost:11211']
|
10
|
-
client.flush_all
|
11
|
-
Cache.config.client = client
|
12
10
|
end
|
13
11
|
|
14
12
|
include SharedTests
|
15
13
|
|
16
14
|
def get_server_status_ids
|
17
|
-
|
15
|
+
@cache.config.client.instance_variable_get(:@servers).map { |s| s.status.object_id }
|
18
16
|
end
|
19
17
|
|
20
18
|
def test_treats_as_thread_safe
|
21
19
|
# make sure servers are connected
|
22
|
-
|
20
|
+
@cache.get 'hi'
|
23
21
|
|
24
22
|
# get the object ids
|
25
23
|
main_thread_server_status_ids = get_server_status_ids
|
26
24
|
|
27
25
|
# sanity check that it's not changing every time
|
28
|
-
|
26
|
+
@cache.get 'hi'
|
29
27
|
assert_equal main_thread_server_status_ids, get_server_status_ids
|
30
28
|
|
31
29
|
# create a new thread and get its server ids
|
32
|
-
new_thread_server_status_ids = Thread.new {
|
30
|
+
new_thread_server_status_ids = Thread.new { @cache.get 'hi'; get_server_status_ids }.value
|
33
31
|
|
34
32
|
# make sure the server ids was reinitialized
|
35
33
|
assert_equal main_thread_server_status_ids, new_thread_server_status_ids
|
@@ -37,18 +35,18 @@ class TestMemcacheStorage < Test::Unit::TestCase
|
|
37
35
|
|
38
36
|
def test_treats_as_not_fork_safe
|
39
37
|
# make sure server ids is initialized
|
40
|
-
|
38
|
+
@cache.get 'hi'
|
41
39
|
|
42
40
|
# get the main thread's server ids
|
43
41
|
parent_process_server_status_ids = get_server_status_ids
|
44
42
|
|
45
43
|
# sanity check that it's not changing every time
|
46
|
-
|
44
|
+
@cache.get 'hi'
|
47
45
|
assert_equal parent_process_server_status_ids, get_server_status_ids
|
48
46
|
|
49
47
|
# fork a new process
|
50
48
|
pid = Kernel.fork do
|
51
|
-
|
49
|
+
@cache.get 'hi'
|
52
50
|
raise "Didn't split!" if parent_process_server_status_ids == get_server_status_ids
|
53
51
|
end
|
54
52
|
Process.wait pid
|
@@ -4,31 +4,29 @@ require 'memcached'
|
|
4
4
|
|
5
5
|
class TestMemcachedRailsStorage < Test::Unit::TestCase
|
6
6
|
def setup
|
7
|
+
@client = Memcached::Rails.new 'localhost:11211'
|
7
8
|
super
|
8
|
-
client = Memcached::Rails.new 'localhost:11211'
|
9
|
-
client.flush
|
10
|
-
Cache.config.client = client
|
11
9
|
end
|
12
10
|
|
13
11
|
include SharedTests
|
14
12
|
|
15
13
|
def get_bare_client_id
|
16
|
-
|
14
|
+
@cache.storage.send(:bare_client).object_id
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_treats_as_not_thread_safe
|
20
18
|
# make sure bare client is initialized
|
21
|
-
|
19
|
+
@cache.get 'hi'
|
22
20
|
|
23
21
|
# get the main thread's bare client
|
24
22
|
main_thread_bare_client_id = get_bare_client_id
|
25
23
|
|
26
24
|
# sanity check that it's not changing every time
|
27
|
-
|
25
|
+
@cache.get 'hi'
|
28
26
|
assert_equal main_thread_bare_client_id, get_bare_client_id
|
29
27
|
|
30
28
|
# create a new thread and get its bare client
|
31
|
-
new_thread_bare_client_id = Thread.new {
|
29
|
+
new_thread_bare_client_id = Thread.new { @cache.get 'hi'; get_bare_client_id }.value
|
32
30
|
|
33
31
|
# make sure the bare client was reinitialized
|
34
32
|
assert(main_thread_bare_client_id != new_thread_bare_client_id)
|
@@ -36,18 +34,18 @@ class TestMemcachedRailsStorage < Test::Unit::TestCase
|
|
36
34
|
|
37
35
|
def test_treats_as_not_fork_safe
|
38
36
|
# make sure bare client is initialized
|
39
|
-
|
37
|
+
@cache.get 'hi'
|
40
38
|
|
41
39
|
# get the main process's bare client
|
42
40
|
parent_process_bare_client_id = get_bare_client_id
|
43
41
|
|
44
42
|
# sanity check that it's not changing every time
|
45
|
-
|
43
|
+
@cache.get 'hi'
|
46
44
|
assert_equal parent_process_bare_client_id, get_bare_client_id
|
47
45
|
|
48
46
|
# fork a new process
|
49
47
|
pid = Kernel.fork do
|
50
|
-
|
48
|
+
@cache.get 'hi'
|
51
49
|
raise "Didn't split!" if parent_process_bare_client_id == get_bare_client_id
|
52
50
|
end
|
53
51
|
Process.wait pid
|
@@ -4,31 +4,29 @@ require 'memcached'
|
|
4
4
|
|
5
5
|
class TestMemcachedStorage < Test::Unit::TestCase
|
6
6
|
def setup
|
7
|
+
@client = Memcached.new 'localhost:11211'
|
7
8
|
super
|
8
|
-
client = Memcached.new 'localhost:11211'
|
9
|
-
client.flush
|
10
|
-
Cache.config.client = client
|
11
9
|
end
|
12
10
|
|
13
11
|
include SharedTests
|
14
12
|
|
15
13
|
def get_bare_client_id
|
16
|
-
|
14
|
+
@cache.storage.send(:bare_client).object_id
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_treats_as_not_thread_safe
|
20
18
|
# make sure bare client is initialized
|
21
|
-
|
19
|
+
@cache.get 'hi'
|
22
20
|
|
23
21
|
# get the main thread's bare client
|
24
22
|
main_thread_bare_client_id = get_bare_client_id
|
25
23
|
|
26
24
|
# sanity check that it's not changing every time
|
27
|
-
|
25
|
+
@cache.get 'hi'
|
28
26
|
assert_equal main_thread_bare_client_id, get_bare_client_id
|
29
27
|
|
30
28
|
# create a new thread and get its bare client
|
31
|
-
new_thread_bare_client_id = Thread.new {
|
29
|
+
new_thread_bare_client_id = Thread.new { @cache.get 'hi'; get_bare_client_id }.value
|
32
30
|
|
33
31
|
# make sure the bare client was reinitialized
|
34
32
|
assert(main_thread_bare_client_id != new_thread_bare_client_id)
|
@@ -36,18 +34,18 @@ class TestMemcachedStorage < Test::Unit::TestCase
|
|
36
34
|
|
37
35
|
def test_treats_as_not_fork_safe
|
38
36
|
# make sure bare client is initialized
|
39
|
-
|
37
|
+
@cache.get 'hi'
|
40
38
|
|
41
39
|
# get the main process's bare client
|
42
40
|
parent_process_bare_client_id = get_bare_client_id
|
43
41
|
|
44
42
|
# sanity check that it's not changing every time
|
45
|
-
|
43
|
+
@cache.get 'hi'
|
46
44
|
assert_equal parent_process_bare_client_id, get_bare_client_id
|
47
45
|
|
48
46
|
# fork a new process
|
49
47
|
pid = Kernel.fork do
|
50
|
-
|
48
|
+
@cache.get 'hi'
|
51
49
|
raise "Didn't split!" if parent_process_bare_client_id == get_bare_client_id
|
52
50
|
end
|
53
51
|
Process.wait pid
|
data/test/test_redis_storage.rb
CHANGED
@@ -6,18 +6,16 @@ if ENV['REDIS_URL']
|
|
6
6
|
|
7
7
|
class TestRedisStorage < Test::Unit::TestCase
|
8
8
|
def setup
|
9
|
-
super
|
10
9
|
uri = URI.parse(ENV["REDIS_URL"])
|
11
|
-
client = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
|
12
|
-
|
13
|
-
Cache.config.client = client
|
10
|
+
@client = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
|
11
|
+
super
|
14
12
|
end
|
15
13
|
|
16
14
|
include SharedTests
|
17
15
|
|
18
16
|
# client DOT client
|
19
17
|
def get_redis_client_connection_socket_id
|
20
|
-
connection =
|
18
|
+
connection = @cache.config.client.client.instance_variable_get :@connection
|
21
19
|
sock = connection.instance_variable_get(:@sock)
|
22
20
|
# $stderr.puts sock.inspect
|
23
21
|
sock.object_id
|
@@ -25,17 +23,17 @@ if ENV['REDIS_URL']
|
|
25
23
|
|
26
24
|
def test_treats_as_thread_safe
|
27
25
|
# make sure ring is initialized
|
28
|
-
|
26
|
+
@cache.get 'hi'
|
29
27
|
|
30
28
|
# get the main thread's ring
|
31
29
|
main_thread_redis_client_connection_socket_id = get_redis_client_connection_socket_id
|
32
30
|
|
33
31
|
# sanity check that it's not changing every time
|
34
|
-
|
32
|
+
@cache.get 'hi'
|
35
33
|
assert_equal main_thread_redis_client_connection_socket_id, get_redis_client_connection_socket_id
|
36
34
|
|
37
35
|
# create a new thread and get its ring
|
38
|
-
new_thread_redis_client_connection_socket_id = Thread.new {
|
36
|
+
new_thread_redis_client_connection_socket_id = Thread.new { @cache.get 'hi'; get_redis_client_connection_socket_id }.value
|
39
37
|
|
40
38
|
# make sure the ring was reinitialized
|
41
39
|
assert_equal main_thread_redis_client_connection_socket_id, new_thread_redis_client_connection_socket_id
|
@@ -43,18 +41,18 @@ if ENV['REDIS_URL']
|
|
43
41
|
|
44
42
|
def test_treats_as_not_fork_safe
|
45
43
|
# make sure ring is initialized
|
46
|
-
|
44
|
+
@cache.get 'hi'
|
47
45
|
|
48
46
|
# get the main thread's ring
|
49
47
|
parent_process_redis_client_connection_socket_id = get_redis_client_connection_socket_id
|
50
48
|
|
51
49
|
# sanity check that it's not changing every time
|
52
|
-
|
50
|
+
@cache.get 'hi'
|
53
51
|
assert_equal parent_process_redis_client_connection_socket_id, get_redis_client_connection_socket_id
|
54
52
|
|
55
53
|
# fork a new process
|
56
54
|
pid = Kernel.fork do
|
57
|
-
|
55
|
+
@cache.get 'hi'
|
58
56
|
raise "Didn't split!" if parent_process_redis_client_connection_socket_id == get_redis_client_connection_socket_id
|
59
57
|
end
|
60
58
|
Process.wait pid
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Seamus Abshere
|