cache 0.2.7 → 0.3.0
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/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
|