cache 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -0
- data/README.md +47 -28
- data/benchmarks/afterrefactor.txt +86 -0
- data/benchmarks/midrefactor.txt +89 -0
- data/cache.gemspec +0 -8
- data/lib/cache.rb +86 -65
- data/lib/cache/active_support_cache_dalli_store.rb +14 -0
- data/lib/cache/active_support_cache_memory_store.rb +10 -0
- data/lib/cache/active_support_cache_store.rb +37 -0
- data/lib/cache/config.rb +0 -32
- data/lib/cache/dalli_client.rb +46 -0
- data/lib/cache/mem_cache.rb +41 -0
- data/lib/cache/memcached.rb +47 -0
- data/lib/cache/memcached_rails.rb +33 -0
- data/lib/cache/redis.rb +38 -0
- data/lib/cache/redis_namespace.rb +6 -0
- data/lib/cache/version.rb +1 -1
- data/test/helper.rb +4 -0
- data/test/shared_tests.rb +1 -18
- data/test/test_dalli_storage.rb +1 -1
- data/test/test_dalli_store_storage.rb +1 -1
- data/test/test_default_storage.rb +5 -5
- data/test/test_memcache_storage.rb +1 -1
- data/test/test_memcached_rails_storage.rb +1 -1
- data/test/test_memcached_storage.rb +4 -1
- data/test/test_rails_cache_storage.rb +17 -15
- data/test/test_redis_storage.rb +1 -1
- metadata +13 -131
- data/lib/cache/storage.rb +0 -260
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Aims to let other libraries be cache-agnostic in return for a performance hit.
|
|
6
6
|
|
7
7
|
## Real world usage
|
8
8
|
|
9
|
-
Used by [lock_method](https://github.com/seamusabshere/lock_method) and
|
9
|
+
Used by [lock_method](https://github.com/seamusabshere/lock_method) and [cache_method](https://github.com/seamusabshere/cache_method) so that you can use them with memcached, redis, etc.
|
10
10
|
|
11
11
|
In production use at [carbon.brighterplanet.com](http://carbon.brighterplanet.com) and [data.brighterplanet.com](http://data.brighterplanet.com).
|
12
12
|
|
@@ -37,37 +37,56 @@ I wanted a common interface to a bunch of great Ruby cache clients so I can deve
|
|
37
37
|
* I'm tired of forgetting whether it's :expires_in or :ttl
|
38
38
|
* I don't know why we ever started using read/write instead of get/set.
|
39
39
|
* I don't like how you have to manually handle after_fork for Redis, Memcached, etc.
|
40
|
-
* I don't know why Memcached::Rails
|
40
|
+
* I don't know why Memcached::Rails doesn't act like a ActiveRecord::Cache::Store
|
41
41
|
* Why are you asking me about :raw or whatever? Just marshal it
|
42
42
|
|
43
43
|
## Speed
|
44
44
|
|
45
|
-
It's
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
set: cache:
|
50
|
-
set: dalli:bin
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
get:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
get:
|
65
|
-
get:
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
45
|
+
It's more than 50% slower than raw [Memcached](https://github.com/evan/memcached) and about the same as raw [Dalli](https://github.com/mperham/dalli)
|
46
|
+
|
47
|
+
# raw dalli versus wrapped
|
48
|
+
|
49
|
+
set: cache:dalli:bin 2.150000 0.840000 2.990000 ( 3.752008) <- Cache.wrap(Dalli::Client.new)
|
50
|
+
set: dalli:bin 2.120000 0.830000 2.950000 ( 3.734024) <- Dalli::Client.new
|
51
|
+
|
52
|
+
get: cache:dalli:bin 2.040000 0.910000 2.950000 ( 3.646148)
|
53
|
+
get: dalli:bin 2.040000 0.900000 2.940000 ( 3.632840)
|
54
|
+
|
55
|
+
delete: cache:dalli:bin 1.830000 0.880000 2.710000 ( 3.381917)
|
56
|
+
delete: dalli:bin 1.790000 0.880000 2.670000 ( 3.327514)
|
57
|
+
|
58
|
+
get-missing: cache:dalli:bin 1.780000 0.880000 2.660000 ( 3.344041)
|
59
|
+
get-missing: dalli:bin 1.760000 0.880000 2.640000 ( 3.337539)
|
60
|
+
|
61
|
+
set-large: cache:dalli:bin 2.750000 0.880000 3.630000 ( 4.474265)
|
62
|
+
set-large: dalli:bin 2.720000 0.870000 3.590000 ( 4.436163)
|
63
|
+
|
64
|
+
get-large: cache:dalli:bin 2.420000 0.990000 3.410000 ( 4.135326)
|
65
|
+
get-large: dalli:bin 2.410000 0.990000 3.400000 ( 4.119832)
|
66
|
+
|
67
|
+
# raw memcached versus wrapped
|
68
|
+
|
69
|
+
set: cache:libm:bin 0.860000 0.640000 1.500000 ( 3.033145) <- Cache.wrap(Memcached.new(:binary_protocol => true))
|
70
|
+
set: libm:bin 0.200000 0.480000 0.680000 ( 1.907099) <- Memcached.new(:binary_protocol => true)
|
71
|
+
|
72
|
+
get: cache:libm:bin 0.800000 0.680000 1.480000 ( 2.700458)
|
73
|
+
get: libm:bin 0.260000 0.660000 0.920000 ( 1.974025)
|
74
|
+
|
75
|
+
delete: cache:libm:bin 1.000000 0.600000 1.600000 ( 2.968057)
|
76
|
+
delete: libm:bin 0.600000 0.560000 1.160000 ( 2.375070)
|
77
|
+
|
78
|
+
get-missing: cache:libm:bin 0.980000 0.800000 1.780000 ( 2.850947)
|
79
|
+
get-missing: libm:bin 0.640000 0.710000 1.350000 ( 2.520733)
|
80
|
+
|
81
|
+
set-large: cache:libm:bin 1.220000 0.590000 1.810000 ( 3.404739)
|
82
|
+
set-large: libm:bin 0.230000 0.520000 0.750000 ( 2.111738)
|
83
|
+
|
84
|
+
get-large: cache:libm:bin 3.780000 0.870000 4.650000 ( 6.073208)
|
85
|
+
get-large: libm:bin 0.340000 0.830000 1.170000 ( 2.304408)
|
86
|
+
|
87
|
+
Thanks to https://github.com/evan/memcached/blob/master/test/profile/benchmark.rb
|
88
|
+
|
89
|
+
So: hopefully it makes it easier to get started with caching and hit the low-hanging fruit. Then you can move on to a raw client!
|
71
90
|
|
72
91
|
## Features
|
73
92
|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
Darwin alzabo0 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:32:41 PDT 2011; root:xnu-1504.15.3~1/RELEASE_X86_64 x86_64
|
2
|
+
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin10.8.0]
|
3
|
+
RUBYOPT=-ropenssl
|
4
|
+
RUBY_VERSION=ruby-1.9.3-p125
|
5
|
+
Ruby 1.9.3p125
|
6
|
+
Loaded memcached 1.4.1
|
7
|
+
Loaded memcache-client 1.8.5
|
8
|
+
Loaded cache 0.2.7
|
9
|
+
Loaded kgio 2.7.4
|
10
|
+
Loaded dalli 2.0.2
|
11
|
+
Loops is 20000
|
12
|
+
Stack depth is 0
|
13
|
+
Small value size is: 19 bytes
|
14
|
+
Large value size is: 4189 bytes
|
15
|
+
user system total real
|
16
|
+
set: cache:dalli:bin 2.140000 0.840000 2.980000 ( 3.750850)
|
17
|
+
set: cache:libm:bin 0.860000 0.630000 1.490000 ( 3.024450)
|
18
|
+
set: dalli:bin 2.120000 0.840000 2.960000 ( 3.727571)
|
19
|
+
set: libm:ascii 0.300000 0.530000 0.830000 ( 2.274182)
|
20
|
+
set: libm:ascii:pipeline 0.110000 0.000000 0.110000 ( 0.111021)
|
21
|
+
set: libm:ascii:udp 0.200000 0.290000 0.490000 ( 1.129215)
|
22
|
+
set: libm:bin 0.200000 0.490000 0.690000 ( 1.929198)
|
23
|
+
set: libm:bin:buffer 0.070000 0.170000 0.240000 ( 0.318657)
|
24
|
+
set: mclient:ascii 4.870000 0.840000 5.710000 ( 5.791865)
|
25
|
+
|
26
|
+
get: cache:dalli:bin 2.030000 0.910000 2.940000 ( 3.639529)
|
27
|
+
get: cache:libm:bin 0.810000 0.680000 1.490000 ( 2.721883)
|
28
|
+
get: dalli:bin 2.010000 0.910000 2.920000 ( 3.630398)
|
29
|
+
get: libm:ascii 0.350000 0.500000 0.850000 ( 1.977741)
|
30
|
+
get: libm:ascii:pipeline 0.360000 0.700000 1.060000 ( 2.278924)
|
31
|
+
get: libm:ascii:udp 0.280000 0.300000 0.580000 ( 1.102862)
|
32
|
+
get: libm:bin 0.260000 0.660000 0.920000 ( 1.985586)
|
33
|
+
get: libm:bin:buffer 0.300000 0.890000 1.190000 ( 2.051324)
|
34
|
+
get: mclient:ascii 5.710000 0.950000 6.660000 ( 6.724394)
|
35
|
+
|
36
|
+
delete: cache:dalli:bin 1.820000 0.890000 2.710000 ( 3.373237)
|
37
|
+
delete: cache:libm:bin 0.960000 0.590000 1.550000 ( 2.928492)
|
38
|
+
delete: dalli:bin 1.790000 0.880000 2.670000 ( 3.338832)
|
39
|
+
delete: libm:ascii 0.620000 0.580000 1.200000 ( 2.428661)
|
40
|
+
delete: libm:ascii:pipeline 0.070000 0.000000 0.070000 ( 0.077325)
|
41
|
+
delete: libm:ascii:udp 0.490000 0.360000 0.850000 ( 1.310359)
|
42
|
+
delete: libm:bin 0.590000 0.560000 1.150000 ( 2.369949)
|
43
|
+
delete: libm:bin:buffer 0.600000 0.830000 1.430000 ( 2.457385)
|
44
|
+
delete: mclient:ascii 4.700000 0.820000 5.520000 ( 5.581853)
|
45
|
+
|
46
|
+
get-missing: cache:dalli:bin 1.770000 0.880000 2.650000 ( 3.331386)
|
47
|
+
get-missing: cache:libm:bin 0.970000 0.800000 1.770000 ( 2.860777)
|
48
|
+
get-missing: dalli:bin 1.760000 0.880000 2.640000 ( 3.337003)
|
49
|
+
get-missing: libm:ascii 0.660000 0.630000 1.290000 ( 2.495618)
|
50
|
+
get-missing: libm:ascii:pipeline 0.670000 0.790000 1.460000 ( 2.523977)
|
51
|
+
get-missing: libm:ascii:udp 0.540000 0.370000 0.910000 ( 1.356731)
|
52
|
+
get-missing: libm:bin 0.630000 0.730000 1.360000 ( 2.530438)
|
53
|
+
get-missing: libm:bin:buffer 0.650000 0.860000 1.510000 ( 2.535072)
|
54
|
+
get-missing: mclient:ascii 4.840000 0.840000 5.680000 ( 5.757437)
|
55
|
+
|
56
|
+
set-large: cache:dalli:bin 2.770000 0.930000 3.700000 ( 4.579959)
|
57
|
+
set-large: cache:libm:bin 1.220000 0.600000 1.820000 ( 3.422516)
|
58
|
+
set-large: dalli:bin 2.720000 0.930000 3.650000 ( 4.510348)
|
59
|
+
set-large: libm:ascii 0.330000 0.530000 0.860000 ( 2.404037)
|
60
|
+
set-large: libm:ascii:pipeline 0.160000 0.140000 0.300000 ( 0.304724)
|
61
|
+
set-large: libm:ascii:udp 0.220000 0.330000 0.550000 ( 1.246952)
|
62
|
+
set-large: libm:bin 0.230000 0.530000 0.760000 ( 2.118547)
|
63
|
+
set-large: libm:bin:buffer 0.120000 0.250000 0.370000 ( 0.453106)
|
64
|
+
set-large: mclient:ascii 5.190000 0.860000 6.050000 ( 6.136922)
|
65
|
+
|
66
|
+
get-large: cache:dalli:bin 2.420000 1.020000 3.440000 ( 4.181324)
|
67
|
+
get-large: cache:libm:bin 3.790000 0.900000 4.690000 ( 6.141065)
|
68
|
+
get-large: dalli:bin 2.390000 1.020000 3.410000 ( 4.140461)
|
69
|
+
get-large: libm:ascii 0.390000 0.640000 1.030000 ( 2.091129)
|
70
|
+
get-large: libm:ascii:pipeline 0.400000 0.760000 1.160000 ( 2.050111)
|
71
|
+
get-large: libm:ascii:udp 0.340000 0.440000 0.780000 ( 1.300560)
|
72
|
+
get-large: libm:bin 0.330000 0.830000 1.160000 ( 2.316933)
|
73
|
+
get-large: libm:bin:buffer 0.370000 1.090000 1.460000 ( 2.420931)
|
74
|
+
get-large: mclient:ascii 6.800000 1.280000 8.080000 ( 8.175742)
|
75
|
+
|
76
|
+
hash:default 0.190000 0.000000 0.190000 ( 0.194626)
|
77
|
+
hash:md5 0.340000 0.000000 0.340000 ( 0.337795)
|
78
|
+
hash:crc 0.210000 0.000000 0.210000 ( 0.214550)
|
79
|
+
hash:fnv1_64 0.160000 0.000000 0.160000 ( 0.151460)
|
80
|
+
hash:fnv1a_64 0.130000 0.000000 0.130000 ( 0.132338)
|
81
|
+
hash:fnv1_32 0.130000 0.000000 0.130000 ( 0.131782)
|
82
|
+
hash:fnv1a_32 0.130000 0.000000 0.130000 ( 0.132192)
|
83
|
+
hash:hsieh 0.060000 0.000000 0.060000 ( 0.057399)
|
84
|
+
hash:murmur 0.090000 0.000000 0.090000 ( 0.087435)
|
85
|
+
hash:jenkins 0.100000 0.000000 0.100000 ( 0.098543)
|
86
|
+
hash:none 0.060000 0.000000 0.060000 ( 0.057412)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
alzabo0:~/code/cache (master) $ ruby test/profile/benchmark.rb
|
2
|
+
Darwin alzabo0 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:32:41 PDT 2011; root:xnu-1504.15.3~1/RELEASE_X86_64 x86_64
|
3
|
+
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin10.8.0]
|
4
|
+
RUBYOPT=-ropenssl
|
5
|
+
RUBY_VERSION=ruby-1.9.3-p125
|
6
|
+
Ruby 1.9.3p125
|
7
|
+
Loaded memcached 1.4.1
|
8
|
+
Loaded memcache-client 1.8.5
|
9
|
+
Loaded cache 0.2.6
|
10
|
+
Loaded kgio 2.7.4
|
11
|
+
Loaded dalli 2.0.2
|
12
|
+
Loops is 20000
|
13
|
+
Stack depth is 0
|
14
|
+
Small value size is: 19 bytes
|
15
|
+
Large value size is: 4189 bytes
|
16
|
+
No matching processes belonging to you were found
|
17
|
+
user system total real
|
18
|
+
set: cache:dalli:bin 2.200000 0.830000 3.030000 ( 3.818512)
|
19
|
+
set: cache:libm:bin 0.630000 0.550000 1.180000 ( 2.579593)
|
20
|
+
set: dalli:bin 2.080000 0.830000 2.910000 ( 3.709548)
|
21
|
+
set: libm:ascii 0.290000 0.520000 0.810000 ( 2.175071)
|
22
|
+
set: libm:ascii:pipeline 0.100000 0.010000 0.110000 ( 0.105957)
|
23
|
+
set: libm:ascii:udp 0.200000 0.310000 0.510000 ( 1.116366)
|
24
|
+
set: libm:bin 0.190000 0.480000 0.670000 ( 1.779256)
|
25
|
+
set: libm:bin:buffer 0.080000 0.160000 0.240000 ( 0.313709)
|
26
|
+
set: mclient:ascii 4.310000 0.830000 5.140000 ( 5.211834)
|
27
|
+
|
28
|
+
get: cache:dalli:bin 2.070000 0.900000 2.970000 ( 3.678416)
|
29
|
+
get: cache:libm:bin 0.580000 0.680000 1.260000 ( 2.372081)
|
30
|
+
get: dalli:bin 1.940000 0.900000 2.840000 ( 3.548862)
|
31
|
+
get: libm:ascii 0.340000 0.490000 0.830000 ( 1.850806)
|
32
|
+
get: libm:ascii:pipeline 0.350000 0.680000 1.030000 ( 2.187457)
|
33
|
+
get: libm:ascii:udp 0.260000 0.330000 0.590000 ( 1.062001)
|
34
|
+
get: libm:bin 0.260000 0.670000 0.930000 ( 1.963878)
|
35
|
+
get: libm:bin:buffer 0.300000 0.930000 1.230000 ( 2.021582)
|
36
|
+
get: mclient:ascii 5.120000 0.850000 5.970000 ( 6.057993)
|
37
|
+
|
38
|
+
delete: cache:dalli:bin 1.900000 0.880000 2.780000 ( 3.450546)
|
39
|
+
delete: cache:libm:bin 0.720000 0.670000 1.390000 ( 2.628000)
|
40
|
+
delete: dalli:bin 1.730000 0.870000 2.600000 ( 3.278894)
|
41
|
+
delete: libm:ascii 0.610000 0.580000 1.190000 ( 2.382143)
|
42
|
+
delete: libm:ascii:pipeline 0.070000 0.000000 0.070000 ( 0.077245)
|
43
|
+
delete: libm:ascii:udp 0.500000 0.380000 0.880000 ( 1.311811)
|
44
|
+
delete: libm:bin 0.590000 0.570000 1.160000 ( 2.325502)
|
45
|
+
delete: libm:bin:buffer 0.580000 0.810000 1.390000 ( 2.347620)
|
46
|
+
delete: mclient:ascii 4.150000 0.810000 4.960000 ( 5.022691)
|
47
|
+
|
48
|
+
get-missing: cache:dalli:bin 1.830000 0.870000 2.700000 ( 3.410744)
|
49
|
+
get-missing: cache:libm:bin 0.730000 0.730000 1.460000 ( 2.553246)
|
50
|
+
get-missing: dalli:bin 1.710000 0.870000 2.580000 ( 3.294497)
|
51
|
+
get-missing: libm:ascii 0.670000 0.650000 1.320000 ( 2.522556)
|
52
|
+
get-missing: libm:ascii:pipeline 0.650000 0.780000 1.430000 ( 2.408539)
|
53
|
+
get-missing: libm:ascii:udp 0.530000 0.390000 0.920000 ( 1.347747)
|
54
|
+
get-missing: libm:bin 0.640000 0.730000 1.370000 ( 2.514046)
|
55
|
+
get-missing: libm:bin:buffer 0.650000 0.880000 1.530000 ( 2.530509)
|
56
|
+
get-missing: mclient:ascii 4.230000 0.820000 5.050000 ( 5.119931)
|
57
|
+
|
58
|
+
set-large: cache:dalli:bin 2.560000 0.880000 3.440000 ( 4.314613)
|
59
|
+
set-large: cache:libm:bin 0.900000 0.650000 1.550000 ( 3.082473)
|
60
|
+
set-large: dalli:bin 2.450000 0.870000 3.320000 ( 4.192634)
|
61
|
+
set-large: libm:ascii 0.320000 0.520000 0.840000 ( 2.383214)
|
62
|
+
set-large: libm:ascii:pipeline 0.160000 0.150000 0.310000 ( 0.313549)
|
63
|
+
set-large: libm:ascii:udp 0.230000 0.360000 0.590000 ( 1.254392)
|
64
|
+
set-large: libm:bin 0.230000 0.520000 0.750000 ( 2.106144)
|
65
|
+
set-large: libm:bin:buffer 0.130000 0.250000 0.380000 ( 0.448009)
|
66
|
+
set-large: mclient:ascii 4.540000 0.860000 5.400000 ( 5.492006)
|
67
|
+
|
68
|
+
get-large: cache:dalli:bin 2.320000 0.980000 3.300000 ( 4.028261)
|
69
|
+
get-large: cache:libm:bin 3.480000 0.850000 4.330000 ( 5.709700)
|
70
|
+
get-large: dalli:bin 2.200000 0.980000 3.180000 ( 3.916877)
|
71
|
+
get-large: libm:ascii 0.380000 0.640000 1.020000 ( 2.054989)
|
72
|
+
get-large: libm:ascii:pipeline 0.380000 0.760000 1.140000 ( 1.999273)
|
73
|
+
get-large: libm:ascii:udp 0.330000 0.460000 0.790000 ( 1.286472)
|
74
|
+
get-large: libm:bin 0.330000 0.860000 1.190000 ( 2.282758)
|
75
|
+
get-large: libm:bin:buffer 0.360000 1.090000 1.450000 ( 2.388201)
|
76
|
+
get-large: mclient:ascii 5.870000 1.070000 6.940000 ( 7.044938)
|
77
|
+
|
78
|
+
hash:default 0.190000 0.000000 0.190000 ( 0.198824)
|
79
|
+
hash:md5 0.370000 0.000000 0.370000 ( 0.361487)
|
80
|
+
hash:crc 0.210000 0.000000 0.210000 ( 0.219091)
|
81
|
+
hash:fnv1_64 0.150000 0.000000 0.150000 ( 0.155696)
|
82
|
+
hash:fnv1a_64 0.140000 0.000000 0.140000 ( 0.135878)
|
83
|
+
hash:fnv1_32 0.140000 0.000000 0.140000 ( 0.138691)
|
84
|
+
hash:fnv1a_32 0.130000 0.000000 0.130000 ( 0.136036)
|
85
|
+
hash:hsieh 0.060000 0.000000 0.060000 ( 0.059796)
|
86
|
+
hash:murmur 0.090000 0.000000 0.090000 ( 0.088340)
|
87
|
+
hash:jenkins 0.100000 0.000000 0.100000 ( 0.102807)
|
88
|
+
hash:none 0.050000 0.000000 0.050000 ( 0.059193)
|
89
|
+
alzabo0:~/code/cache (master) $
|
data/cache.gemspec
CHANGED
@@ -21,13 +21,5 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.add_dependency 'activesupport', '>=2.3.11' # for default memory store
|
23
23
|
s.add_dependency 'i18n' # activesupport
|
24
|
-
s.add_development_dependency 'yard'
|
25
|
-
s.add_development_dependency 'test-unit'
|
26
|
-
s.add_development_dependency 'redis'
|
27
|
-
s.add_development_dependency 'redis-namespace'
|
28
|
-
s.add_development_dependency 'dalli'
|
29
|
-
s.add_development_dependency 'memcached'
|
30
|
-
s.add_development_dependency 'memcache-client'
|
31
|
-
s.add_development_dependency 'rake'
|
32
24
|
end
|
33
25
|
|
data/lib/cache.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext'
|
1
2
|
require 'cache/config'
|
2
|
-
require 'cache/storage'
|
3
3
|
|
4
4
|
class Cache
|
5
5
|
# Create a new Cache instance by wrapping a client of your choice.
|
@@ -7,7 +7,7 @@ class Cache
|
|
7
7
|
# Defaults to an in-process memory store.
|
8
8
|
#
|
9
9
|
# Supported memcached clients:
|
10
|
-
# * memcached[https://github.com/
|
10
|
+
# * memcached[https://github.com/evan/memcached] (either a Memcached or a Memcached::Rails)
|
11
11
|
# * dalli[https://github.com/mperham/dalli] (either a Dalli::Client or an ActiveSupport::Cache::DalliStore)
|
12
12
|
# * memcache-client[https://github.com/mperham/memcache-client] (MemCache, the one commonly used by Rails)
|
13
13
|
#
|
@@ -17,20 +17,30 @@ class Cache
|
|
17
17
|
# Example:
|
18
18
|
# raw_client = Memcached.new('127.0.0.1:11211')
|
19
19
|
# cache = Cache.wrap raw_client
|
20
|
-
def self.wrap(
|
21
|
-
new
|
20
|
+
def self.wrap(metal = nil)
|
21
|
+
new metal
|
22
22
|
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def config #:nodoc:
|
29
|
-
@config ||= Config.new self
|
30
|
-
end
|
24
|
+
attr_reader :config
|
25
|
+
attr_reader :metal
|
31
26
|
|
32
|
-
def
|
33
|
-
@
|
27
|
+
def initialize(metal = nil) #:nodoc:
|
28
|
+
@pid = ::Process.pid
|
29
|
+
@config = Config.new self
|
30
|
+
@metal = if metal.is_a?(Cache)
|
31
|
+
metal.metal
|
32
|
+
elsif metal
|
33
|
+
metal
|
34
|
+
elsif defined?(::Rails) and ::Rails.respond_to?(:cache) and rails_cache = ::Rails.cache
|
35
|
+
rails_cache
|
36
|
+
else
|
37
|
+
require 'active_support/cache'
|
38
|
+
require 'active_support/cache/memory_store'
|
39
|
+
::ActiveSupport::Cache::MemoryStore.new
|
40
|
+
end
|
41
|
+
metal_class = @metal.class.name.delete('::') # Memcached::Rails -> 'MemcachedRails'
|
42
|
+
require "cache/#{metal_class.underscore}"
|
43
|
+
extend Cache.const_get(metal_class)
|
34
44
|
end
|
35
45
|
|
36
46
|
# Get a value.
|
@@ -38,34 +48,51 @@ class Cache
|
|
38
48
|
# Example:
|
39
49
|
# cache.get 'hello'
|
40
50
|
def get(k, ignored_options = nil)
|
41
|
-
|
51
|
+
handle_fork
|
52
|
+
_get k
|
42
53
|
end
|
43
|
-
|
54
|
+
|
55
|
+
alias :read :get
|
56
|
+
|
57
|
+
# Get multiple cache entries.
|
58
|
+
#
|
59
|
+
# Example:
|
60
|
+
# cache.get_multi 'hello', 'privyet'
|
61
|
+
def get_multi(*ks)
|
62
|
+
handle_fork
|
63
|
+
_get_multi ks
|
64
|
+
end
|
65
|
+
|
44
66
|
# Store a value. Note that this will Marshal it.
|
45
67
|
#
|
46
68
|
# Example:
|
47
69
|
# cache.set 'hello', 'world'
|
48
70
|
# cache.set 'hello', 'world', 80 # seconds til it expires
|
49
71
|
def set(k, v, ttl = nil, ignored_options = nil)
|
50
|
-
|
72
|
+
handle_fork
|
73
|
+
_set k, v, extract_ttl(ttl)
|
51
74
|
end
|
52
|
-
|
75
|
+
|
76
|
+
alias :write :set
|
77
|
+
|
53
78
|
# Delete a value.
|
54
79
|
#
|
55
80
|
# Example:
|
56
81
|
# cache.delete 'hello'
|
57
82
|
def delete(k, ignored_options = nil)
|
58
|
-
|
83
|
+
handle_fork
|
84
|
+
_delete k
|
59
85
|
end
|
60
|
-
|
86
|
+
|
61
87
|
# Flush the cache.
|
62
88
|
#
|
63
89
|
# Example:
|
64
90
|
# cache.flush
|
65
91
|
def flush
|
66
|
-
|
92
|
+
handle_fork
|
93
|
+
_flush
|
67
94
|
end
|
68
|
-
|
95
|
+
|
69
96
|
alias :clear :flush
|
70
97
|
|
71
98
|
# Check if something exists.
|
@@ -73,15 +100,19 @@ class Cache
|
|
73
100
|
# Example:
|
74
101
|
# cache.exist? 'hello'
|
75
102
|
def exist?(k, ignored_options = nil)
|
76
|
-
|
103
|
+
handle_fork
|
104
|
+
_exist? k
|
77
105
|
end
|
78
|
-
|
106
|
+
|
79
107
|
# Increment a value.
|
80
108
|
#
|
81
109
|
# Example:
|
82
110
|
# cache.increment 'high-fives'
|
83
111
|
def increment(k, amount = 1, ignored_options = nil)
|
84
|
-
|
112
|
+
handle_fork
|
113
|
+
new_v = _get(k).to_i + amount
|
114
|
+
_set k, new_v, 0
|
115
|
+
new_v
|
85
116
|
end
|
86
117
|
|
87
118
|
# Decrement a value.
|
@@ -89,12 +120,7 @@ class Cache
|
|
89
120
|
# Example:
|
90
121
|
# cache.decrement 'high-fives'
|
91
122
|
def decrement(k, amount = 1, ignored_options = nil)
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
# Reset the cache connection. You shouldn't really use this, because it happens automatically on forking/threading.
|
96
|
-
def reset
|
97
|
-
storage.reset
|
123
|
+
increment k, -amount
|
98
124
|
end
|
99
125
|
|
100
126
|
# Try to get a value and if it doesn't exist, set it to the result of the block.
|
@@ -104,59 +130,54 @@ class Cache
|
|
104
130
|
# Example:
|
105
131
|
# cache.fetch 'hello' { 'world' }
|
106
132
|
def fetch(k, ttl = nil, &blk)
|
107
|
-
|
133
|
+
handle_fork
|
134
|
+
if _exist? k
|
135
|
+
_get k
|
136
|
+
elsif blk
|
137
|
+
v = blk.call
|
138
|
+
_set k, v, extract_ttl(ttl)
|
139
|
+
v
|
140
|
+
end
|
108
141
|
end
|
109
|
-
|
142
|
+
|
110
143
|
# Get the current value (if any), pass it into a block, and set the result.
|
111
144
|
#
|
112
145
|
# Example:
|
113
146
|
# cache.cas 'hello' { |current| 'world' }
|
114
147
|
def cas(k, ttl = nil, &blk)
|
115
|
-
|
148
|
+
handle_fork
|
149
|
+
if blk and _exist?(k)
|
150
|
+
old_v = _get k
|
151
|
+
new_v = blk.call old_v
|
152
|
+
_set k, new_v, extract_ttl(ttl)
|
153
|
+
new_v
|
154
|
+
end
|
116
155
|
end
|
117
|
-
|
156
|
+
|
118
157
|
alias :compare_and_swap :cas
|
119
|
-
|
158
|
+
|
120
159
|
# Get stats.
|
121
160
|
#
|
122
161
|
# Example:
|
123
162
|
# cache.stats
|
124
163
|
def stats
|
125
|
-
|
164
|
+
handle_fork
|
165
|
+
_stats
|
126
166
|
end
|
127
167
|
|
128
|
-
|
129
|
-
#
|
130
|
-
# Example:
|
131
|
-
# cache.get_multi 'hello', 'privyet'
|
132
|
-
def get_multi(*ks)
|
133
|
-
storage.get_multi ks
|
134
|
-
end
|
135
|
-
|
136
|
-
# Like get, but accepts :expires_in for compatibility with Rails.
|
137
|
-
#
|
138
|
-
# In general, you should use get instead.
|
139
|
-
#
|
140
|
-
# Example:
|
141
|
-
# cache.write 'hello', 'world', :expires_in => 5.minutes
|
142
|
-
def write(k, v, ttl = nil)
|
143
|
-
storage.set k, v, extract_ttl(ttl)
|
144
|
-
end
|
145
|
-
|
146
|
-
def read(k, ignored_options = nil) #:nodoc:
|
147
|
-
storage.get k
|
148
|
-
end
|
168
|
+
private
|
149
169
|
|
150
|
-
def
|
151
|
-
|
170
|
+
def handle_fork
|
171
|
+
if ::Process.pid != @pid
|
172
|
+
@pid = ::Process.pid
|
173
|
+
after_fork
|
174
|
+
end
|
152
175
|
end
|
153
|
-
|
154
|
-
def
|
155
|
-
|
176
|
+
|
177
|
+
def after_fork
|
178
|
+
# nothing
|
156
179
|
end
|
157
|
-
|
158
|
-
private
|
159
|
-
|
180
|
+
|
160
181
|
def extract_ttl(ttl)
|
161
182
|
case ttl
|
162
183
|
when ::Hash
|