cache_advance 1.1.5 → 2.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/VERSION +1 -1
- data/cache_advance.gemspec +7 -10
- data/lib/cache_advance/cache_set.rb +0 -15
- data/lib/cache_advance/named_cache.rb +2 -75
- data/rails/init.rb +0 -19
- metadata +11 -10
- data/lib/cache_advance/active_record_sweeper.rb +0 -32
- 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/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.0
|
data/cache_advance.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cache_advance}
|
8
|
-
s.version = "
|
8
|
+
s.version = "2.0.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Aubrey Holland"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-19}
|
13
13
|
s.description = %q{hmm}
|
14
14
|
s.email = %q{aubreyholland@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,13 +24,9 @@ Gem::Specification.new do |s|
|
|
24
24
|
"VERSION",
|
25
25
|
"cache_advance.gemspec",
|
26
26
|
"lib/cache_advance.rb",
|
27
|
-
"lib/cache_advance/active_record_sweeper.rb",
|
28
27
|
"lib/cache_advance/cache_set.rb",
|
29
|
-
"lib/cache_advance/cached_key_list.rb",
|
30
|
-
"lib/cache_advance/lock.rb",
|
31
28
|
"lib/cache_advance/mapper.rb",
|
32
29
|
"lib/cache_advance/named_cache.rb",
|
33
|
-
"lib/cache_advance/named_cache_configuration.rb",
|
34
30
|
"rails/init.rb",
|
35
31
|
"script/console",
|
36
32
|
"test/active_record_sweeper_test.rb",
|
@@ -44,7 +40,7 @@ Gem::Specification.new do |s|
|
|
44
40
|
s.homepage = %q{http://github.com/aub/cache_advance/tree/master}
|
45
41
|
s.rdoc_options = ["--charset=UTF-8"]
|
46
42
|
s.require_paths = ["lib"]
|
47
|
-
s.rubygems_version = %q{1.3.
|
43
|
+
s.rubygems_version = %q{1.3.7}
|
48
44
|
s.summary = %q{A declarative system for caching with ActiveRecord}
|
49
45
|
s.test_files = [
|
50
46
|
"test/active_record_sweeper_test.rb",
|
@@ -60,9 +56,10 @@ Gem::Specification.new do |s|
|
|
60
56
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
61
57
|
s.specification_version = 3
|
62
58
|
|
63
|
-
if Gem::Version.new(Gem::
|
59
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
64
60
|
else
|
65
61
|
end
|
66
62
|
else
|
67
63
|
end
|
68
64
|
end
|
65
|
+
|
@@ -9,7 +9,6 @@ module CacheAdvance
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def setup_complete
|
12
|
-
|
13
12
|
end
|
14
13
|
|
15
14
|
def apply(cache_name, request, options, &block)
|
@@ -39,19 +38,5 @@ module CacheAdvance
|
|
39
38
|
def define_caches
|
40
39
|
yield Mapper.new(self)
|
41
40
|
end
|
42
|
-
|
43
|
-
def create_sweepers
|
44
|
-
@sweeper_type.initialize_observed(@named_caches.values.map { |c| c.expiration_types }.flatten.compact.uniq)
|
45
|
-
end
|
46
|
-
|
47
|
-
def expire_for_class(class_name)
|
48
|
-
@named_caches.values.each do |named_cache|
|
49
|
-
named_cache.expire_for(class_name)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def sweeper_type=(type)
|
54
|
-
@sweeper_type = type
|
55
|
-
end
|
56
41
|
end
|
57
42
|
end
|
@@ -1,21 +1,14 @@
|
|
1
1
|
module CacheAdvance
|
2
2
|
class NamedCache
|
3
3
|
|
4
|
-
ENABLED_CHECK_INTERVAL = 60
|
5
|
-
|
6
4
|
def initialize(name, params, cache_set, store)
|
7
5
|
@name = name.to_s
|
8
6
|
@params = params
|
9
7
|
@cache_set = cache_set
|
10
8
|
@store = store
|
11
|
-
@cached_key_list = CachedKeyList.new(@store, "#{@name}/STORED_CACHES", expiration_time)
|
12
|
-
@enabled_check_time = Time.now + ENABLED_CHECK_INTERVAL
|
13
|
-
@enabled = nil
|
14
9
|
end
|
15
10
|
|
16
11
|
def value_for(request, options, &block)
|
17
|
-
return block.call unless enabled?
|
18
|
-
|
19
12
|
key = key_for(request, options[:key])
|
20
13
|
|
21
14
|
if (value = read_from_store(key))
|
@@ -32,52 +25,11 @@ module CacheAdvance
|
|
32
25
|
result
|
33
26
|
end
|
34
27
|
|
35
|
-
def expire_for(type)
|
36
|
-
if expiration_types.include?(type)
|
37
|
-
expire_all
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def expire_all
|
42
|
-
delete_all_from_store
|
43
|
-
end
|
44
|
-
|
45
|
-
def all_cached_keys
|
46
|
-
@cached_key_list.all_keys
|
47
|
-
end
|
48
|
-
|
49
|
-
def expiration_types
|
50
|
-
Array(@params[:expiration_types])
|
51
|
-
end
|
52
|
-
|
53
|
-
def title
|
54
|
-
@params[:title] || @name.to_s
|
55
|
-
end
|
56
|
-
|
57
|
-
def enabled=(state)
|
58
|
-
@enabled = !!state
|
59
|
-
@store.set(enabled_key, @enabled)
|
60
|
-
end
|
61
|
-
|
62
|
-
def enabled?
|
63
|
-
if @enabled.nil? || Time.now >= @enabled_check_time
|
64
|
-
@enabled = [nil, true].include?(read_from_store(enabled_key, false))
|
65
|
-
@enabled_check_time = Time.now + ENABLED_CHECK_INTERVAL
|
66
|
-
end
|
67
|
-
@enabled
|
68
|
-
end
|
69
|
-
|
70
28
|
protected
|
71
29
|
|
72
|
-
def read_from_store(key
|
30
|
+
def read_from_store(key)
|
73
31
|
begin
|
74
|
-
|
75
|
-
# this is to prevent a situation where the cached key list forgets
|
76
|
-
# about keys that are actually cached.
|
77
|
-
if data && add_to_key_list
|
78
|
-
@cached_key_list.add_key(key)
|
79
|
-
end
|
80
|
-
data
|
32
|
+
@store.get(key)
|
81
33
|
rescue MemCache::MemCacheError, Errno::ECONNREFUSED => exception
|
82
34
|
log_memcache_error(exception)
|
83
35
|
nil
|
@@ -87,33 +39,12 @@ module CacheAdvance
|
|
87
39
|
def write_to_store(key, value)
|
88
40
|
begin
|
89
41
|
expiration_time ? @store.set(key, value, expiration_time) : @store.set(key, value)
|
90
|
-
@cached_key_list.add_key(key)
|
91
42
|
rescue MemCache::MemCacheError, Errno::ECONNREFUSED => exception
|
92
43
|
log_memcache_error(exception)
|
93
44
|
nil
|
94
45
|
end
|
95
46
|
end
|
96
47
|
|
97
|
-
def delete_from_store(key)
|
98
|
-
begin
|
99
|
-
@store.delete(key)
|
100
|
-
@cached_key_list.delete_key(key)
|
101
|
-
rescue MemCache::MemCacheError, Errno::ECONNREFUSED => exception
|
102
|
-
log_memcache_error(exception)
|
103
|
-
nil
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def delete_all_from_store
|
108
|
-
begin
|
109
|
-
@cached_key_list.all_keys.each { |key| delete_from_store(key) }
|
110
|
-
@cached_key_list.clear
|
111
|
-
rescue MemCache::MemCacheError, Errno::ECONNREFUSED => exception
|
112
|
-
log_memcache_error(exception)
|
113
|
-
nil
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
48
|
def each_plugin
|
118
49
|
@cache_set.plugins.each do |p|
|
119
50
|
yield p
|
@@ -129,10 +60,6 @@ module CacheAdvance
|
|
129
60
|
"#{@name}/#{suffix}/[#{qualifier_data}]".gsub(/\s/, '')
|
130
61
|
end
|
131
62
|
|
132
|
-
def enabled_key
|
133
|
-
"#{@name}/ENABLED_STATUS"
|
134
|
-
end
|
135
|
-
|
136
63
|
def expiration_time
|
137
64
|
@params[:expiration_time]
|
138
65
|
end
|
data/rails/init.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
require 'cache_advance'
|
2
|
-
require 'cache_advance/active_record_sweeper'
|
3
2
|
|
4
3
|
require "#{RAILS_ROOT}/config/caches"
|
5
4
|
require 'dispatcher'
|
6
5
|
|
7
|
-
# Setup the sweeper and cache types as appropriate for Rails.
|
8
|
-
CacheAdvance.cache_set.sweeper_type = CacheAdvance::ActiveRecordSweeper
|
9
|
-
|
10
6
|
CacheAdvance.caching_enabled = config.action_controller.perform_caching
|
11
7
|
|
12
8
|
# This is the helper method that can be used in rails views/controllers/helpers.
|
@@ -35,18 +31,3 @@ ActionMailer::Base.helper do
|
|
35
31
|
capture(&block)
|
36
32
|
end
|
37
33
|
end
|
38
|
-
|
39
|
-
# This will get called after the standard rails environment is initialized.
|
40
|
-
config.after_initialize do
|
41
|
-
if config.action_controller.perform_caching
|
42
|
-
# This hooks the sweepers into the observer system and adds it to the list.
|
43
|
-
CacheAdvance.cache_set.create_sweepers
|
44
|
-
ActiveRecord::Base.observers << CacheAdvance::ActiveRecordSweeper
|
45
|
-
|
46
|
-
# In development mode, the models we observe get reloaded with each request. Using
|
47
|
-
# this hook allows us to reload the observer relationships each time as well.
|
48
|
-
ActionController::Dispatcher.to_prepare(:cache_advance_reload) do
|
49
|
-
CacheAdvance::ActiveRecordSweeper.instance.reload_sweeper
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cache_advance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
|
-
-
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version:
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 2.0.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Aubrey Holland
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date:
|
18
|
+
date: 2011-01-19 00:00:00 -05:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -35,13 +36,9 @@ files:
|
|
35
36
|
- VERSION
|
36
37
|
- cache_advance.gemspec
|
37
38
|
- lib/cache_advance.rb
|
38
|
-
- lib/cache_advance/active_record_sweeper.rb
|
39
39
|
- lib/cache_advance/cache_set.rb
|
40
|
-
- lib/cache_advance/cached_key_list.rb
|
41
|
-
- lib/cache_advance/lock.rb
|
42
40
|
- lib/cache_advance/mapper.rb
|
43
41
|
- lib/cache_advance/named_cache.rb
|
44
|
-
- lib/cache_advance/named_cache_configuration.rb
|
45
42
|
- rails/init.rb
|
46
43
|
- script/console
|
47
44
|
- test/active_record_sweeper_test.rb
|
@@ -61,23 +58,27 @@ rdoc_options:
|
|
61
58
|
require_paths:
|
62
59
|
- lib
|
63
60
|
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
64
62
|
requirements:
|
65
63
|
- - ">="
|
66
64
|
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
67
66
|
segments:
|
68
67
|
- 0
|
69
68
|
version: "0"
|
70
69
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
71
|
requirements:
|
72
72
|
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
74
75
|
segments:
|
75
76
|
- 0
|
76
77
|
version: "0"
|
77
78
|
requirements: []
|
78
79
|
|
79
80
|
rubyforge_project:
|
80
|
-
rubygems_version: 1.3.
|
81
|
+
rubygems_version: 1.3.7
|
81
82
|
signing_key:
|
82
83
|
specification_version: 3
|
83
84
|
summary: A declarative system for caching with ActiveRecord
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
gem 'activerecord'
|
3
|
-
require 'active_record/observer'
|
4
|
-
|
5
|
-
module CacheAdvance
|
6
|
-
class ActiveRecordSweeper < ::ActiveRecord::Observer
|
7
|
-
|
8
|
-
def self.initialize_observed(classes)
|
9
|
-
observe(classes)
|
10
|
-
end
|
11
|
-
|
12
|
-
def reload_sweeper
|
13
|
-
observed_classes.each do |klass|
|
14
|
-
klass.name.constantize.add_observer(self)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def after_create(object)
|
19
|
-
expire_caches_for(object)
|
20
|
-
end
|
21
|
-
|
22
|
-
alias_method :after_update, :after_create
|
23
|
-
alias_method :after_destroy, :after_create
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
|
-
def expire_caches_for(object)
|
28
|
-
class_symbol = object.class.name.underscore.to_sym
|
29
|
-
CacheAdvance.cache_set.expire_for_class(class_symbol)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -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
|
-
sleep((2**count) / 10.0)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|