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 CHANGED
@@ -2,3 +2,11 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in cache.gemspec
4
4
  gemspec
5
+ gem 'yard'
6
+ gem 'test-unit'
7
+ gem 'redis'
8
+ gem 'redis-namespace'
9
+ gem 'dalli'
10
+ gem 'memcached'
11
+ gem 'memcache-client'
12
+ gem 'rake'
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 [cache_method](https://github.com/seamusabshere/cache_method) so that you can use them with memcached, redis, etc.
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 isn't implemented as an ActiveRecord::Cache::Store (Dalli did it just fine!)
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 about 50% slower than raw Memcached (if that's what you're wrapping) and barely slower at all than Dalli (if that's what you're wrapping.)
46
-
47
- user system total real
48
- set: cache:dalli:bin 5.710000 1.870000 7.580000 ( 10.210710) <- Cache.wrap(Dalli::Client.new)
49
- set: cache:libm:bin 1.320000 1.260000 2.580000 ( 5.913591) <- Cache.wrap(Memcached.new(:binary_protocol => true))
50
- set: dalli:bin 5.350000 1.860000 7.210000 ( 9.860368) <- Dalli::Client.new
51
- set: libm:ascii 0.760000 1.310000 2.070000 ( 5.369027)
52
- set: libm:ascii:pipeline 0.280000 0.020000 0.300000 ( 0.300872)
53
- set: libm:ascii:udp 0.640000 0.690000 1.330000 ( 3.618846)
54
- set: libm:bin 0.640000 1.370000 2.010000 ( 5.287203) <- Memcached.new(:binary_protocol => true)
55
- set: libm:bin:buffer 0.320000 0.170000 0.490000 ( 1.238471)
56
- set: mclient:ascii 11.840000 3.820000 15.660000 ( 15.933338)
57
- set: stash:bin 3.420000 1.300000 4.720000 ( 7.871299)
58
-
59
- get: cache:dalli:bin 5.740000 2.050000 7.790000 ( 10.220809) <- Cache.wrap(Dalli::Client.new)
60
- get: cache:libm:bin 1.330000 1.260000 2.590000 ( 5.789277) <- Cache.wrap(Memcached.new(:binary_protocol => true))
61
- get: dalli:bin 5.430000 2.050000 7.480000 ( 9.945485) <- Dalli::Client.new
62
- get: libm:ascii 0.970000 1.290000 2.260000 ( 5.421878)
63
- get: libm:ascii:pipeline 1.030000 1.590000 2.620000 ( 5.728829)
64
- get: libm:ascii:udp 0.790000 0.730000 1.520000 ( 3.393461)
65
- get: libm:bin 0.830000 1.330000 2.160000 ( 5.362280) <- Memcached.new(:binary_protocol => true)
66
- get: libm:bin:buffer 0.900000 1.640000 2.540000 ( 5.719478)
67
- get: mclient:ascii 14.010000 3.860000 17.870000 ( 18.125730)
68
- get: stash:bin 3.100000 1.320000 4.420000 ( 7.559659)
69
-
70
- Thanks to https://github.com/fauna/memcached/blob/master/test/profile/benchmark.rb
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/fauna/memcached] (either a Memcached or a Memcached::Rails)
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(client = nil)
21
- new client
20
+ def self.wrap(metal = nil)
21
+ new metal
22
22
  end
23
23
 
24
- def initialize(client = nil) #:nodoc:
25
- config.client = client
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 storage #:nodoc:
33
- @storage ||= Storage.new self
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
- storage.get k
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
- storage.set k, v, extract_ttl(ttl)
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
- storage.delete k
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
- storage.flush
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
- storage.exist? k
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
- storage.increment k, amount
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
- storage.decrement k, amount
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
- storage.fetch k, extract_ttl(ttl), &blk
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
- storage.cas k, extract_ttl(ttl), &blk
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
- storage.stats
164
+ handle_fork
165
+ _stats
126
166
  end
127
167
 
128
- # Get multiple cache entries.
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 logger #:nodoc:
151
- config.logger
170
+ def handle_fork
171
+ if ::Process.pid != @pid
172
+ @pid = ::Process.pid
173
+ after_fork
174
+ end
152
175
  end
153
-
154
- def logger=(logger) #:nodoc:
155
- config.logger = logger
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