interlock 1.0 → 1.1
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/CHANGELOG +2 -0
- data/Manifest +8 -15
- data/README +16 -73
- data/TODO +3 -0
- data/interlock.gemspec +16 -9
- data/lib/interlock/action_controller.rb +135 -36
- data/lib/interlock/action_view.rb +85 -18
- data/lib/interlock/active_record.rb +1 -1
- data/lib/interlock/config.rb +1 -1
- data/lib/interlock/interlock.rb +22 -3
- data/tasks/interlock.rake +10 -0
- data/test/integration/app/app/controllers/application.rb +2 -2
- data/test/integration/app/app/controllers/items_controller.rb +19 -1
- data/test/integration/app/app/views/items/detail.rhtml +20 -0
- data/test/integration/app/app/views/items/{list.html.erb → list.rhtml} +6 -0
- data/test/integration/app/app/views/items/{recent.html.erb → recent.rhtml} +0 -0
- data/test/integration/app/app/views/items/{show.html.erb → show.rhtml} +1 -1
- data/test/integration/app/app/views/layouts/application.html.erb +9 -0
- data/test/integration/app/app/views/shared/{_related.html.erb → _related.rhtml} +0 -0
- data/test/integration/app/config/boot.rb +2 -0
- data/test/integration/app/config/environment.rb +1 -3
- data/test/integration/server_test.rb +53 -6
- data/test/setup.rb +5 -0
- data/test/teardown.rb +0 -4
- data/test/test_helper.rb +9 -2
- data/test/unit/interlock_test.rb +21 -0
- data.tar.gz.sig +0 -0
- metadata +14 -20
- metadata.gz.sig +0 -0
- data/test/integration/app/coverage/cache-43041 +0 -0
- data/test/integration/app/coverage/index.html +0 -414
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-action_controller_rb.html +0 -733
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-action_view_rb.html +0 -644
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-active_record_rb.html +0 -639
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-config_rb.html +0 -688
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-core_extensions_rb.html +0 -674
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-interlock_rb.html +0 -722
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-memcached_rb.html +0 -640
- data/test/integration/app/coverage/vendor-plugins-interlock-lib-interlock_rb.html +0 -635
- data/test/integration/app/db/schema.rb +0 -21
data/lib/interlock/config.rb
CHANGED
@@ -19,7 +19,7 @@ module Interlock
|
|
19
19
|
#
|
20
20
|
# Load the configuration file, if available, and then set up the Memcached instance,
|
21
21
|
# Rails settings, and CACHE constants. Should be more or less compatible with
|
22
|
-
#
|
22
|
+
# Cache_fu.
|
23
23
|
#
|
24
24
|
def run!
|
25
25
|
if File.exist?(CONFIG_FILE)
|
data/lib/interlock/interlock.rb
CHANGED
@@ -7,9 +7,20 @@ module Interlock
|
|
7
7
|
end
|
8
8
|
class UsageError < InterlockError #:nodoc:
|
9
9
|
end
|
10
|
+
class FragmentConsistencyError < InterlockError #:nodoc:
|
11
|
+
end
|
10
12
|
|
11
13
|
SCOPE_KEYS = [:controller, :action, :id]
|
12
14
|
|
15
|
+
# Buried value extracted from memcache.rb in the memcache-client gem.
|
16
|
+
# If one tries to request a key that is too long, the client throws an error.
|
17
|
+
# In practice, it seems better to simply avoid ever setting such long keys,
|
18
|
+
# so we use this value to achieve such for keys generated by Interlock.
|
19
|
+
KEY_LENGTH_LIMIT = 250
|
20
|
+
|
21
|
+
# Similarly buried and useful: no whitespace allowed in keys.
|
22
|
+
ILLEGAL_KEY_CHARACTERS_PATTERN = /\s/
|
23
|
+
|
13
24
|
mattr_accessor :local_cache
|
14
25
|
|
15
26
|
class << self
|
@@ -93,12 +104,20 @@ module Interlock
|
|
93
104
|
# rolling your own.
|
94
105
|
#
|
95
106
|
def caching_key(controller, action, id, tag)
|
96
|
-
raise ArgumentError,
|
107
|
+
raise ArgumentError, 'Both controller and action must be specified' unless controller and action
|
97
108
|
|
98
109
|
id = (id or 'all').to_interlock_tag
|
99
110
|
tag = tag.to_interlock_tag
|
100
|
-
|
101
|
-
"interlock:#{ENV['RAILS_ASSET_ID']}:#{controller}:#{action}:#{id}:#{tag}"
|
111
|
+
|
112
|
+
key = "interlock:#{ENV['RAILS_ASSET_ID']}:#{controller}:#{action}:#{id}:#{tag}"
|
113
|
+
|
114
|
+
if key.length > KEY_LENGTH_LIMIT
|
115
|
+
old_key = key
|
116
|
+
key = key[0..KEY_LENGTH_LIMIT-1]
|
117
|
+
say old_key, "truncated to #{key}"
|
118
|
+
end
|
119
|
+
|
120
|
+
key.gsub ILLEGAL_KEY_CHARACTERS_PATTERN, ''
|
102
121
|
end
|
103
122
|
|
104
123
|
#
|
@@ -2,9 +2,9 @@
|
|
2
2
|
# Likewise, all the methods added will be available for all controllers.
|
3
3
|
|
4
4
|
class ApplicationController < ActionController::Base
|
5
|
-
helper :all # include all helpers, all the time
|
5
|
+
# helper :all # include all helpers, all the time
|
6
6
|
|
7
7
|
# See ActionController::RequestForgeryProtection for details
|
8
8
|
# Uncomment the :secret if you're not using the cookie session store
|
9
|
-
protect_from_forgery # :secret => '491bb7f9ad07a91046fcc3756839524b'
|
9
|
+
# protect_from_forgery # :secret => '491bb7f9ad07a91046fcc3756839524b'
|
10
10
|
end
|
@@ -9,6 +9,16 @@ class ItemsController < ApplicationController
|
|
9
9
|
render :action => 'list'
|
10
10
|
end
|
11
11
|
|
12
|
+
def detail
|
13
|
+
# Nesting is theoretically useful when the outer view block invalidates faster than the inner one
|
14
|
+
behavior_cache :tag => :outer do
|
15
|
+
@items = Item.find(:all)
|
16
|
+
end
|
17
|
+
behavior_cache Item => :id, :tag => :inner do
|
18
|
+
@item = Item.find(params[:id])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
12
22
|
def show
|
13
23
|
behavior_cache Item => :id do
|
14
24
|
@item = Item.find(params['id'])
|
@@ -21,6 +31,14 @@ class ItemsController < ApplicationController
|
|
21
31
|
end
|
22
32
|
end
|
23
33
|
|
34
|
+
def preview
|
35
|
+
@perform = false
|
36
|
+
behavior_cache Item => :id, :perform => @perform do
|
37
|
+
@item = Item.find(params['id'])
|
38
|
+
end
|
39
|
+
render :action => 'show'
|
40
|
+
end
|
41
|
+
|
24
42
|
private
|
25
43
|
|
26
44
|
def related
|
@@ -28,5 +46,5 @@ class ItemsController < ApplicationController
|
|
28
46
|
@related = "Delicious cake"
|
29
47
|
end
|
30
48
|
end
|
31
|
-
|
49
|
+
|
32
50
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
<% view_cache :tag => :outer do %>
|
3
|
+
<div style="border: 1px solid black; padding: 5px;">
|
4
|
+
<p>I invalidate quickly.</p>
|
5
|
+
<h1><%= @items.size %> total items</h1>
|
6
|
+
|
7
|
+
<% content_for :title do %>Outer: <% end %>
|
8
|
+
|
9
|
+
<% view_cache :tag => :inner do %>
|
10
|
+
<div style="margin: 20px; padding: 5px; border: 1px solid black;">
|
11
|
+
<p>I invalidate slowly.</p>
|
12
|
+
<h2>Item <%= @item.id %> is <%= @item.name %>.</h2>
|
13
|
+
|
14
|
+
<% content_for :title do %>Inner<% end %>
|
15
|
+
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
</div>
|
20
|
+
<% end %>
|
@@ -1,10 +1,16 @@
|
|
1
1
|
|
2
2
|
<h1>List</h1>
|
3
3
|
<% view_cache do %>
|
4
|
+
|
5
|
+
<% content_for :title do %>
|
6
|
+
<%= @items.size %> Items
|
7
|
+
<% end %>
|
8
|
+
|
4
9
|
<% @items.each do |item| %>
|
5
10
|
<h3><%= item.name %></h3>
|
6
11
|
<p><%= item.description %></p>
|
7
12
|
<% end %>
|
13
|
+
|
8
14
|
<% end %>
|
9
15
|
|
10
16
|
<%= render :partial => 'shared/related' %>
|
File without changes
|
File without changes
|
@@ -55,8 +55,10 @@ module Rails
|
|
55
55
|
|
56
56
|
def load_rails_gem
|
57
57
|
if version = self.class.gem_version
|
58
|
+
STDERR.puts "Boot.rb loading version #{version}"
|
58
59
|
gem 'rails', version
|
59
60
|
else
|
61
|
+
STDERR.puts "Boot.rb loading latest available version"
|
60
62
|
gem 'rails'
|
61
63
|
end
|
62
64
|
rescue Gem::LoadError => load_error
|
@@ -1,13 +1,11 @@
|
|
1
1
|
|
2
|
-
RAILS_GEM_VERSION = ENV['MULTIRAILS_RAILS_VERSION'] if ENV['MULTIRAILS_RAILS_VERSION']
|
3
|
-
|
4
2
|
require File.join(File.dirname(__FILE__), 'boot')
|
5
3
|
require 'action_controller'
|
6
4
|
|
7
5
|
Rails::Initializer.run do |config|
|
8
6
|
|
9
7
|
if ActionController::Base.respond_to? 'session='
|
10
|
-
config.action_controller.session = {:session_key => '_app_session', :secret => '
|
8
|
+
config.action_controller.session = {:session_key => '_app_session', :secret => '22cde4d5c1a61ba69a81795322cde4d5c1a61ba69a817953'}
|
11
9
|
end
|
12
10
|
|
13
11
|
# config.to_prepare do
|
@@ -70,7 +70,8 @@ class ServerTest < Test::Unit::TestCase
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_caching_with_tag
|
73
|
-
|
73
|
+
# This test is a little over-complicated
|
74
|
+
sleep(4)
|
74
75
|
assert_no_match(/Artichoke/, browse("items/recent?seconds=3"))
|
75
76
|
assert_match(/recent:all:3 is running the controller block/, log)
|
76
77
|
|
@@ -79,15 +80,26 @@ class ServerTest < Test::Unit::TestCase
|
|
79
80
|
assert_match(/recent:all:2 is running the controller block/, log)
|
80
81
|
assert_no_match(/recent:all:3 is running the controller block/, log)
|
81
82
|
|
83
|
+
truncate
|
84
|
+
remote_eval("Item.find(1).save!")
|
85
|
+
assert_match(/Artichoke/, browse("items/recent?seconds=4"))
|
86
|
+
assert_match(/recent:all:4 is running the controller block/, log)
|
87
|
+
|
82
88
|
truncate
|
83
89
|
assert_no_match(/Artichoke/, browse("items/recent?seconds=3"))
|
84
|
-
assert_no_match(/recent:all:3 is running the controller block/, log)
|
90
|
+
assert_no_match(/recent:all:3 is running the controller block/, log)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_caching_with_perform_false
|
94
|
+
browse("items/preview/1")
|
95
|
+
assert_no_match(/preview:1:untagged registered a dependency/, log)
|
96
|
+
assert_match(/preview:1:untagged is not cached/, log)
|
85
97
|
|
86
98
|
truncate
|
87
|
-
|
88
|
-
|
89
|
-
assert_match(/
|
90
|
-
end
|
99
|
+
browse("items/preview/1")
|
100
|
+
assert_no_match(/preview:1:untagged registered a dependency/, log)
|
101
|
+
assert_match(/preview:1:untagged is not cached/, log)
|
102
|
+
end
|
91
103
|
|
92
104
|
def test_caching_with_ignore
|
93
105
|
assert_match(/Delicious cake/, browse('items'))
|
@@ -104,6 +116,41 @@ class ServerTest < Test::Unit::TestCase
|
|
104
116
|
assert_match(/any:any:all:related is running the controller block/, log)
|
105
117
|
end
|
106
118
|
|
119
|
+
def test_caching_of_content_for
|
120
|
+
assert_match(/Interlock Test:\s*\d\s*Items/m, browse("items"))
|
121
|
+
assert_match(/all:untagged is running the controller block/, log)
|
122
|
+
assert_match(/all:untagged wrote/, log)
|
123
|
+
|
124
|
+
truncate
|
125
|
+
assert_match(/Interlock Test:\s*\d\s*Items/m, browse("items"))
|
126
|
+
# Make sure we didn't copy the content_for too many times
|
127
|
+
assert_no_match(/Interlock Test:\s*\d\s*Items\s*\d\s*Items/m, browse("items"))
|
128
|
+
assert_no_match(/all:untagged is running the controller block/, log)
|
129
|
+
assert_match(/all:untagged read from memcached/, log)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_nested_view_caches
|
133
|
+
assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1"))
|
134
|
+
assert_match(/detail:1:outer is running the controller block/, log)
|
135
|
+
assert_match(/detail:1:inner is running the controller block/, log)
|
136
|
+
|
137
|
+
truncate
|
138
|
+
assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1"))
|
139
|
+
assert_no_match(/detail:1:outer is running the controller block/, log)
|
140
|
+
assert_no_match(/detail:1:inner is running the controller block/, log)
|
141
|
+
|
142
|
+
truncate
|
143
|
+
remote_eval("Item.find(2).save!")
|
144
|
+
assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1"))
|
145
|
+
assert_match(/detail:1:outer is running the controller block/, log)
|
146
|
+
assert_no_match(/detail:1:inner is running the controller block/, log)
|
147
|
+
|
148
|
+
truncate
|
149
|
+
remote_eval("Item.find(1).save!")
|
150
|
+
assert_match(/Outer: Inner<.*2 total items.*Artichoke/m, browse("items/detail/1"))
|
151
|
+
assert_match(/detail:1:outer is running the controller block/, log)
|
152
|
+
assert_match(/detail:1:inner is running the controller block/, log)
|
153
|
+
end
|
107
154
|
|
108
155
|
### Support methods
|
109
156
|
|
data/test/setup.rb
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
# Setup integration system for the integration suite
|
3
3
|
|
4
4
|
Dir.chdir "#{File.dirname(__FILE__)}/integration/app/" do
|
5
|
+
|
6
|
+
`ps awx`.split("\n").grep(/4304[1-3]/).map do |process|
|
7
|
+
system("kill -9 #{process.to_i}")
|
8
|
+
end
|
9
|
+
|
5
10
|
system "memcached -p 43042 &"
|
6
11
|
system "memcached -p 43043 &"
|
7
12
|
|
data/test/teardown.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -2,12 +2,19 @@
|
|
2
2
|
$VERBOSE = nil
|
3
3
|
require 'rubygems'
|
4
4
|
require 'test/unit'
|
5
|
+
require 'echoe'
|
5
6
|
require 'multi_rails_init'
|
6
7
|
|
8
|
+
if defined? ENV['MULTIRAILS_RAILS_VERSION']
|
9
|
+
ENV['RAILS_GEM_VERSION'] = ENV['MULTIRAILS_RAILS_VERSION']
|
10
|
+
end
|
11
|
+
|
7
12
|
$rcov = ENV['RCOV']
|
8
13
|
require 'ruby-debug' unless $rcov
|
9
14
|
|
10
|
-
|
11
|
-
|
15
|
+
Echoe.silence do
|
16
|
+
HERE = File.expand_path(File.dirname(__FILE__))
|
17
|
+
$LOAD_PATH << HERE
|
18
|
+
end
|
12
19
|
|
13
20
|
require 'integration/app/config/environment'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../test_helper"
|
2
|
+
|
3
|
+
class InterlockTest < Test::Unit::TestCase
|
4
|
+
def test_caching_key_requires_controller_and_action
|
5
|
+
assert_raises ArgumentError do
|
6
|
+
Interlock.caching_key nil, nil, nil, nil
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_caching_key_prevents_too_long_keys
|
11
|
+
assert_equal Interlock::KEY_LENGTH_LIMIT,
|
12
|
+
Interlock.caching_key('controller', 'action', 'id', 'x'*Interlock::KEY_LENGTH_LIMIT).size,
|
13
|
+
"keys longer than #{Interlock::KEY_LENGTH_LIMIT} will result in errors from memcache-client"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_caching_key_strips_whitespace
|
17
|
+
assert_no_match Interlock::ILLEGAL_KEY_CHARACTERS_PATTERN,
|
18
|
+
Interlock.caching_key('controller', 'action', 'id', 'tag with illegal characters')
|
19
|
+
'generated keys should not contain illegal characters'
|
20
|
+
end
|
21
|
+
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interlock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.1"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ""
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
yZ0=
|
31
31
|
-----END CERTIFICATE-----
|
32
32
|
|
33
|
-
date:
|
33
|
+
date: 2008-01-15 00:00:00 -05:00
|
34
34
|
default_executable:
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 1.5.0
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: A Rails plugin for maintainable and high-efficiency caching.
|
46
46
|
email: ""
|
47
47
|
executables: []
|
48
48
|
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- LICENSE
|
66
66
|
- Manifest
|
67
67
|
- README
|
68
|
+
- tasks/interlock.rake
|
68
69
|
- test/integration/app/app/controllers/application.rb
|
69
70
|
- test/integration/app/app/controllers/eval_controller.rb
|
70
71
|
- test/integration/app/app/controllers/items_controller.rb
|
@@ -72,10 +73,12 @@ files:
|
|
72
73
|
- test/integration/app/app/helpers/eval_helper.rb
|
73
74
|
- test/integration/app/app/helpers/items_helper.rb
|
74
75
|
- test/integration/app/app/models/item.rb
|
75
|
-
- test/integration/app/app/views/items/
|
76
|
-
- test/integration/app/app/views/items/
|
77
|
-
- test/integration/app/app/views/items/
|
78
|
-
- test/integration/app/app/views/
|
76
|
+
- test/integration/app/app/views/items/detail.rhtml
|
77
|
+
- test/integration/app/app/views/items/list.rhtml
|
78
|
+
- test/integration/app/app/views/items/recent.rhtml
|
79
|
+
- test/integration/app/app/views/items/show.rhtml
|
80
|
+
- test/integration/app/app/views/layouts/application.html.erb
|
81
|
+
- test/integration/app/app/views/shared/_related.rhtml
|
79
82
|
- test/integration/app/config/boot.rb
|
80
83
|
- test/integration/app/config/database.yml
|
81
84
|
- test/integration/app/config/environment.rb
|
@@ -86,18 +89,7 @@ files:
|
|
86
89
|
- test/integration/app/config/initializers/mime_types.rb
|
87
90
|
- test/integration/app/config/memcached.yml
|
88
91
|
- test/integration/app/config/routes.rb
|
89
|
-
- test/integration/app/coverage/cache-43041
|
90
|
-
- test/integration/app/coverage/index.html
|
91
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-action_controller_rb.html
|
92
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-action_view_rb.html
|
93
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-active_record_rb.html
|
94
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-config_rb.html
|
95
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-core_extensions_rb.html
|
96
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-interlock_rb.html
|
97
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock-memcached_rb.html
|
98
|
-
- test/integration/app/coverage/vendor-plugins-interlock-lib-interlock_rb.html
|
99
92
|
- test/integration/app/db/migrate/001_create_items.rb
|
100
|
-
- test/integration/app/db/schema.rb
|
101
93
|
- test/integration/app/doc/README_FOR_APP
|
102
94
|
- test/integration/app/public/404.html
|
103
95
|
- test/integration/app/public/422.html
|
@@ -138,6 +130,7 @@ files:
|
|
138
130
|
- test/setup.rb
|
139
131
|
- test/teardown.rb
|
140
132
|
- test/test_helper.rb
|
133
|
+
- test/unit/interlock_test.rb
|
141
134
|
- test/unit/memcached_test.rb
|
142
135
|
- TODO
|
143
136
|
- interlock.gemspec
|
@@ -163,10 +156,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
156
|
requirements: []
|
164
157
|
|
165
158
|
rubyforge_project: fauna
|
166
|
-
rubygems_version: 0.
|
159
|
+
rubygems_version: 1.0.1
|
167
160
|
signing_key:
|
168
161
|
specification_version: 2
|
169
|
-
summary:
|
162
|
+
summary: A Rails plugin for maintainable and high-efficiency caching.
|
170
163
|
test_files:
|
171
164
|
- test/integration/server_test.rb
|
165
|
+
- test/unit/interlock_test.rb
|
172
166
|
- test/unit/memcached_test.rb
|
metadata.gz.sig
CHANGED
Binary file
|
Binary file
|