aub-cache_advance 0.2.0 → 1.0.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/README.textile +0 -47
- data/TODO.textile +0 -6
- data/cache_advance.gemspec +3 -3
- data/lib/cache_advance/active_record_sweeper.rb +1 -1
- data/lib/cache_advance/cache_set.rb +13 -17
- data/lib/cache_advance/named_cache.rb +58 -83
- data/lib/cache_advance/rails_cache.rb +15 -0
- data/lib/cache_advance.rb +3 -13
- data/rails/init.rb +14 -36
- data/test/cache_set_test.rb +3 -3
- data/test/named_cache_test.rb +2 -121
- data/test/rails_cache_test.rb +7 -0
- data/test/test_helper.rb +0 -1
- metadata +8 -14
- data/lib/cache_advance/cached_key_list.rb +0 -46
- data/lib/cache_advance/lock.rb +0 -40
- data/lib/cache_advance/named_cache_configuration.rb +0 -7
- data/test/cache_mock.rb +0 -15
- data/test/spec/db/schema.rb +0 -18
- data/test/spec/mapper_spec.rb +0 -16
- data/test/spec/mocks/memcache.rb +0 -41
- data/test/spec/spec_helper.rb +0 -30
data/README.textile
CHANGED
@@ -1,47 +0,0 @@
|
|
1
|
-
h1. cache advance
|
2
|
-
|
3
|
-
CacheAdvance is a wrapper around the Rails caching system that provides a simple, centralized
|
4
|
-
configuration file for defining caches and an even simpler way to apply them.
|
5
|
-
|
6
|
-
Written by "Aubrey Holland":mailto:aubreyholland@gmail.com.
|
7
|
-
|
8
|
-
h3. download
|
9
|
-
|
10
|
-
Github: "Page":http://github.com/aub/cache_advance/tree/master
|
11
|
-
|
12
|
-
Gem: <pre>gem install aub-cache_advance --source http://gems.github.com</pre>
|
13
|
-
|
14
|
-
Note: if you install using the gem from Github, you'll need this
|
15
|
-
in your environment.rb if you want to use Rails 2.1's dependency manager:
|
16
|
-
|
17
|
-
<pre><code>
|
18
|
-
config.gem 'aub-cache_advance', :lib => 'cache_advance', :source => 'http://gems.github.com'
|
19
|
-
</code></pre>
|
20
|
-
|
21
|
-
h3. cache definition
|
22
|
-
|
23
|
-
Caches are defined in the file config/caches.rb, which will be loaded automatically by the gem.
|
24
|
-
This file is similar in format to the rails routes config file, allowing you to specify named
|
25
|
-
caches and configure their keys and how they will be expired.
|
26
|
-
|
27
|
-
<pre><code>
|
28
|
-
CacheAdvance::Caches.define_caches do |config|
|
29
|
-
|
30
|
-
config.qualifier(:params) do |request|
|
31
|
-
request.params
|
32
|
-
end
|
33
|
-
|
34
|
-
config.plugin :template_handler_observer_cache_plugin
|
35
|
-
|
36
|
-
config.content_block :expiration_time => 10.minutes, :qualifiers => [ :subdomain, :params ]
|
37
|
-
|
38
|
-
config.change_towns_all :expiration_types => [ :publication ]
|
39
|
-
config.change_towns_limited :expiration_types => [ :publication ]
|
40
|
-
|
41
|
-
config.publication_twitter_update :expiration_time => 10.minutes, :qualifiers => [ :subdomain ]
|
42
|
-
|
43
|
-
config.weather_widget :expiration_time => 10.minutes, :qualifiers => [ :subdomain ]
|
44
|
-
end
|
45
|
-
</code></pre>
|
46
|
-
|
47
|
-
..............More later.
|
data/TODO.textile
CHANGED
@@ -1,6 +0,0 @@
|
|
1
|
-
- Fix to allow keys of > 256 characters with memcache
|
2
|
-
- Make test coverage not pitiful
|
3
|
-
- Add ability for cache to expire when a specific object changes
|
4
|
-
- Apply plugins only to specific caches
|
5
|
-
- Test with caching strategies other than memcache
|
6
|
-
- Improve documentation
|
data/cache_advance.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.version = '0.
|
2
|
+
s.version = '1.0.0'
|
3
3
|
s.date = %q{2009-01-08}
|
4
4
|
|
5
5
|
s.name = %q{cache_advance}
|
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.authors = ['Aubrey Holland']
|
8
8
|
s.description = %q{A system for spiffy declarative caching}
|
9
9
|
s.email = %q{aubrey@patch.com}
|
10
|
-
s.files = %w(
|
10
|
+
s.files = %w(cache_advance.gemspec lib/cache_advance/active_record_sweeper.rb lib/cache_advance/cache_set.rb lib/cache_advance/mapper.rb lib/cache_advance/named_cache.rb lib/cache_advance/rails_cache.rb lib/cache_advance.rb rails/init.rb Rakefile README.textile test/active_record_sweeper_test.rb test/cache_set_test.rb test/mapper_test.rb test/named_cache_test.rb test/rails_cache_test.rb test/test_helper.rb TODO.textile)
|
11
11
|
s.homepage = %q{http://github.com/aub/cache_advance}
|
12
12
|
s.require_paths = ['lib']
|
13
13
|
s.rubygems_version = %q{1.2.0}
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.has_rdoc = true
|
16
16
|
s.extra_rdoc_files = ['README.textile']
|
17
17
|
s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.textile']
|
18
|
-
s.test_files = %w(test/active_record_sweeper_test.rb test/cache_set_test.rb test/mapper_test.rb test/named_cache_test.rb)
|
18
|
+
s.test_files = %w(test/active_record_sweeper_test.rb test/cache_set_test.rb test/mapper_test.rb test/named_cache_test.rb test/rails_cache_test.rb)
|
19
19
|
|
20
20
|
if s.respond_to? :specification_version then
|
21
21
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
@@ -3,19 +3,19 @@ module CacheAdvance
|
|
3
3
|
attr_reader :named_caches
|
4
4
|
attr_reader :qualifiers
|
5
5
|
attr_reader :plugins
|
6
|
+
attr_accessor :observer_type
|
7
|
+
attr_accessor :cache
|
6
8
|
|
7
|
-
def initialize
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
def setup_complete
|
12
|
-
|
9
|
+
def initialize
|
10
|
+
@named_caches = {}
|
11
|
+
@qualifiers = {}
|
12
|
+
@plugins = []
|
13
13
|
end
|
14
14
|
|
15
15
|
def apply(cache_name, request, options, &block)
|
16
|
-
|
17
|
-
raise UnknownNamedCacheException if
|
18
|
-
|
16
|
+
cache = @named_caches[cache_name]
|
17
|
+
raise UnknownNamedCacheException if cache.nil?
|
18
|
+
cache.value_for(request, options, &block)
|
19
19
|
end
|
20
20
|
|
21
21
|
def add_qualifier(name, proc)
|
@@ -27,7 +27,7 @@ module CacheAdvance
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def add_named_cache(name, options)
|
30
|
-
@named_caches[name] = NamedCache.new(name, options, self,
|
30
|
+
@named_caches[name] = NamedCache.new(name, options, self, cache)
|
31
31
|
end
|
32
32
|
|
33
33
|
def define_caches
|
@@ -35,17 +35,13 @@ module CacheAdvance
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def create_sweepers
|
38
|
-
|
38
|
+
observer_type.initialize_observed(@named_caches.values.map { |c| c.expiration_types }.flatten.compact.uniq)
|
39
39
|
end
|
40
40
|
|
41
41
|
def expire_for_class(class_name)
|
42
|
-
@named_caches.values.each do |
|
43
|
-
|
42
|
+
@named_caches.values.each do |cache|
|
43
|
+
cache.expire_for(class_name)
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
def sweeper_type=(type)
|
48
|
-
@sweeper_type = type
|
49
|
-
end
|
50
46
|
end
|
51
47
|
end
|
@@ -1,37 +1,51 @@
|
|
1
|
-
module CacheAdvance
|
1
|
+
module CacheAdvance
|
2
2
|
class NamedCache
|
3
|
-
|
4
|
-
ENABLED_CHECK_INTERVAL = 60
|
3
|
+
STORED_KEY = 'STORED_CACHES'
|
5
4
|
|
6
|
-
def initialize(name, params,
|
5
|
+
def initialize(name, params, configuration, cache)
|
7
6
|
@name = name.to_s
|
8
7
|
@params = params
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@cached_key_list = CachedKeyList.new(@store, "#{@name}/STORED_CACHES", expiration_time)
|
12
|
-
@enabled_check_time = Time.now + ENABLED_CHECK_INTERVAL
|
13
|
-
@enabled = nil
|
8
|
+
@configuration = configuration
|
9
|
+
@cache = cache
|
14
10
|
end
|
15
|
-
|
11
|
+
|
12
|
+
def key_for(request, suffix='')
|
13
|
+
key = @name.dup
|
14
|
+
key << suffix.to_s
|
15
|
+
|
16
|
+
qualifiers.each do |q|
|
17
|
+
if (qualifier = @configuration.qualifiers[q])
|
18
|
+
this_one = qualifier.call(request)
|
19
|
+
key << this_one.to_s unless this_one.nil?
|
20
|
+
end
|
21
|
+
end if qualifiers
|
22
|
+
key
|
23
|
+
end
|
24
|
+
|
16
25
|
def value_for(request, options, &block)
|
17
|
-
return block.call unless enabled?
|
18
|
-
|
19
26
|
key = key_for(request, options[:key])
|
20
|
-
|
21
|
-
if (
|
22
|
-
|
23
|
-
return
|
27
|
+
|
28
|
+
if (cache = @cache.read(key))
|
29
|
+
call_plugins('after_read', key, request)
|
30
|
+
return cache
|
24
31
|
end
|
25
32
|
|
26
|
-
|
33
|
+
call_plugins('before_write', key, request)
|
27
34
|
result = block.call
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
35
|
+
@cache.write(key, result, rails_options)
|
36
|
+
call_plugins('after_write', key, request)
|
37
|
+
|
38
|
+
add_to_cached_keys_list(key)
|
39
|
+
|
32
40
|
result
|
33
41
|
end
|
34
|
-
|
42
|
+
|
43
|
+
def rails_options
|
44
|
+
options = {}
|
45
|
+
options[:expires_in] = expiration_time if expiration_time
|
46
|
+
options
|
47
|
+
end
|
48
|
+
|
35
49
|
def expire_for(type)
|
36
50
|
if expiration_types.include?(type)
|
37
51
|
expire_all
|
@@ -39,82 +53,43 @@ module CacheAdvance
|
|
39
53
|
end
|
40
54
|
|
41
55
|
def expire_all
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
56
|
+
if (data = @cache.read(@name + STORED_KEY))
|
57
|
+
data = Array(Marshal.load(data))
|
58
|
+
data.each { |key| @cache.delete(key) }
|
59
|
+
else
|
60
|
+
@cache.delete(@name)
|
61
|
+
end
|
47
62
|
end
|
48
63
|
|
49
64
|
def expiration_types
|
50
65
|
Array(@params[:expiration_types])
|
51
66
|
end
|
52
67
|
|
53
|
-
def
|
54
|
-
@params[:
|
55
|
-
end
|
56
|
-
|
57
|
-
def enabled=(state)
|
58
|
-
@enabled = !!state
|
59
|
-
write_to_store(enabled_key, @enabled, false)
|
68
|
+
def expiration_time
|
69
|
+
@params[:expiration_time]
|
60
70
|
end
|
61
71
|
|
62
|
-
def
|
63
|
-
|
64
|
-
@enabled = [nil, true].include?(read_from_store(enabled_key))
|
65
|
-
@enabled_check_time = Time.now + ENABLED_CHECK_INTERVAL
|
66
|
-
end
|
67
|
-
@enabled
|
72
|
+
def qualifiers
|
73
|
+
Array(@params[:qualifiers])
|
68
74
|
end
|
69
75
|
|
70
76
|
protected
|
71
77
|
|
72
|
-
def
|
73
|
-
@
|
74
|
-
end
|
75
|
-
|
76
|
-
def write_to_store(key, value, add_to_key_list=true)
|
77
|
-
expiration_time ? @store.set(key, value, expiration_time) : @store.set(key, value)
|
78
|
-
if add_to_key_list
|
79
|
-
@cached_key_list.add_key(key)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def delete_from_store(key)
|
84
|
-
@store.delete(key)
|
85
|
-
@cached_key_list.delete_key(key)
|
86
|
-
end
|
87
|
-
|
88
|
-
def delete_all_from_store
|
89
|
-
@cached_key_list.all_keys.each { |key| delete_from_store(key) }
|
90
|
-
@cached_key_list.clear
|
91
|
-
end
|
92
|
-
|
93
|
-
def each_plugin
|
94
|
-
@cache_set.plugins.each do |p|
|
95
|
-
yield p
|
96
|
-
end
|
78
|
+
def call_plugins(method, key, request)
|
79
|
+
@configuration.plugins.each { |p| p.send(method, @name, key, request) if p.respond_to?(method) }
|
97
80
|
end
|
98
81
|
|
99
|
-
def
|
100
|
-
|
101
|
-
if (
|
102
|
-
(
|
82
|
+
def add_to_cached_keys_list(key)
|
83
|
+
unless expiration_types.blank? || key == @name
|
84
|
+
if (data = @cache.read(@name + STORED_KEY))
|
85
|
+
data = Array(Marshal.load(data))
|
86
|
+
else
|
87
|
+
data = []
|
103
88
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
def enabled_key
|
109
|
-
"#{@name}/ENABLED_STATUS"
|
110
|
-
end
|
111
|
-
|
112
|
-
def expiration_time
|
113
|
-
@params[:expiration_time]
|
114
|
-
end
|
115
|
-
|
116
|
-
def qualifiers
|
117
|
-
Array(@params[:qualifiers])
|
89
|
+
unless data.include?(key)
|
90
|
+
@cache.write(@name + STORED_KEY, Marshal.dump(data << key))
|
91
|
+
end
|
92
|
+
end
|
118
93
|
end
|
119
94
|
end
|
120
95
|
end
|
data/lib/cache_advance.rb
CHANGED
@@ -1,19 +1,9 @@
|
|
1
|
+
require 'cache_advance/named_cache'
|
1
2
|
require 'cache_advance/cache_set'
|
2
|
-
require 'cache_advance/cached_key_list'
|
3
3
|
require 'cache_advance/mapper'
|
4
|
-
require 'cache_advance/named_cache'
|
5
|
-
require 'cache_advance/named_cache_configuration'
|
6
4
|
|
7
5
|
module CacheAdvance
|
8
6
|
class UnknownNamedCacheException < Exception; end
|
9
|
-
|
10
|
-
|
11
|
-
attr_reader :cache_set
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.define_caches(store)
|
15
|
-
@cache_set = CacheSet.new(store)
|
16
|
-
yield Mapper.new(@cache_set)
|
17
|
-
@cache_set.setup_complete # This allows the cache set to finalize some of its configuration
|
18
|
-
end
|
7
|
+
|
8
|
+
Caches = CacheSet.new
|
19
9
|
end
|
data/rails/init.rb
CHANGED
@@ -1,47 +1,25 @@
|
|
1
1
|
require 'cache_advance'
|
2
|
-
require 'cache_advance/
|
3
|
-
|
4
|
-
require
|
2
|
+
require 'cache_advance/active_record_observer'
|
3
|
+
require 'cache_advance/rails_cache'
|
4
|
+
require 'config/caches'
|
5
5
|
require 'dispatcher'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# This is the helper method that can be used in rails views/controllers/helpers.
|
11
|
-
# If caching is disabled, just make it yield the results of the block.
|
12
|
-
if config.action_controller.perform_caching
|
13
|
-
ActionController::Base.helper do
|
14
|
-
def cache_it(cache, options={}, &block)
|
15
|
-
CacheAdvance.cache_set.apply(cache, request, options) do
|
16
|
-
capture(&block)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
else
|
21
|
-
ActionController::Base.helper do
|
22
|
-
def cache_it(cache, options={}, &block)
|
7
|
+
ActionController::Base.helper do
|
8
|
+
def cache_it(cache, options={}, &block)
|
9
|
+
CacheAdvance::Caches.apply(cache, request, options) do
|
23
10
|
capture(&block)
|
24
11
|
end
|
25
12
|
end
|
26
13
|
end
|
27
14
|
|
28
|
-
ActionMailer::Base.helper do
|
29
|
-
def cache_it(cache, options={}, &block)
|
30
|
-
capture(&block)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# This will get called after the standard rails environment is initialized.
|
35
15
|
config.after_initialize do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
CacheAdvance::ActiveRecordSweeper.instance.reload_sweeper
|
45
|
-
end
|
16
|
+
CacheAdvance::Caches.observer_type = CacheAdvance::ActiveRecordObserver
|
17
|
+
CacheAdvance::Caches.cache = CacheAdvance::RailsCache.new
|
18
|
+
|
19
|
+
CacheAdvance::Caches.create_sweepers
|
20
|
+
ActiveRecord::Base.observers << CacheAdvance::ActiveRecordObserver
|
21
|
+
|
22
|
+
ActionController::Dispatcher.to_prepare(:cache_advance_reload) do
|
23
|
+
CacheAdvance::ActiveRecordSweeper.instance.reload_sweeper
|
46
24
|
end
|
47
25
|
end
|
data/test/cache_set_test.rb
CHANGED
@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper.rb'
|
|
2
2
|
|
3
3
|
class Plugin; end
|
4
4
|
|
5
|
-
require 'cache_advance/
|
5
|
+
require 'cache_advance/active_record_observer'
|
6
6
|
|
7
7
|
class CacheSetTest < Test::Unit::TestCase
|
8
8
|
def setup
|
@@ -30,10 +30,10 @@ class CacheSetTest < Test::Unit::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_should_pass_expiration_types_to_the_sweeper
|
33
|
-
@cache_set.
|
33
|
+
@cache_set.observer_type = CacheAdvance::ActiveRecordObserver
|
34
34
|
@cache_set.add_named_cache(:kewl, { :expiration_types => [:publication, :article] })
|
35
35
|
@cache_set.add_named_cache(:howza, { :expiration_types => [:publication] })
|
36
|
-
CacheAdvance::
|
36
|
+
CacheAdvance::ActiveRecordObserver.expects(:initialize_observed).with([:publication, :article])
|
37
37
|
@cache_set.create_sweepers
|
38
38
|
end
|
39
39
|
end
|
data/test/named_cache_test.rb
CHANGED
@@ -1,126 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
3
|
class NamedCacheTest < Test::Unit::TestCase
|
4
|
-
|
5
|
-
|
6
|
-
@request = mock
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_key_for_in_basic_case
|
10
|
-
create_named_cache
|
11
|
-
assert_equal 'test_cache', @named_cache.key_for(@request)
|
12
|
-
assert_equal 'test_cachesuf', @named_cache.key_for(@request, 'suf')
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_key_with_qualifiers
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
protected
|
20
|
-
|
21
|
-
def create_named_cache(options={})
|
22
|
-
@name = options[:name] || 'test_cache'
|
23
|
-
@params = {}
|
24
|
-
@cache_set = CacheAdvance::CacheSet.new
|
25
|
-
@cache = CacheAdvance::CacheMock.new
|
26
|
-
@named_cache = CacheAdvance::NamedCache.new(@name, @params, @cache_set, @cache)
|
4
|
+
def test_fake
|
5
|
+
assert true
|
27
6
|
end
|
28
7
|
end
|
29
|
-
|
30
|
-
|
31
|
-
# module CacheAdvance
|
32
|
-
# class NamedCache
|
33
|
-
# STORED_KEY = 'STORED_CACHES'
|
34
|
-
#
|
35
|
-
# def initialize(name, params, configuration, cache)
|
36
|
-
# @name = name.to_s
|
37
|
-
# @params = params
|
38
|
-
# @configuration = configuration
|
39
|
-
# @cache = cache
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# def key_for(request, suffix='')
|
43
|
-
# key = @name.dup
|
44
|
-
# key << suffix.to_s
|
45
|
-
#
|
46
|
-
# qualifiers.each do |q|
|
47
|
-
# if (qualifier = @configuration.qualifiers[q])
|
48
|
-
# this_one = qualifier.call(request)
|
49
|
-
# key << this_one.to_s unless this_one.nil?
|
50
|
-
# end
|
51
|
-
# end if qualifiers
|
52
|
-
# key
|
53
|
-
# end
|
54
|
-
#
|
55
|
-
# def value_for(request, options, &block)
|
56
|
-
# key = key_for(request, options[:key])
|
57
|
-
#
|
58
|
-
# if (cache = @cache.read(key))
|
59
|
-
# call_plugins('after_read', key, request)
|
60
|
-
# return cache
|
61
|
-
# end
|
62
|
-
#
|
63
|
-
# call_plugins('before_write', key, request)
|
64
|
-
# result = block.call
|
65
|
-
# @cache.write(key, result, rails_options)
|
66
|
-
# call_plugins('after_write', key, request)
|
67
|
-
#
|
68
|
-
# add_to_cached_keys_list(key)
|
69
|
-
#
|
70
|
-
# result
|
71
|
-
# end
|
72
|
-
#
|
73
|
-
# def rails_options
|
74
|
-
# options = {}
|
75
|
-
# options[:expires_in] = expiration_time if expiration_time
|
76
|
-
# options
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# def expire_for(type)
|
80
|
-
# if expiration_types.include?(type)
|
81
|
-
# expire_all
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# def expire_all
|
86
|
-
# if (data = @cache.read(@name + STORED_KEY))
|
87
|
-
# data = Array(Marshal.load(data))
|
88
|
-
# data.each { |key| @cache.delete(key) }
|
89
|
-
# else
|
90
|
-
# @cache.delete(@name)
|
91
|
-
# end
|
92
|
-
# end
|
93
|
-
#
|
94
|
-
# def expiration_types
|
95
|
-
# Array(@params[:expiration_types])
|
96
|
-
# end
|
97
|
-
#
|
98
|
-
# def expiration_time
|
99
|
-
# @params[:expiration_time]
|
100
|
-
# end
|
101
|
-
#
|
102
|
-
# def qualifiers
|
103
|
-
# Array(@params[:qualifiers])
|
104
|
-
# end
|
105
|
-
#
|
106
|
-
# protected
|
107
|
-
#
|
108
|
-
# def call_plugins(method, key, request)
|
109
|
-
# @configuration.plugins.each { |p| p.send(method, @name, key, request) if p.respond_to?(method) }
|
110
|
-
# end
|
111
|
-
#
|
112
|
-
# def add_to_cached_keys_list(key)
|
113
|
-
# unless expiration_types.blank? || key == @name
|
114
|
-
# if (data = @cache.read(@name + STORED_KEY))
|
115
|
-
# data = Array(Marshal.load(data))
|
116
|
-
# else
|
117
|
-
# data = []
|
118
|
-
# end
|
119
|
-
# unless data.include?(key)
|
120
|
-
# @cache.write(@name + STORED_KEY, Marshal.dump(data << key))
|
121
|
-
# end
|
122
|
-
# end
|
123
|
-
# end
|
124
|
-
# end
|
125
|
-
# end
|
126
|
-
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aub-cache_advance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aubrey Holland
|
@@ -22,30 +22,23 @@ extensions: []
|
|
22
22
|
extra_rdoc_files:
|
23
23
|
- README.textile
|
24
24
|
files:
|
25
|
-
- README.textile
|
26
|
-
- Rakefile
|
27
|
-
- TODO.textile
|
28
|
-
- cache_advance-1.0.9.gem
|
29
25
|
- cache_advance.gemspec
|
30
|
-
- lib/cache_advance.rb
|
31
26
|
- lib/cache_advance/active_record_sweeper.rb
|
32
27
|
- lib/cache_advance/cache_set.rb
|
33
|
-
- lib/cache_advance/cached_key_list.rb
|
34
|
-
- lib/cache_advance/lock.rb
|
35
28
|
- lib/cache_advance/mapper.rb
|
36
29
|
- lib/cache_advance/named_cache.rb
|
37
|
-
- lib/cache_advance/
|
30
|
+
- lib/cache_advance/rails_cache.rb
|
31
|
+
- lib/cache_advance.rb
|
38
32
|
- rails/init.rb
|
33
|
+
- Rakefile
|
34
|
+
- README.textile
|
39
35
|
- test/active_record_sweeper_test.rb
|
40
|
-
- test/cache_mock.rb
|
41
36
|
- test/cache_set_test.rb
|
42
37
|
- test/mapper_test.rb
|
43
38
|
- test/named_cache_test.rb
|
44
|
-
- test/
|
45
|
-
- test/spec/mapper_spec.rb
|
46
|
-
- test/spec/mocks/memcache.rb
|
47
|
-
- test/spec/spec_helper.rb
|
39
|
+
- test/rails_cache_test.rb
|
48
40
|
- test/test_helper.rb
|
41
|
+
- TODO.textile
|
49
42
|
has_rdoc: true
|
50
43
|
homepage: http://github.com/aub/cache_advance
|
51
44
|
post_install_message:
|
@@ -80,3 +73,4 @@ test_files:
|
|
80
73
|
- test/cache_set_test.rb
|
81
74
|
- test/mapper_test.rb
|
82
75
|
- test/named_cache_test.rb
|
76
|
+
- test/rails_cache_test.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module CacheAdvance
|
2
|
-
class CachedKeyList
|
3
|
-
def initialize(store, cache_key, expiration_time=nil)
|
4
|
-
@store, @cache_key, @expiration_time = store, cache_key, expiration_time
|
5
|
-
end
|
6
|
-
|
7
|
-
def all_keys
|
8
|
-
key_list.keys
|
9
|
-
end
|
10
|
-
|
11
|
-
def add_key(key)
|
12
|
-
Lock.new(@store).execute_locked(@cache_key) do
|
13
|
-
data = key_list
|
14
|
-
unless data.has_key?(key)
|
15
|
-
data[key] = @expiration_time.nil? ? nil : Time.now + @expiration_time
|
16
|
-
@store.set(@cache_key, data)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def delete_key(key)
|
22
|
-
Lock.new(@store).execute_locked(@cache_key) do
|
23
|
-
data = key_list
|
24
|
-
if data.has_key?(key)
|
25
|
-
data.delete(key)
|
26
|
-
@store.set(@cache_key, data)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def clear
|
32
|
-
@store.set(@cache_key, {})
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
def key_list
|
38
|
-
list = @store.get(@cache_key) || {}
|
39
|
-
if @expiration_time
|
40
|
-
now = Time.now
|
41
|
-
list.delete_if { |k,v| v <= now }
|
42
|
-
end
|
43
|
-
list
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/lib/cache_advance/lock.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
module CacheAdvance
|
2
|
-
class Lock
|
3
|
-
|
4
|
-
class LockAcquisitionFailureException < Exception; end
|
5
|
-
|
6
|
-
DEFAULT_RETRIES = 5
|
7
|
-
DEFAULT_EXPIRATION_TIME = 30
|
8
|
-
|
9
|
-
def initialize(store)
|
10
|
-
@store = store
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute_locked(key, lock_expiry = DEFAULT_EXPIRATION_TIME, retries = DEFAULT_RETRIES)
|
14
|
-
begin
|
15
|
-
acquire(key, lock_expiry, retries)
|
16
|
-
yield
|
17
|
-
ensure
|
18
|
-
release_lock(key)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def acquire(key, lock_expiry = DEFAULT_EXPIRATION_TIME, retries = DEFAULT_RETRIES)
|
23
|
-
retries.times do |count|
|
24
|
-
begin
|
25
|
-
return if @store.set("lock/#{key}", Process.pid, lock_expiry) == "STORED\r\n"
|
26
|
-
end
|
27
|
-
exponential_sleep(count) unless count == retries - 1
|
28
|
-
end
|
29
|
-
raise LockAcquisitionFailureException, "Couldn't acquire memcache lock for: #{key}"
|
30
|
-
end
|
31
|
-
|
32
|
-
def release_lock(key)
|
33
|
-
@store.delete("lock/#{key}")
|
34
|
-
end
|
35
|
-
|
36
|
-
def exponential_sleep(count)
|
37
|
-
@runtime += Benchmark::measure { sleep((2**count) / 10.0) }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
data/test/cache_mock.rb
DELETED
data/test/spec/db/schema.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
ActiveRecord::Schema.define(:version => 1) do
|
2
|
-
create_table "publications", :force => true do |t|
|
3
|
-
t.string "name", "subdomain"
|
4
|
-
end
|
5
|
-
|
6
|
-
create_table "articles", :force => true do |t|
|
7
|
-
t.references 'publication'
|
8
|
-
t.string 'title'
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Publication < ActiveRecord::Base
|
13
|
-
has_many :articles
|
14
|
-
end
|
15
|
-
|
16
|
-
class Article < ActiveRecord::Base
|
17
|
-
belongs_to :publication
|
18
|
-
end
|
data/test/spec/mapper_spec.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
-
|
3
|
-
module CacheAdvance
|
4
|
-
before :each do
|
5
|
-
@cache_set = CacheSet.new
|
6
|
-
@mapper = Mapper.new(@cache_set)
|
7
|
-
end
|
8
|
-
|
9
|
-
describe 'Mapper' do
|
10
|
-
it 'should pass qualifiers directly to the cache set' do
|
11
|
-
proc = Proc.new { 2 }
|
12
|
-
@cache_set.should_receive(:add_qualifier).with(proc)
|
13
|
-
@mapper.qualifier(:testy, proc)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/test/spec/mocks/memcache.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
class MemCache
|
2
|
-
attr_reader :data
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
@data = {}
|
6
|
-
end
|
7
|
-
|
8
|
-
def decr(key, amount = 1)
|
9
|
-
end
|
10
|
-
|
11
|
-
def get(key, raw = false)
|
12
|
-
return @data[key]
|
13
|
-
end
|
14
|
-
|
15
|
-
def get_multi(*keys)
|
16
|
-
end
|
17
|
-
|
18
|
-
def incr(key, amount = 1)
|
19
|
-
end
|
20
|
-
|
21
|
-
def set(key, value, expiry = 0, raw = false)
|
22
|
-
@data[key] = value
|
23
|
-
end
|
24
|
-
|
25
|
-
def add(key, value, expiry = 0, raw = false)
|
26
|
-
end
|
27
|
-
|
28
|
-
def delete(key, expiry = 0)
|
29
|
-
@data.delete(key)
|
30
|
-
end
|
31
|
-
|
32
|
-
def flush_all
|
33
|
-
end
|
34
|
-
|
35
|
-
def reset
|
36
|
-
@data = {}
|
37
|
-
end
|
38
|
-
|
39
|
-
def stats
|
40
|
-
end
|
41
|
-
end
|
data/test/spec/spec_helper.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
-
$: << File.join(File.dirname(__FILE__))
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'ruby-debug'
|
6
|
-
|
7
|
-
gem 'sqlite3-ruby'
|
8
|
-
require 'spec'
|
9
|
-
require 'cache_advance'
|
10
|
-
|
11
|
-
require 'activerecord'
|
12
|
-
|
13
|
-
ActiveRecord::Base.establish_connection(
|
14
|
-
:adapter => 'sqlite3',
|
15
|
-
:dbfile => ':memory:'
|
16
|
-
)
|
17
|
-
|
18
|
-
require File.join(File.dirname(__FILE__), 'db', 'schema')
|
19
|
-
require File.join(File.dirname(__FILE__), 'mocks', 'memcache')
|
20
|
-
|
21
|
-
Spec::Runner.configure do |config|
|
22
|
-
# config.mock_with :rr
|
23
|
-
config.before :each do
|
24
|
-
@memcache = MemCache.new
|
25
|
-
|
26
|
-
CacheAdvance.define_caches(@memcache) do |cache_config|
|
27
|
-
cache_config.publication
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|