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 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