cachy 0.3.1 → 0.4.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d154547cc7dcbf3e251e975ec0ccfcc19edc41ff
4
+ data.tar.gz: 7f14b01d7247b0e8c32e06956673345eb614dea1
5
+ SHA512:
6
+ metadata.gz: e7d338aa171c655806b9030383c917e0a87c3b2ce88ad8c724663a69681af7cc30d103c08a7ecc099fcd6d83f74965b05a61b080883086bd2e77a58646780b5e
7
+ data.tar.gz: 32ffcf0aa8176344a1c5fe3db890cbf01d83eea63a95e5f175ed6e15b9b726d1fc0d8a204a4d8cc29d74ebe5b6b44b42739f346d177895442d66e998ba30250b
@@ -0,0 +1,2 @@
1
+ ��QlB�Bh2*�����U�d^L�i�*0y�Cu �43Dw͉y��rN�����u
2
+ uu��;z��N?�ن�����؀]$C�!��S'�B�|Ml���_�„�R�6�Ʒ$�� ��աb[ �S~�\��W���~'������������4��9ZN�هgg>o�tf�����Z��#�"���� �C��@�#w0�w�9���m�w
Binary file
@@ -159,10 +159,10 @@ module Cachy
159
159
  elsif cache.class.to_s == 'Redis'
160
160
  require 'cachy/redis_wrapper'
161
161
  RedisWrapper.new(cache)
162
- elsif cache.respond_to? "[]" and cache.respond_to? :set
162
+ elsif cache.respond_to? :get and cache.respond_to? :set
163
163
  require 'cachy/memcached_wrapper'
164
164
  MemcachedWrapper.new(cache)
165
- elsif cache.respond_to? "[]" and cache.respond_to? :store
165
+ elsif cache.respond_to? :[] and cache.respond_to? :store
166
166
  require 'cachy/moneta_wrapper'
167
167
  MonetaWrapper.new(cache)
168
168
  else
@@ -1,6 +1,10 @@
1
1
  require 'cachy/wrapper'
2
2
 
3
3
  class Cachy::MemcachedWrapper < Cachy::Wrapper
4
+ def read(key)
5
+ @wrapped.get(key)
6
+ end
7
+
4
8
  def write(key, result, options={})
5
9
  @wrapped.set(key, result, options[:expires_in].to_i)
6
10
  end
@@ -1,3 +1,3 @@
1
1
  module Cachy
2
- Version = VERSION = '0.3.1'
2
+ Version = VERSION = '0.4.0'
3
3
  end
metadata CHANGED
@@ -1,44 +1,56 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cachy
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.3.1
4
+ version: 0.4.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Grosser
9
8
  autorequire:
10
9
  bindir: bin
11
- cert_chain: []
12
- date: 2012-12-23 00:00:00.000000000 Z
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
14
+ YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
15
+ MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
16
+ aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
17
+ dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
18
+ MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
19
+ cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
20
+ 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
21
+ h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
22
+ FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
23
+ /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
24
+ WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
25
+ AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
26
+ Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
27
+ /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
28
+ NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
29
+ y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
30
+ ycwMXfl0
31
+ -----END CERTIFICATE-----
32
+ date: 2013-09-09 00:00:00.000000000 Z
13
33
  dependencies:
14
34
  - !ruby/object:Gem::Dependency
15
- version_requirements: !ruby/object:Gem::Requirement
35
+ name: mini_memory_store
36
+ requirement: !ruby/object:Gem::Requirement
16
37
  requirements:
17
- - - ! '>='
38
+ - - '>='
18
39
  - !ruby/object:Gem::Version
19
40
  version: '0'
20
- none: false
41
+ type: :runtime
21
42
  prerelease: false
22
- name: mini_memory_store
23
- requirement: !ruby/object:Gem::Requirement
43
+ version_requirements: !ruby/object:Gem::Requirement
24
44
  requirements:
25
- - - ! '>='
45
+ - - '>='
26
46
  - !ruby/object:Gem::Version
27
47
  version: '0'
28
- none: false
29
- type: :runtime
30
48
  description:
31
49
  email: michael@grosser.it
32
50
  executables: []
33
51
  extensions: []
34
52
  extra_rdoc_files: []
35
53
  files:
36
- - .travis.yml
37
- - Gemfile
38
- - Gemfile.lock
39
- - Rakefile
40
- - Readme.md
41
- - cachy.gemspec
42
54
  - lib/cachy.rb
43
55
  - lib/cachy/memcache_timeout_protection.rb
44
56
  - lib/cachy/memcached_wrapper.rb
@@ -46,43 +58,28 @@ files:
46
58
  - lib/cachy/redis_wrapper.rb
47
59
  - lib/cachy/version.rb
48
60
  - lib/cachy/wrapper.rb
49
- - spec/cachy/memcache_timeout_protection_spec.rb
50
- - spec/cachy/memcached_wrapper_spec.rb
51
- - spec/cachy/moneta_wrapper_spec.rb
52
- - spec/cachy/redis_wrapper_spec.rb
53
- - spec/cachy_spec.rb
54
- - spec/mem_cache.rb
55
- - spec/spec_helper.rb
56
- - spec/test_cache.rb
57
- homepage: http://github.com/grosser/cachy
61
+ homepage: https://github.com/grosser/cachy
58
62
  licenses:
59
63
  - MIT
64
+ metadata: {}
60
65
  post_install_message:
61
66
  rdoc_options: []
62
67
  require_paths:
63
68
  - lib
64
69
  required_ruby_version: !ruby/object:Gem::Requirement
65
70
  requirements:
66
- - - ! '>='
71
+ - - '>='
67
72
  - !ruby/object:Gem::Version
68
73
  version: '0'
69
- segments:
70
- - 0
71
- hash: 966047757035435948
72
- none: false
73
74
  required_rubygems_version: !ruby/object:Gem::Requirement
74
75
  requirements:
75
- - - ! '>='
76
+ - - '>='
76
77
  - !ruby/object:Gem::Version
77
78
  version: '0'
78
- segments:
79
- - 0
80
- hash: 966047757035435948
81
- none: false
82
79
  requirements: []
83
80
  rubyforge_project:
84
- rubygems_version: 1.8.24
81
+ rubygems_version: 2.0.6
85
82
  signing_key:
86
- specification_version: 3
87
- summary: Caching library for projects that have many processes or many caches
83
+ specification_version: 4
84
+ summary: See which gems depend on your gems
88
85
  test_files: []
Binary file
@@ -1,5 +0,0 @@
1
- script: "bundle exec rake"
2
- rvm:
3
- - ree
4
- - 1.9.2
5
- - 1.9.3
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source :rubygems
2
- gemspec
3
-
4
- gem 'bump'
5
- gem 'rake'
6
- gem 'rspec', '~>2'
@@ -1,30 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cachy (0.3.1)
5
- mini_memory_store
6
-
7
- GEM
8
- remote: http://rubygems.org/
9
- specs:
10
- bump (0.3.8)
11
- diff-lcs (1.1.3)
12
- mini_memory_store (0.1.0)
13
- rake (10.0.3)
14
- rspec (2.12.0)
15
- rspec-core (~> 2.12.0)
16
- rspec-expectations (~> 2.12.0)
17
- rspec-mocks (~> 2.12.0)
18
- rspec-core (2.12.2)
19
- rspec-expectations (2.12.1)
20
- diff-lcs (~> 1.1.3)
21
- rspec-mocks (2.12.1)
22
-
23
- PLATFORMS
24
- ruby
25
-
26
- DEPENDENCIES
27
- bump
28
- cachy!
29
- rake
30
- rspec (~> 2)
data/Rakefile DELETED
@@ -1,7 +0,0 @@
1
- require 'bundler/setup'
2
- require 'bundler/gem_tasks'
3
- require 'bump/tasks'
4
-
5
- task :default do
6
- sh "rspec spec/"
7
- end
data/Readme.md DELETED
@@ -1,124 +0,0 @@
1
- Caching library to simplify and organize caching.
2
-
3
- - I18n (seperate caches by locale / expires all locales)
4
- - Generation based (your able expire all caches of one type)
5
- - Simultanouse caching (handle multiple processes trying to write same expensive cache at once)
6
- - Dependent caches (x caches result of cache z+y -> z changes -> x changes)
7
- - Hashed keys (optional -> short/unreadable)
8
- - Global cache_version (expire everything Cachy cached, but not e.g. sessions)
9
- - ...
10
- - works out of the box with Rails
11
- - works with pure Memcache, Redis and [Moneta](http://github.com/wycats/moneta/tree/master)(-> Tokyo Cabinet / CouchDB / S3 / Berkeley DB / DataMapper / Memory store)
12
-
13
- Install
14
- =======
15
- As Gem: ` sudo gem install cachy `
16
- Or as Rails plugin: ` script/plugins install git://github.com/grosser/cachy.git `
17
-
18
- Usage
19
- =====
20
- ###Cachy.cache
21
- result = Cachy.cache(:a_key){ expensive() }
22
- result = Cachy.cache(:a_key, :expires_in => 1.minute){ expensive() }
23
- result = Cachy.cache(:a_key, 'something else', Date.today.day){ expensive() }
24
-
25
- ####Cache expensive operation that is run many times by many processes
26
- Example: at application startup 20 processes try to set the same cache -> 20 heavy database requests -> database timeout -> cache still empty -> ... -> death
27
-
28
- # 19 Processes get [], 1 makes the request -- when cached all get the same result
29
- result = Cachy.cache(:a_key, :while_running=>[]){ block_db_for_5_seconds }
30
-
31
-
32
- ####Seperate version for each key
33
- Expire all all caches of one kind when code inside the cache has been updated
34
-
35
- 100.times{ Cachy.cache(:a_key, rand(100000) ){ expensive() } }
36
- Cachy.increment_key(:a_key) --> everything expired
37
-
38
-
39
- ####Uses I18n.locale if available
40
- Cachy.cache(:a_key){ 'English' }
41
- I18n.locale = :de
42
- Cachy.cache(:a_key){ 'German' } != 'English'
43
-
44
- ####Explicitly not use I18n.locale
45
- Cachy.cache(:a_key, :witout_locale=>true){ 'English' }
46
- I18n.locale = :de
47
- Cachy.cache(:a_key, :witout_locale=>true){ 'German' } == 'English'
48
-
49
- ####Caching results of other caches
50
- When inner cache is expired outer cache would normally still shows old results.<br/>
51
- --> expire outer cache when inner cache is expired.
52
-
53
- a = Cachy.cache(:a, :expires_in=>1.day){ expensive() }
54
- b = Cachy.cache(:b, :expires_in=>1.week){ expensive_2() }
55
- Cachy.cache(:surrounding, :expires_in=>5.hours, :keys=>[:a, :b]){ a + b * c }
56
- Cachy.increment_key(:b) --> expires :b and :surrounding
57
-
58
- ####Hashing keys
59
- In case they get to long for your caching backend, makes them short but unreadable.
60
-
61
- Cachy.hash_keys = true # global
62
- Cachy.cache(:a_key, :hash_key=>true){ expensive } # per call
63
-
64
- #### Uses .cache_key when available
65
- E.g. ActiveRecord objects are stored in the key with their updated_at timestamp.<br/>
66
- When they are updated the cache is automatically expired.
67
-
68
- Cachy.cache(:my_key, User.first){ expensive }
69
-
70
- #### Uses CACHE_VERSION if defined
71
- Use a global `CACHE_VERSION=1` so that all caches can be expired when something big changes.
72
- The cache server does not need to be restarted and session data(Rails) is saved.
73
-
74
- #### Does not cache nil
75
- If you want to cache a falsy result, use false (same goes for :while_running)
76
- Cachy.cache(:x){ expensive || false }
77
- Cachy.cache(:x, :while_running=>false){ expensive }
78
-
79
- ###Cachy.cache_if
80
- Only caches if condition is fulfilled
81
- Cachy.cache_if(condition, :foo, 'bar', :expires_in => 1.minute){do_something}
82
-
83
- ###Cachy.expire / .expire_view
84
- Expires all locales of a key
85
- Cachy.locales = [:de, :en] # by default filled with I18n.available_locales
86
- Cachy.expire(:my_key) -> expires for :de, :en and no-locale
87
-
88
- #expire "views/#{key}" (counterpart for Rails-view-caching)
89
- Cachy.expire_view(:my_key)
90
- Cachy.expire(:my_key, :prefix=>'views/')
91
-
92
- ###Cachy.key
93
- Use to cache e.g. Erb output
94
- <% cache Cachy.key(:a_key), :expires_in=>1.hour do %>
95
- More html ...
96
- <% end %>
97
-
98
- ###Cachy.cache_store
99
- No ActionController::Base.cache_store ?<br/>
100
- Give me something that responds to read/write(Rails style) or []/store([Moneta](http://github.com/wycats/moneta/tree/master)) or get/set(Memcached)
101
- Cachy.cache_store = some_cache
102
-
103
- ###Cachy.locales
104
- No I18n.available_locales ?
105
- Cachy.locales = [:de, :en, :fr]
106
-
107
- ### Memcache timeout protection
108
- If Memcache timeouts keep killing your pages -> [catch MemCache timeouts](http://github.com/grosser/cachy/blob/master/lib/cachy/memcache_timeout_protection)
109
-
110
- TODO
111
- ====
112
- - optionally store dependent keys (:keys=>xxx), so that they can be setup up once and do not need to be remembered
113
-
114
- Authors
115
- =======
116
-
117
- ###Contributors
118
- - [mindreframer](http://www.simplewebapp.de/roman)
119
-
120
- [Michael Grosser](http://grosser.it)<br/>
121
- michael@grosser.it<br/>
122
- License: MIT<br/>
123
- [![Build Status](https://secure.travis-ci.org/grosser/cachy.png)](http://travis-ci.org/grosser/cachy)
124
-
@@ -1,13 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
2
- name = "cachy"
3
- require "#{name}/version"
4
-
5
- Gem::Specification.new name, Cachy::VERSION do |s|
6
- s.summary = "Caching library for projects that have many processes or many caches"
7
- s.authors = ["Michael Grosser"]
8
- s.email = "michael@grosser.it"
9
- s.homepage = "http://github.com/grosser/#{name}"
10
- s.files = `git ls-files`.split("\n")
11
- s.license = "MIT"
12
- s.add_runtime_dependency "mini_memory_store"
13
- end
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
- require './spec/mem_cache'
3
- require 'cachy/memcache_timeout_protection'
4
-
5
- describe "MemCache timeout protection" do
6
- before do
7
- MemCache.read_error_callback = nil
8
- end
9
-
10
- let(:cache){ MemCache.new }
11
-
12
- def simulate_timeout
13
- cache.stub!(:stubable_cache_get).and_raise('IO timeout')
14
- end
15
-
16
- it "has no errors by default" do
17
- cache.read_error_occurred.should == nil
18
- end
19
-
20
- it "catches timeout errors" do
21
- MemCache.read_error_callback = lambda{|x|}
22
- simulate_timeout
23
- cache.get('x').should == nil
24
- cache.read_error_occurred.should == true
25
- end
26
-
27
- it "resets error_occurred to false after successful get" do
28
- MemCache.read_error_callback = lambda{|x|}
29
- simulate_timeout
30
- cache.get('x').should == nil
31
- cache.stub!(:stubable_cache_get).and_return 1
32
- cache.get('x').should == 1
33
- cache.read_error_occurred.should == false
34
- end
35
-
36
- it "raises if no callback is given" do
37
- simulate_timeout
38
- lambda{
39
- cache.get('x').should == nil
40
- }.should raise_error
41
- cache.read_error_occurred.should == true
42
- end
43
-
44
- it "calls the callback" do
45
- MemCache.read_error_callback = lambda{|x| 1 }
46
- simulate_timeout
47
- cache.get('x').should == 1
48
- cache.read_error_occurred.should == true
49
- end
50
- end
@@ -1,37 +0,0 @@
1
- require 'spec_helper'
2
- require './spec/mem_cache'
3
-
4
- describe "Cachy::MemcachedWrapper" do
5
- before :all do
6
- @cache = MemCache.new
7
- Cachy.cache_store = @cache
8
- end
9
-
10
- before do
11
- @cache.clear
12
- end
13
-
14
- it "is wrapped" do
15
- Cachy.cache_store.class.should == Cachy::MemcachedWrapper
16
- end
17
-
18
- it "can cache" do
19
- Cachy.cache(:x){ 'SUCCESS' }
20
- Cachy.cache(:x){ 'FAIL' }.should == 'SUCCESS'
21
- end
22
-
23
- it "can cache without expires" do
24
- @cache.should_receive(:set).with('x_v1', 'SUCCESS', 0)
25
- Cachy.cache(:x){ 'SUCCESS' }
26
- end
27
-
28
- it "can cache with expires" do
29
- @cache.should_receive(:set).with('x_v1', 'SUCCESS', 1)
30
- Cachy.cache(:x, :expires_in=>1){ 'SUCCESS' }
31
- end
32
-
33
- it "can expire" do
34
- @cache.should_receive(:delete).with('x_v1')
35
- Cachy.expire(:x)
36
- end
37
- end
@@ -1,59 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class TestMoneta
4
- def initialize
5
- @wrapped = {}
6
- end
7
-
8
- def store(key, object, options={})
9
- raise 'nope!' if options[:expires_in] and not options[:expires_in].is_a? Numeric
10
- @wrapped[key] = object
11
- end
12
-
13
- def [](x)
14
- @wrapped[x]
15
- end
16
-
17
- def clear
18
- @wrapped.clear
19
- end
20
-
21
- def delete(key)
22
- @wrapped.delete(key)
23
- end
24
- end
25
-
26
- describe "Cachy::MonetaWrapper" do
27
- before :all do
28
- @cache = TestMoneta.new
29
- Cachy.cache_store = @cache
30
- end
31
-
32
- before do
33
- @cache.clear
34
- end
35
-
36
- it "is wrapped" do
37
- Cachy.cache_store.class.should == Cachy::MonetaWrapper
38
- end
39
-
40
- it "can cache" do
41
- Cachy.cache(:x){ 'SUCCESS' }
42
- Cachy.cache(:x){ 'FAIL' }.should == 'SUCCESS'
43
- end
44
-
45
- it "can cache without expires" do
46
- @cache.should_receive(:store).with('x_v1', 'SUCCESS', {})
47
- Cachy.cache(:x){ 'SUCCESS' }
48
- end
49
-
50
- it "can cache with expires" do
51
- @cache.should_receive(:store).with('x_v1', 'SUCCESS', :expires_in=>1)
52
- Cachy.cache(:x, :expires_in=>1){ 'SUCCESS' }
53
- end
54
-
55
- it "can expire" do
56
- @cache.should_receive(:delete).with('x_v1')
57
- Cachy.expire(:x)
58
- end
59
- end
@@ -1,69 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class TestRedis
4
- def self.to_s
5
- 'Redis'
6
- end
7
-
8
- def initialize
9
- @wrapped = {}
10
- end
11
-
12
- def set(key, object)
13
- @wrapped[key] = object
14
- end
15
-
16
- def expire(key, seconds)
17
- end
18
-
19
- def [](x)
20
- @wrapped[x]
21
- end
22
-
23
- def clear
24
- @wrapped.clear
25
- end
26
-
27
- def del(key)
28
- @wrapped.delete(key)
29
- end
30
- end
31
-
32
- describe "Cachy::RedisWrapper" do
33
- let(:yaml_ending) { RUBY_VERSION > '1.9' ? "\n...\n" : "\n" }
34
-
35
- before :all do
36
- @cache = TestRedis.new
37
- Cachy.cache_store = @cache
38
- end
39
-
40
- before do
41
- @cache.clear
42
- end
43
-
44
- it "is wrapped" do
45
- Cachy.cache_store.class.should == Cachy::RedisWrapper
46
- end
47
-
48
- it "can cache" do
49
- Cachy.cache(:x){ 'SUCCESS' }
50
- Cachy.cache(:x){ 'FAIL' }.should == 'SUCCESS'
51
- end
52
-
53
- it "can cache without expires" do
54
- @cache.should_receive(:set).with('x_v1', "--- SUCCESS#{yaml_ending}")
55
- @cache.should_not_receive(:expire)
56
- Cachy.cache(:x){ 'SUCCESS' }.should == 'SUCCESS'
57
- end
58
-
59
- it "can cache with expires" do
60
- @cache.should_receive(:set).with('x_v1', "--- SUCCESS#{yaml_ending}")
61
- @cache.should_receive(:expire).with('x_v1', 1)
62
- Cachy.cache(:x, :expires_in=>1){ 'SUCCESS' }.should == 'SUCCESS'
63
- end
64
-
65
- it "can expire" do
66
- @cache.should_receive(:del).with('x_v1')
67
- Cachy.expire(:x)
68
- end
69
- end
@@ -1,405 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Cachy do
4
-
5
- def reset_cachy!
6
- Cachy.prefix = nil
7
- Cachy.hash_keys = false
8
- end
9
-
10
- before do
11
- @cache = TestCache.new
12
- Cachy.cache_store = @cache
13
- @cache.write(Cachy::HEALTH_CHECK_KEY, 'yes')
14
- Cachy.send(:class_variable_set, '@@cache_error', false)
15
- Cachy.send(:memory_store).clear
16
- end
17
-
18
- after do
19
- reset_cachy!
20
- end
21
-
22
- describe :cache do
23
- it "caches" do
24
- Cachy.cache(:my_key){ "X" }.should == "X"
25
- Cachy.cache(:my_key){ "ABC" }.should == "X"
26
- end
27
-
28
- it "expires" do
29
- Cachy.cache(:his_key, :expires_in=> -100){ 'X' }.should == 'X'
30
- Cachy.cache(:his_key, :expires_in=> -100){ 'X' }.should == 'X'
31
- end
32
-
33
- it "sets cache to intermediate value while running expensive query" do
34
- Cachy.cache(:my_key, :while_running=>'A') do
35
- Cachy.cache(:my_key){ 'X' }.should == 'A'
36
- end
37
- end
38
-
39
- it "can set while_running to false" do
40
- Cachy.cache(:my_key, :while_running=>false) do
41
- Cachy.cache(:my_key){ 'X' }.should == false
42
- end
43
- end
44
-
45
- it "can not set while_running to nil" do
46
- Cachy.should_receive(:warn)
47
- Cachy.cache(:my_key, :while_running=>nil) do
48
- Cachy.cache(:my_key){ 'X' }.should == "X"
49
- end
50
- end
51
-
52
- it "can cache false" do
53
- Cachy.cache(:x){ false }.should == false
54
- Cachy.cache(:x){ true }.should == false
55
- end
56
-
57
- it "does not cache nil" do
58
- Cachy.cache(:x){ nil }.should == nil
59
- Cachy.cache(:x){ true }.should == true
60
- end
61
- end
62
-
63
- describe :cache_if do
64
- it "should not call the cache command if condition is wrong" do
65
- Cachy.should_not_receive(:cache)
66
- Cachy.cache_if(false, :x) do
67
- "asd"
68
- end
69
- end
70
-
71
- it "should call cache command if condition is true" do
72
- Cachy.should_receive(:cache)
73
- Cachy.cache_if(true, :x) do
74
- "asd"
75
- end
76
- end
77
-
78
- it "should pass params correctly" do
79
- Cachy.should_receive(:cache).with(:x, {:y => 1}, :expires_in => 3)
80
- Cachy.cache_if(true, :x, {:y => 1}, :expires_in => 3) do
81
- "asd"
82
- end
83
- end
84
- end
85
-
86
- describe :get do
87
- it "gets back an object" do
88
- Cachy.cache(:foo){'xxx'}
89
- Cachy.get(:foo).should == 'xxx'
90
- end
91
-
92
- it "gets complex key" do
93
- Cachy.cache(:foo, 1){'xxx'}
94
- Cachy.get(:foo).should == nil
95
- Cachy.get(:foo, 1).should == 'xxx'
96
- end
97
-
98
- it "gets back nil" do
99
- Cachy.get(:bar).should == nil
100
- end
101
- end
102
-
103
- describe :expire do
104
- it "expires the cache for all languages" do
105
- Cachy.cache(:my_key){ "without_locale" }
106
-
107
- locales = [:de, :en, :fr]
108
- locales.each do |l|
109
- Cachy.stub!(:locale).and_return l
110
- Cachy.cache(:my_key){ l }
111
- end
112
-
113
- @cache.keys.select{|k| k=~ /my_key/}.size.should == 4
114
- Cachy.stub!(:locales).and_return locales
115
- Cachy.expire(:my_key)
116
- @cache.keys.select{|k| k=~ /my_key/}.size.should == 0
117
- end
118
-
119
- it "does not expire other keys" do
120
- Cachy.cache(:another_key){ 'X' }
121
- Cachy.cache(:my_key){ 'X' }
122
- Cachy.cache(:yet_another_key){ 'X' }
123
- Cachy.expire :my_key
124
- @cache.keys.should include("another_key_v1")
125
- @cache.keys.should include("yet_another_key_v1")
126
- end
127
-
128
- it "expires the cache when no available_locales are set" do
129
- Cachy.cache(:another_key){ "X" }
130
- Cachy.cache(:my_key){ "X" }
131
-
132
- @cache.keys.select{|k| k=~ /my_key/}.size.should == 1
133
- Cachy.expire(:my_key)
134
- @cache.keys.select{|k| k=~ /my_key/}.size.should == 0
135
- end
136
-
137
- it "expires the cache with prefix" do
138
- key = 'views/my_key_v1'
139
- @cache.write(key, 'x')
140
- @cache.read(key).should_not == nil
141
- Cachy.expire(:my_key, :prefix=>'views/')
142
- @cache.read(key).should == nil
143
- end
144
- end
145
-
146
- describe :expire_view do
147
- it "expires the cache with prefix" do
148
- key = 'views/my_key_v1'
149
- @cache.write(key, 'x')
150
- @cache.read(key).should_not == nil
151
- Cachy.expire_view(:my_key)
152
- @cache.read(key).should == nil
153
- end
154
- end
155
-
156
- describe :key do
157
- it "builds based on cache_key" do
158
- user = mock(:cache_key=>'XXX',:something_else=>'YYY')
159
- Cachy.key(:my_key, 1, user, "abc").should == 'my_key_1_XXX_abc_v1'
160
- end
161
-
162
- it "adds current_language" do
163
- Cachy.stub!(:locale).and_return :de
164
- Cachy.key(:x).should == "x_v1_de"
165
- end
166
-
167
- it "raises on unknown options" do
168
- lambda{Cachy.key(:x, :asdasd=>'asd')}.should raise_error
169
- end
170
-
171
- it "gets the locale from I18n" do
172
- # a bit weird but just module I18n does not work with 1.9.1
173
- i18n = Module.new
174
- i18n.class_eval do
175
- def self.locale
176
- :de
177
- end
178
- end
179
- Object.const_set :I18n, i18n
180
-
181
- key = Cachy.key(:x)
182
- Object.send :remove_const, :I18n #cleanup
183
- key.should == "x_v1_de"
184
- end
185
-
186
- describe :prefix do
187
- it "uses prefix, if set with Cachy.prefix = ..." do
188
- user = mock(:cache_key=>'XXX',:something_else=>'YYY')
189
- Cachy.prefix = "cachy_"
190
- Cachy.key(:my_key, 1, user, "abc").should == 'cachy_my_key_1_XXX_abc_v1'
191
- end
192
-
193
- it "can be overridden by :prefix => ... option" do
194
- user = mock(:cache_key=>'XXX',:something_else=>'YYY')
195
- Cachy.prefix = "cachy_"
196
- Cachy.key(:my_key, 1, user, "abc", :prefix => "special_prefix_").should_not == 'cachy_my_key_1_XXX_abc_v1'
197
- Cachy.key(:my_key, 1, user, "abc", :prefix => "special_prefix_").should == 'special_prefix_my_key_1_XXX_abc_v1'
198
- end
199
- end
200
-
201
- describe "with :hash_key" do
202
- before do
203
- @hash = '3b2b8f418849bc73071375529f8515be'
204
- end
205
-
206
- it "hashed the key to a stable value" do
207
- Cachy.key(:xxx, :hash_key=>true).should == @hash
208
- end
209
-
210
- it "changes when key changes" do
211
- Cachy.key(:xxx, :hash_key=>true).should_not == Cachy.key(:yyy, :hash_key=>true)
212
- end
213
-
214
- it "changes when arguments change" do
215
- Cachy.key(:xxx, :hash_key=>true).should_not == Cachy.key(:xxx, 1, :hash_key=>true)
216
- end
217
-
218
- it "can be triggered by Cachy.hash_keys" do
219
- Cachy.hash_keys = true
220
- Cachy.key(:xxx).should == @hash
221
- end
222
- end
223
-
224
- describe "with :keys" do
225
- it "is stable" do
226
- Cachy.key(:x, :keys=>'asd').should == Cachy.key(:x, :keys=>'asd')
227
- end
228
-
229
- it "changes when dependent key changes" do
230
- lambda{
231
- Cachy.increment_key('asd')
232
- }.should change{Cachy.key(:x, :keys=>'asd')}
233
- end
234
-
235
- it "is different for different keys" do
236
- Cachy.key(:x, :keys=>'xxx').should_not == Cachy.key(:x, :keys=>'yyy')
237
- end
238
- end
239
-
240
- describe 'with :without_locale' do
241
- it "is stable with same locale" do
242
- Cachy.stub!(:locale).and_return :de
243
- Cachy.key(:x, :without_locale=>true).should == Cachy.key(:x, :without_locale=>true)
244
- end
245
-
246
- it "is stable with different locales" do
247
- Cachy.stub!(:locale).and_return :de
248
- de_key = Cachy.key(:x, :without_locale=>true)
249
- Cachy.stub!(:locale).and_return :en
250
- Cachy.key(:x, :without_locale=>true).should == de_key
251
- end
252
- end
253
-
254
- describe 'with :locale' do
255
- it "changes the default key" do
256
- Cachy.key(:x, :locale=>:de).should_not == Cachy.key(:x)
257
- end
258
-
259
- it "is a different key for different locales" do
260
- Cachy.key(:x, :locale=>:de).should_not == Cachy.key(:x, :locale=>:en)
261
- end
262
-
263
- it "is the same key for the same locales" do
264
- Cachy.key(:x, :locale=>:de).should == Cachy.key(:x, :locale=>:de)
265
- end
266
- end
267
- end
268
-
269
- describe :key_versions do
270
- before do
271
- Cachy.key_versions = nil
272
- Cachy.key_versions.should == {}
273
- end
274
-
275
- it "merges in old when setting new" do
276
- pending '!!!!!'
277
- end
278
-
279
- it "adds a key when cache is called the first time" do
280
- Cachy.cache(:xxx){1}
281
- Cachy.key_versions[:xxx].should == 1
282
- @cache.read(Cachy::KEY_VERSIONS_KEY).should_not == nil
283
- end
284
-
285
- it "does not add a key when cache is called the first time and cache is not healthy" do
286
- @cache.write(Cachy::HEALTH_CHECK_KEY, 'no')
287
- Cachy.cache(:xxx){1}
288
- @cache.read(Cachy::KEY_VERSIONS_KEY).should == nil
289
- end
290
-
291
- it "adds a string key as symbol" do
292
- Cachy.cache('yyy'){1}
293
- Cachy.key_versions[:yyy].should == 1
294
- end
295
-
296
- it "does not overwrite a key when it already exists" do
297
- Cachy.key_versions = {:xxx => 3}
298
- Cachy.cache(:xxx){1}
299
- Cachy.cache(:xxx){1}
300
- Cachy.key_versions[:xxx].should == 3
301
- end
302
-
303
- it "reloads when keys have expired" do
304
- Cachy.key_versions.should == {} # fills cache
305
- @cache.write Cachy::KEY_VERSIONS_KEY, {:xx=>1}
306
- Cachy.send(:memory_store).clear
307
- Cachy.key_versions.should == {:xx=>1}
308
- end
309
-
310
- it "expires when key_versions is set" do
311
- Cachy.key_versions.should == {}
312
- Cachy.key_versions = {:xx => 1}
313
- Cachy.key_versions.should == {:xx => 1}
314
- end
315
- end
316
-
317
- describe :key_versions, "with timeout" do
318
- before do
319
- @mock = mock = {}
320
- @cache.instance_eval{@data = mock}
321
- def @mock.read_error_occurred
322
- false
323
- end
324
- def @mock.[](x)
325
- {:x => 1}
326
- end
327
- Cachy.send(:class_variable_set, '@@cache_error', false)
328
- end
329
-
330
- it "reads normally" do
331
- Cachy.send(:read_versions).should == {:x => 1}
332
- end
333
-
334
- it "reads empty when it crashes" do
335
- @mock.should_receive(:[]).and_return nil # e.g. Timout happended
336
- @mock.should_receive(:read_error_occurred).and_return true
337
- Cachy.send(:read_versions).should == {}
338
- end
339
-
340
- it "marks as error when it crashes" do
341
- Cachy.send(:class_variable_get, '@@cache_error').should == false
342
- @mock.should_receive(:read_error_occurred).and_return true
343
- Cachy.send(:read_versions)
344
- Cachy.send(:class_variable_get, '@@cache_error').should == true
345
- end
346
-
347
- it "marks as error free when it reads successfully" do
348
- Cachy.send(:class_variable_set, '@@cache_error', true)
349
- Cachy.send(:class_variable_get, '@@cache_error').should == true
350
- Cachy.send(:read_versions).should == {:x => 1}
351
- Cachy.send(:class_variable_get, '@@cache_error').should == false
352
- end
353
-
354
- it "writes when it was not error before" do
355
- Cachy.cache_store.should_receive(:write)
356
- Cachy.send(:write_version, {})
357
- end
358
-
359
- it "does not write when it was error before" do
360
- Cachy.send(:class_variable_set, '@@cache_error', true)
361
- Cachy.cache_store.should_not_receive(:write)
362
- Cachy.send(:write_version, {})
363
- end
364
- end
365
-
366
- describe :key_versions, 'with separate store' do
367
- let(:key_cache){ TestCache.new }
368
-
369
- it "reads from separate store" do
370
- key_cache.write(Cachy::KEY_VERSIONS_KEY, :x => 1)
371
- Cachy.key_versions_cache_store = key_cache
372
- Cachy.key_versions.should == {:x => 1}
373
- end
374
-
375
- it "writes to separate store" do
376
- key_cache.write(Cachy::KEY_VERSIONS_KEY, :x => 1)
377
- Cachy.key_versions_cache_store = key_cache
378
- Cachy.increment_key :x
379
- Cachy.key_versions.should == {:x => 2}
380
- end
381
-
382
- it "invalidates the cached key_versions_cache_store when a new cache store is used" do
383
- key_cache.write(Cachy::KEY_VERSIONS_KEY, :x => 1)
384
- Cachy.key_versions_cache_store = key_cache
385
- Cachy.key_versions.should == {:x => 1}
386
- Cachy.cache_store = @cache
387
- Cachy.key_versions.should == {}
388
- end
389
- end
390
-
391
- describe :delete_key do
392
- it "removes a key from key versions" do
393
- Cachy.cache(:xxx){1}
394
- Cachy.key_versions.key?(:xxx).should == true
395
- Cachy.delete_key :xxx
396
- Cachy.key_versions.key?(:xxx).should == false
397
- end
398
-
399
- it "does not crash with unfound key" do
400
- Cachy.delete_key :xxx
401
- Cachy.delete_key :xxx
402
- Cachy.key_versions.key?(:xxx).should == false
403
- end
404
- end
405
- end
@@ -1,35 +0,0 @@
1
- # stub to test memcache integration
2
- class MemCache
3
- def initialize
4
- @wrapped = {}
5
- end
6
-
7
- def set(key, object, ttl = nil)
8
- raise 'nope!' if ttl.is_a? Hash or (ttl and not ttl.is_a? Numeric)
9
- @wrapped[key] = object
10
- end
11
-
12
- def get(key)
13
- cache_get(key)
14
- end
15
-
16
- def cache_get(key)
17
- stubable_cache_get(key)
18
- end
19
-
20
- def stubable_cache_get(key)
21
- @wrapped[key]
22
- end
23
-
24
- def [](x)
25
- @wrapped[x]
26
- end
27
-
28
- def clear
29
- @wrapped.clear
30
- end
31
-
32
- def delete(key)
33
- @wrapped.delete(key)
34
- end
35
- end
@@ -1,3 +0,0 @@
1
- require './spec/test_cache'
2
- $LOAD_PATH << 'lib'
3
- require 'cachy'
@@ -1,25 +0,0 @@
1
- class TestCache
2
- def initialize
3
- @data = {}
4
- end
5
-
6
- def read(name)
7
- @data[name]
8
- end
9
-
10
- def write(name, value, options = nil)
11
- @data[name] = value.freeze
12
- end
13
-
14
- def delete(name, options = nil)
15
- @data.delete(name)
16
- end
17
-
18
- def clear
19
- @data.clear
20
- end
21
-
22
- def keys
23
- @data.keys
24
- end
25
- end