lacquer 0.5.5 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +216 -214
- data/lib/lacquer/cache_control.rb +13 -14
- data/lib/lacquer/cache_utils.rb +1 -1
- data/lib/lacquer/configuration.rb +47 -47
- data/lib/lacquer/recipes.rb +7 -7
- data/lib/lacquer/tasks.rb +4 -4
- data/lib/lacquer/varnish.rb +10 -7
- data/lib/lacquer/varnishd.rb +24 -25
- data/lib/lacquer/version.rb +1 -1
- data/spec/config/generate.vcl.erb +0 -1
- data/spec/config/varnish.vcl +0 -1
- data/spec/lacquer/cache_control_spec.rb +6 -6
- data/spec/lacquer/delayed_job_job_spec.rb +2 -0
- data/spec/lacquer/resque_job_spec.rb +2 -0
- data/spec/lacquer/varnish_spec.rb +4 -4
- data/spec/lacquer/varnishd_spec.rb +11 -13
- data/spec/spec_helper.rb +1 -1
- metadata +14 -14
data/README.rdoc
CHANGED
@@ -1,214 +1,216 @@
|
|
1
|
-
= lacquer
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
# req.url ~ "
|
135
|
-
# req.url ~ "
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
rake lacquer:varnishd:
|
189
|
-
rake lacquer:varnishd:
|
190
|
-
rake lacquer:varnishd:
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
*
|
209
|
-
*
|
210
|
-
*
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
Copyright
|
1
|
+
{<img src="https://secure.travis-ci.org/russ/lacquer.png?branch=master" alt="Build Status" />}[http://travis-ci.org/russ/lacquer]
|
2
|
+
|
3
|
+
= lacquer
|
4
|
+
|
5
|
+
Rails drop in for Varnish support.
|
6
|
+
|
7
|
+
== Install
|
8
|
+
This gem requires ruby 1.9
|
9
|
+
|
10
|
+
Basic installation
|
11
|
+
|
12
|
+
sudo gem install lacquer
|
13
|
+
rails generate lacquer:install
|
14
|
+
|
15
|
+
config/initializers/lacquer.rb
|
16
|
+
|
17
|
+
Lacquer.configure do |config|
|
18
|
+
# Globally enable/disable cache
|
19
|
+
config.enable_cache = true
|
20
|
+
|
21
|
+
# Unless overridden in a controller or action, the default will be used
|
22
|
+
config.default_ttl = 1.week
|
23
|
+
|
24
|
+
# Can be :none, :delayed_job, :resque
|
25
|
+
config.job_backend = :none
|
26
|
+
|
27
|
+
# Array of Varnish servers to manage
|
28
|
+
config.varnish_servers << {
|
29
|
+
:host => "0.0.0.0", :port => 6082 # if you have authentication enabled, add :secret => "your secret"
|
30
|
+
}
|
31
|
+
|
32
|
+
# Number of retries
|
33
|
+
config.retries = 5
|
34
|
+
|
35
|
+
# config handler (optional, if you use Hoptoad or another error tracking service)
|
36
|
+
config.command_error_handler = lambda { |s| HoptoadNotifier.notify(s) }
|
37
|
+
|
38
|
+
|
39
|
+
### Varnish - 2.x / 3.x .. VCL-Changes
|
40
|
+
### https://www.varnish-cache.org/docs/trunk/installation/upgrade.html
|
41
|
+
|
42
|
+
# => Purge Command ( "url.purge" for Varnish 2.x .. "ban.url" for Varnish 3.x )
|
43
|
+
# => purges are now called bans in Varnish 3.x .. purge() and purge_url() are now respectively ban() and ban_url()
|
44
|
+
config.purge_command = "ban.url"
|
45
|
+
|
46
|
+
# => VCL_Fetch Pass Command ( "pass" for Varnish 2.x .. "hit_for_pass" for Varnish 3.x )
|
47
|
+
# => pass in vcl_fetch renamed to hit_for_pass in Varnish 3.x
|
48
|
+
config.pass_command = "pass"
|
49
|
+
end
|
50
|
+
|
51
|
+
app/controllers/application_controller.rb
|
52
|
+
|
53
|
+
class ApplicationController < ActionController::Base
|
54
|
+
include Lacquer::CacheUtils
|
55
|
+
end
|
56
|
+
|
57
|
+
config/varnishd.yml
|
58
|
+
|
59
|
+
development:
|
60
|
+
listen: localhost:3001
|
61
|
+
telnet: localhost:6082
|
62
|
+
sbin_path: /usr/local/sbin
|
63
|
+
storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"
|
64
|
+
|
65
|
+
test:
|
66
|
+
listen: localhost:3002
|
67
|
+
telnet: localhost:6083
|
68
|
+
sbin_path: /usr/local/sbin
|
69
|
+
storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"
|
70
|
+
|
71
|
+
production:
|
72
|
+
listen: :80
|
73
|
+
telnet: localhost:6082
|
74
|
+
sbin_path: /usr/local/sbin
|
75
|
+
storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"
|
76
|
+
params:
|
77
|
+
overflow_max: 2000 # for Varnish 2.x ... use "queue_max: 2000" for Varnish 3.x
|
78
|
+
thread_pool_add_delay: 2
|
79
|
+
thread_pools: 4 # <Number of cpu cores>
|
80
|
+
thread_pool_min: 200 # <800/number of cpu cores>
|
81
|
+
thread_pool_max: 4000
|
82
|
+
|
83
|
+
If only some urls of the application should be cached by varnish, Lacquer::CacheControl will be helpful.
|
84
|
+
|
85
|
+
config/initializers/caches.rb
|
86
|
+
|
87
|
+
require "lacquer/cache_control"
|
88
|
+
|
89
|
+
Lacquer.cache_control.configure do |config|
|
90
|
+
config.register :static, :url => "^/images",
|
91
|
+
:expires_in => "365d"
|
92
|
+
|
93
|
+
config.register :static, :url => "^/stylesheets",
|
94
|
+
:expires_in => "365d"
|
95
|
+
|
96
|
+
config.register :static, :url => "^/javascripts",
|
97
|
+
:expires_in => "365d"
|
98
|
+
|
99
|
+
config.register :class_section, :url => "^(/[a-z]{2})?/(info_screens|class_sections)/%s.*$",
|
100
|
+
:args => "[0-9]+",
|
101
|
+
:expires_in => "1m"
|
102
|
+
|
103
|
+
config.register :open_scoring, :url => "^(/[a-z]{2})?/class_sections/%s/open_scoring.*$",
|
104
|
+
:args => "[0-9]+",
|
105
|
+
:expires_in => "1m"
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
In the sweeper we can do something like this
|
110
|
+
|
111
|
+
class_section = ClassSection.find(1)
|
112
|
+
Lacquer.cache_control.purge(:open_scoring, class_section)
|
113
|
+
|
114
|
+
This will purge "^(/[a-z]{2})?/class_sections/1/open_scoring.*$" (/sv/class_sections/1/open_scoring.js, /sv/class_sections/1/open_scoring.html)
|
115
|
+
|
116
|
+
The varnish.vcl is preprocssed when starting varnishd with the rake tasks
|
117
|
+
|
118
|
+
rake lacquer:varnishd:start
|
119
|
+
|
120
|
+
config/varnish.vcl.erb
|
121
|
+
|
122
|
+
sub vcl_recv {
|
123
|
+
# Lookup requests that we know should be cached
|
124
|
+
if (<%= Lacquer.cache_control.to_vcl_conditions %>) {
|
125
|
+
# Clear cookie and authorization headers, set grace time, lookup in the cache
|
126
|
+
unset req.http.Cookie;
|
127
|
+
unset req.http.Authorization;
|
128
|
+
return(lookup);
|
129
|
+
}
|
130
|
+
|
131
|
+
# Generates
|
132
|
+
#
|
133
|
+
# if(req.url ~ "^/images" ||
|
134
|
+
# req.url ~ "^/stylesheets" ||
|
135
|
+
# req.url ~ "^/javascripts" ||
|
136
|
+
# req.url ~ "^(/[a-z]{2})?/(info_screens|class_sections)/[0-9]+.*$" ||
|
137
|
+
# req.url ~ "^(/[a-z]{2})?/class_sections/[0-9]+/open_scoring.*$") {
|
138
|
+
# unset req.http.Cookie;
|
139
|
+
# unset req.http.Authorization;
|
140
|
+
# return(lookup);
|
141
|
+
# }
|
142
|
+
}
|
143
|
+
|
144
|
+
sub vcl_fetch {
|
145
|
+
<%= Lacquer.cache_control.to_vcl_override_ttl_urls %>
|
146
|
+
|
147
|
+
# Generates
|
148
|
+
#
|
149
|
+
# if(req.url ~ "^/images" || req.url ~ "^/stylesheets" || req.url ~ "^/javascripts") {
|
150
|
+
# unset beresp.http.Set-Cookie;
|
151
|
+
# set beresp.ttl = 365d;
|
152
|
+
# return(deliver);
|
153
|
+
# }
|
154
|
+
#
|
155
|
+
# if(req.url ~ "^(/[a-z]{2})?/(info_screens|class_sections)/[0-9]+.*$" ||
|
156
|
+
# req.url ~ "^(/[a-z]{2})?/class_sections/[0-9]+/open_scoring.*$") {
|
157
|
+
# unset beresp.http.Set-Cookie;
|
158
|
+
# set beresp.ttl = 1m;
|
159
|
+
# return(deliver);
|
160
|
+
# }
|
161
|
+
}
|
162
|
+
|
163
|
+
This makes it much simpler to perform cacheing, it's only setuped in one place, purge it or just let it expire.
|
164
|
+
|
165
|
+
== Usage
|
166
|
+
|
167
|
+
To set a custom ttl for a controller:
|
168
|
+
|
169
|
+
before_filter { |controller| controller.set_cache_ttl(15.minutes) }
|
170
|
+
|
171
|
+
Clearing the cache:
|
172
|
+
|
173
|
+
class Posts < ApplicationController
|
174
|
+
after_filter :clear_cache, :only => [ :create, :update, :destroy ]
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def clear_cache
|
179
|
+
clear_cache_for(
|
180
|
+
root_path,
|
181
|
+
posts_path,
|
182
|
+
post_path(@post))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
Control varnishd with the following rake tasks
|
187
|
+
|
188
|
+
rake lacquer:varnishd:start
|
189
|
+
rake lacquer:varnishd:stop
|
190
|
+
rake lacquer:varnishd:restart
|
191
|
+
rake lacquer:varnishd:status
|
192
|
+
rake lacquer:varnishd:global_purge
|
193
|
+
|
194
|
+
== Gotchas
|
195
|
+
|
196
|
+
The default TTL for most actions is set to 0, since for most cases you'll probably want to be fairly explicit about what pages do get cached by varnish. The default cache header is typically:
|
197
|
+
|
198
|
+
Cache-Control: max-age=0, no-cache, private
|
199
|
+
|
200
|
+
This is good for normal controller actions, since you won't want to cache them. If TTL for an action is set to 0, it won't mess with the default header.
|
201
|
+
|
202
|
+
The key gotcha here is that cached pages strip cookies, so if your application relies on sessions and uses authenticity tokens, the user will need a session cookie set before form actions will work. Setting default TTL to 0 here will make sure these session cookies won't break.
|
203
|
+
|
204
|
+
As a result, all you have to do to set a cacheable action is the before filter above.
|
205
|
+
|
206
|
+
== Note on Patches/Pull Requests
|
207
|
+
|
208
|
+
* Fork the project.
|
209
|
+
* Make your feature addition or bug fix.
|
210
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
211
|
+
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
212
|
+
* Send me a pull request. Bonus points for topic branches.
|
213
|
+
|
214
|
+
== Copyright
|
215
|
+
|
216
|
+
Copyright (c) 2010 Russ Smith. See LICENSE for details.
|
@@ -1,40 +1,39 @@
|
|
1
1
|
module Lacquer
|
2
|
-
|
3
2
|
def self.cache_control
|
4
3
|
@cache_control ||= CacheControl.new
|
5
4
|
end
|
6
|
-
|
5
|
+
|
7
6
|
class CacheControl
|
8
7
|
include Lacquer::CacheUtils
|
9
8
|
attr_accessor :store
|
10
|
-
|
9
|
+
|
11
10
|
def initialize
|
12
11
|
self.store = []
|
13
12
|
end
|
14
|
-
|
13
|
+
|
15
14
|
def register(group, options = {})
|
16
15
|
options[:group] = group
|
17
16
|
options[:args] = Array(options[:args]).compact
|
18
17
|
store << options
|
19
18
|
end
|
20
|
-
|
19
|
+
|
21
20
|
def configure
|
22
21
|
yield self
|
23
22
|
end
|
24
|
-
|
23
|
+
|
25
24
|
def purge(group, *args)
|
26
25
|
clear_cache_for(*urls_for(group, *args))
|
27
26
|
end
|
28
|
-
|
27
|
+
|
29
28
|
def urls_for(group, *args)
|
30
29
|
args.map! { |arg| arg.to_param }
|
31
30
|
urls_by(group).map { |options| options[:url] % args }
|
32
31
|
end
|
33
|
-
|
32
|
+
|
34
33
|
def to_vcl_conditions(urls = store)
|
35
34
|
urls.map { |opt| %Q[req.url ~ "#{(opt[:url] % opt[:args])}"] }.join(" || ")
|
36
35
|
end
|
37
|
-
|
36
|
+
|
38
37
|
def to_vcl_override_ttl_urls
|
39
38
|
urls_grouped_by_expires.map do |expires_in, list|
|
40
39
|
<<-CODE.gsub(/^[ \t]{4}*/, '')
|
@@ -62,15 +61,15 @@ module Lacquer
|
|
62
61
|
}
|
63
62
|
CODE
|
64
63
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
68
67
|
def urls_grouped_by_expires
|
69
68
|
store.group_by { |opt| opt[:expires_in] }.select { |expires_in, list| expires_in }
|
70
69
|
end
|
71
|
-
|
70
|
+
|
72
71
|
def urls_by(group)
|
73
72
|
store.select { |opt| opt[:group] == group }
|
74
73
|
end
|
75
|
-
end
|
74
|
+
end
|
76
75
|
end
|
data/lib/lacquer/cache_utils.rb
CHANGED
@@ -1,47 +1,47 @@
|
|
1
|
-
module Lacquer
|
2
|
-
class Configuration
|
3
|
-
OPTIONS = []
|
4
|
-
|
5
|
-
# Enable cache
|
6
|
-
attr_accessor :enable_cache
|
7
|
-
|
8
|
-
# Varnish servers
|
9
|
-
attr_accessor :varnish_servers
|
10
|
-
|
11
|
-
# Application default ttl
|
12
|
-
attr_accessor :default_ttl
|
13
|
-
|
14
|
-
# Number of retries before failing
|
15
|
-
attr_accessor :retries
|
16
|
-
|
17
|
-
# Job backend
|
18
|
-
attr_accessor :job_backend
|
19
|
-
|
20
|
-
# Error handler
|
21
|
-
attr_accessor :command_error_handler
|
22
|
-
|
23
|
-
# Purge Command
|
24
|
-
attr_accessor :purge_command
|
25
|
-
|
26
|
-
# Pass Command (in vcl_fetch)
|
27
|
-
attr_accessor :pass_command
|
28
|
-
|
29
|
-
def initialize
|
30
|
-
@enable_cache = true
|
31
|
-
@varnish_servers = []
|
32
|
-
@default_ttl = 0
|
33
|
-
@job_backend = :none
|
34
|
-
@retries = 5
|
35
|
-
@command_error_handler = nil
|
36
|
-
@purge_command = "url.purge"
|
37
|
-
@pass_command = "pass"
|
38
|
-
end
|
39
|
-
|
40
|
-
# Returns a hash of all configurable options
|
41
|
-
def to_hash
|
42
|
-
OPTIONS.inject({}) do |hash, option|
|
43
|
-
hash.merge(option.to_sym => send(option))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
1
|
+
module Lacquer
|
2
|
+
class Configuration
|
3
|
+
OPTIONS = []
|
4
|
+
|
5
|
+
# Enable cache
|
6
|
+
attr_accessor :enable_cache
|
7
|
+
|
8
|
+
# Varnish servers
|
9
|
+
attr_accessor :varnish_servers
|
10
|
+
|
11
|
+
# Application default ttl
|
12
|
+
attr_accessor :default_ttl
|
13
|
+
|
14
|
+
# Number of retries before failing
|
15
|
+
attr_accessor :retries
|
16
|
+
|
17
|
+
# Job backend
|
18
|
+
attr_accessor :job_backend
|
19
|
+
|
20
|
+
# Error handler
|
21
|
+
attr_accessor :command_error_handler
|
22
|
+
|
23
|
+
# Purge Command
|
24
|
+
attr_accessor :purge_command
|
25
|
+
|
26
|
+
# Pass Command (in vcl_fetch)
|
27
|
+
attr_accessor :pass_command
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@enable_cache = true
|
31
|
+
@varnish_servers = []
|
32
|
+
@default_ttl = 0
|
33
|
+
@job_backend = :none
|
34
|
+
@retries = 5
|
35
|
+
@command_error_handler = nil
|
36
|
+
@purge_command = "url.purge"
|
37
|
+
@pass_command = "pass"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a hash of all configurable options
|
41
|
+
def to_hash
|
42
|
+
OPTIONS.inject({}) do |hash, option|
|
43
|
+
hash.merge(option.to_sym => send(option))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/lacquer/recipes.rb
CHANGED
@@ -18,32 +18,32 @@ Capistrano::Configuration.instance.load do
|
|
18
18
|
def rails_env
|
19
19
|
fetch(:rails_env, false) ? "RAILS_ENV=#{fetch(:rails_env)}" : ''
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def rake
|
23
23
|
fetch(:rake, 'rake')
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def roles
|
27
27
|
fetch(:varnishd_role, :varnish)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
desc "Link varnishd.yml from shared/config to app/config"
|
31
31
|
task :link_varnishd_yml, :roles => lambda { roles } do
|
32
32
|
run "cd #{release_path} && ln -nfs #{shared_path}/config/varnishd.yml #{release_path}/config/varnishd.yml"
|
33
33
|
end
|
34
34
|
after 'deploy:update_code', 'varnishd:link_varnishd_yml'
|
35
|
-
|
35
|
+
|
36
36
|
desc "Link varnish.vcl from shared/config to app/config"
|
37
37
|
task :link_varnish_vcl, :roles => lambda { roles } do
|
38
38
|
run "cd #{release_path} && ln -nfs #{shared_path}/config/varnish.vcl #{release_path}/config/varnish.vcl"
|
39
39
|
end
|
40
40
|
after 'deploy:update_code', 'varnishd:link_varnishd_vcl'
|
41
|
-
|
41
|
+
|
42
42
|
desc "Purge ALL urls from Varnish"
|
43
43
|
task :global_purge, :roles => lambda { roles } do
|
44
44
|
run "cd #{current_path};#{rails_env} #{rake} varnishd:global_purge"
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
desc "Stop the varnishd process"
|
48
48
|
task :stop, :roles => lambda { roles } do
|
49
49
|
run "cd #{current_path};#{rails_env} #{rake} varnishd:stop"
|
@@ -59,4 +59,4 @@ Capistrano::Configuration.instance.load do
|
|
59
59
|
run "cd #{current_path};#{rails_env} #{rake} varnishd:restart"
|
60
60
|
end
|
61
61
|
end
|
62
|
-
end
|
62
|
+
end
|
data/lib/lacquer/tasks.rb
CHANGED
@@ -4,12 +4,12 @@ namespace :lacquer do
|
|
4
4
|
task :start => :environment do
|
5
5
|
Lacquer::Varnishd.new.start
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
desc "Stop varnishd daemon using Lacquer's settings"
|
9
9
|
task :stop => :environment do
|
10
10
|
Lacquer::Varnishd.new.stop
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
desc "Running status of varnishd daemon using Lacquer's settings"
|
14
14
|
task :status => :environment do
|
15
15
|
if Lacquer::Varnishd.new.running?
|
@@ -18,7 +18,7 @@ namespace :lacquer do
|
|
18
18
|
puts "Varnishd is not running"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
desc "Restart varnishd daemon using Lacquer's settings"
|
23
23
|
task :restart => :environment do
|
24
24
|
varnishd = Lacquer::Varnishd.new
|
@@ -28,7 +28,7 @@ namespace :lacquer do
|
|
28
28
|
end
|
29
29
|
varnishd.start
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
desc "Purge ALL urls from Varnish"
|
33
33
|
task :global_purge => :environment do
|
34
34
|
Lacquer::Varnish.new.purge('.*')
|
data/lib/lacquer/varnish.rb
CHANGED
@@ -14,12 +14,15 @@ module Lacquer
|
|
14
14
|
# Sends the command 'url.purge *path*'
|
15
15
|
def purge(*paths)
|
16
16
|
paths.all? do |path|
|
17
|
-
|
18
|
-
|
17
|
+
ActiveSupport::Notifications.instrument('purge.lacquer', path: path) do |payload|
|
18
|
+
send_command(Lacquer.configuration.purge_command + " " + path.gsub('\\', '\\\\\\')).all? do |result|
|
19
|
+
payload[:result] = result
|
20
|
+
result =~ /200/
|
21
|
+
end
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
22
|
-
|
25
|
+
|
23
26
|
# Sends commands over telnet to varnish servers listed in the config.
|
24
27
|
def send_command(command)
|
25
28
|
Lacquer.configuration.varnish_servers.collect do |server|
|
@@ -31,7 +34,7 @@ module Lacquer
|
|
31
34
|
'Host' => server[:host],
|
32
35
|
'Port' => server[:port],
|
33
36
|
'Timeout' => server[:timeout] || 5)
|
34
|
-
|
37
|
+
|
35
38
|
if(server[:secret])
|
36
39
|
connection.waitfor("Match" => /^107/) do |authentication_request|
|
37
40
|
matchdata = /^107 \d{2}\s*(.{32}).*$/m.match(authentication_request) # Might be a bit ugly regex, but it works great!
|
@@ -39,7 +42,7 @@ module Lacquer
|
|
39
42
|
if(salt.empty?)
|
40
43
|
raise VarnishError, "Bad authentication request"
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
digest = OpenSSL::Digest::Digest.new('sha256')
|
44
47
|
digest << salt
|
45
48
|
digest << "\n"
|
@@ -47,7 +50,7 @@ module Lacquer
|
|
47
50
|
digest << "\n"
|
48
51
|
digest << salt
|
49
52
|
digest << "\n"
|
50
|
-
|
53
|
+
|
51
54
|
connection.cmd("String" => "auth #{digest.to_s}", "Match" => /\d{3}/) do |auth_response|
|
52
55
|
if(!(/^200/ =~ auth_response))
|
53
56
|
raise AuthenticationError, "Could not authenticate"
|
@@ -55,7 +58,7 @@ module Lacquer
|
|
55
58
|
end
|
56
59
|
end
|
57
60
|
end
|
58
|
-
|
61
|
+
|
59
62
|
connection.cmd('String' => command, 'Match' => /\n\n/) {|r| response = r.split("\n").first.strip}
|
60
63
|
connection.close if connection.respond_to?(:close)
|
61
64
|
rescue Exception => e
|
data/lib/lacquer/varnishd.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Lacquer
|
2
2
|
class Varnishd
|
3
3
|
attr_accessor :listen, :telnet, :sbin_path, :storage, :working_dir, :user, :backend, :params
|
4
|
-
|
4
|
+
|
5
5
|
cattr_accessor :started_check_delay, :vcl_script_filename
|
6
6
|
self.started_check_delay = 1
|
7
7
|
self.vcl_script_filename = 'config/varnish.vcl'
|
8
|
-
|
8
|
+
|
9
9
|
def self.root_path
|
10
10
|
Rails.root
|
11
11
|
end
|
@@ -13,26 +13,26 @@ module Lacquer
|
|
13
13
|
def self.env
|
14
14
|
Rails.env
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def self.config_file
|
18
18
|
root_path.join('config/varnishd.yml')
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def self.config
|
22
22
|
YAML.load(File.read(config_file))[env].stringify_keys
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def initialize(settings = self.class.config)
|
26
26
|
self.listen, self.telnet, self.backend, self.sbin_path, self.storage, self.working_dir, self.user, self.params =
|
27
27
|
settings.values_at("listen", "telnet", "backend", "sbin_path", "storage", "working_dir", "user", "params")
|
28
28
|
end
|
29
|
-
|
30
|
-
def render_vcl
|
29
|
+
|
30
|
+
def render_vcl
|
31
31
|
require 'erubis'
|
32
32
|
eruby = Erubis::Eruby.new(erb_vcl_script_filename.read)
|
33
33
|
eruby.result(binding)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def generate_vcl
|
37
37
|
if erb_vcl_script_filename.exist?
|
38
38
|
log "#{erb_vcl_script_filename} found rendering to #{vcl_script_filename}"
|
@@ -41,7 +41,7 @@ module Lacquer
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def start
|
46
46
|
if running?
|
47
47
|
log("Already running")
|
@@ -52,26 +52,26 @@ module Lacquer
|
|
52
52
|
sleep(self.class.started_check_delay)
|
53
53
|
log("Failed to start varnishd daemon") unless running?
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def stop
|
57
57
|
if running?
|
58
58
|
execute("kill #{pid}")
|
59
59
|
pid_file.delete
|
60
60
|
else
|
61
61
|
log("pid file not found or varnishd not running")
|
62
|
-
end
|
62
|
+
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def running?
|
66
66
|
!!pid && !!Process.kill(0, pid.to_i)
|
67
67
|
rescue
|
68
68
|
false
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def args
|
72
72
|
options.map { |k, v| "#{k} #{v}" }.join(" ")
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
def params_args
|
76
76
|
params.map { |k, v| "-p #{k}=#{v}" }.join(" ")
|
77
77
|
end
|
@@ -87,38 +87,38 @@ module Lacquer
|
|
87
87
|
opt["-f"] = vcl_script_filename
|
88
88
|
opt
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def params
|
92
92
|
@params || {}
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
protected
|
96
|
-
|
96
|
+
|
97
97
|
def varnishd_cmd
|
98
98
|
Pathname.new(sbin_path).join('varnishd')
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
def pid_file
|
102
102
|
self.class.root_path.join("log/varnishd.#{self.class.env}.pid")
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
def vcl_script_filename
|
106
106
|
self.class.root_path.join(self.class.vcl_script_filename)
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
109
|
def erb_vcl_script_filename
|
110
110
|
vcl_script_filename.sub_ext('.vcl.erb')
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
def log(message)
|
114
114
|
puts "** [#{self.class.name}] #{message}"
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
def execute(cmd)
|
118
118
|
log(cmd)
|
119
119
|
`#{cmd}`
|
120
120
|
end
|
121
|
-
|
121
|
+
|
122
122
|
def pid
|
123
123
|
if pid_file.exist?
|
124
124
|
pid_file.read
|
@@ -126,6 +126,5 @@ module Lacquer
|
|
126
126
|
nil
|
127
127
|
end
|
128
128
|
end
|
129
|
-
|
130
129
|
end
|
131
|
-
end
|
130
|
+
end
|
data/lib/lacquer/version.rb
CHANGED
data/spec/config/varnish.vcl
CHANGED
@@ -11,9 +11,9 @@ describe Lacquer::CacheControl do
|
|
11
11
|
cache_control.store.first[:args].should == ["[0-9]+"]
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
describe "#urls_for" do
|
16
|
-
it "returns urls to expire for object" do
|
16
|
+
it "returns urls to expire for object" do
|
17
17
|
cache_control = described_class.new
|
18
18
|
cache_control.register :class_section, :url => "^/sv/class_sections/%s.*$", :args => "[0-9]+"
|
19
19
|
cache_control.urls_for(:class_section, mock("ClassSection", :to_param => 1)).should == ["^/sv/class_sections/1.*$"]
|
@@ -25,7 +25,7 @@ describe Lacquer::CacheControl do
|
|
25
25
|
cache_control = described_class.new
|
26
26
|
cache_control.register :class_section, :url => "^/sv/class_sections/%s.*$", :args => "[0-9]+"
|
27
27
|
cache_control.register :class_section, :url => "^/sv/info_screens/%s.*$", :args => "[0-9]+"
|
28
|
-
|
28
|
+
|
29
29
|
conditions = cache_control.to_vcl_conditions
|
30
30
|
conditions.should include("req.url ~ \"^/sv/class_sections/[0-9]+.*$\"")
|
31
31
|
conditions.should include("||")
|
@@ -47,7 +47,7 @@ describe Lacquer::CacheControl do
|
|
47
47
|
pass_urls.should include('if(req.url ~ "*.mp4$")')
|
48
48
|
pass_urls.should include('return(pipe)')
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "returns vcl for override ttl on beresp" do
|
52
52
|
cache_control = described_class.new
|
53
53
|
cache_control.register :class_section, :url => "^/sv/competitions$", :expires_in => "7d"
|
@@ -56,13 +56,13 @@ describe Lacquer::CacheControl do
|
|
56
56
|
override_ttl.should include('unset beresp.http.Set-Cookie')
|
57
57
|
override_ttl.should include('return(deliver)')
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
it "group by expires in" do
|
61
61
|
cache_control = described_class.new
|
62
62
|
cache_control.register :class_section, :url => "^/sv/competitions$", :expires_in => "1d"
|
63
63
|
cache_control.register :class_section, :url => "^/sv/competitions/%s$", :args => "[0-9]+", :expires_in => "2d"
|
64
64
|
cache_control.register :class_section, :url => "^/sv/competitions/%s/info_screen$", :args => "[0-9]+"
|
65
|
-
|
65
|
+
|
66
66
|
override_ttl = cache_control.to_vcl_override_ttl_urls
|
67
67
|
override_ttl.should include('if(req.url ~ "^/sv/competitions$")')
|
68
68
|
override_ttl.should include('set beresp.ttl = 1d')
|
@@ -3,6 +3,8 @@ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
|
3
3
|
describe "DelayedJobJob" do
|
4
4
|
describe "perform" do
|
5
5
|
it "should purge the parameter" do
|
6
|
+
require File.expand_path('lib/lacquer/delayed_job_job')
|
7
|
+
|
6
8
|
@varnish_mock = mock('varnish')
|
7
9
|
Lacquer::Varnish.stub!(:new).and_return(@varnish_mock)
|
8
10
|
|
@@ -3,6 +3,8 @@ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
|
3
3
|
describe "ResqueJob" do
|
4
4
|
describe "perform" do
|
5
5
|
it "should purge the parameter" do
|
6
|
+
require File.expand_path('lib/lacquer/resque_job')
|
7
|
+
|
6
8
|
@varnish_mock = mock('varnish')
|
7
9
|
Lacquer::Varnish.stub!(:new).and_return(@varnish_mock)
|
8
10
|
|
@@ -5,7 +5,7 @@ describe "Varnish" do
|
|
5
5
|
@telnet_mock = mock('Net::Telnet')
|
6
6
|
Net::Telnet.stub!(:new).and_return(@telnet_mock)
|
7
7
|
@telnet_mock.stub!(:close)
|
8
|
-
@telnet_mock.stub!(:cmd)
|
8
|
+
@telnet_mock.stub!(:cmd)
|
9
9
|
@telnet_mock.stub!(:puts)
|
10
10
|
@telnet_mock.stub!(:waitfor)
|
11
11
|
Lacquer.configuration.retries.should == 5
|
@@ -33,7 +33,7 @@ describe "Varnish" do
|
|
33
33
|
Lacquer::Varnish.new.purge('/')
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
describe "when using authentication" do
|
38
38
|
after(:each) do
|
39
39
|
Lacquer.configuration.varnish_servers.first[:secret] = nil
|
@@ -47,7 +47,7 @@ describe "Varnish" do
|
|
47
47
|
@telnet_mock.stub!(:waitfor).with("Match" => /^107/).and_yield('107 59 \nhaalpffwlcvblmdrinpnjwigwsbiiigq\n\nAuthentication required.\n\n')
|
48
48
|
@telnet_mock.stub!(:cmd).with("String" => "auth d218942acc92753db0c9fedddb32cde6158de28e903356caed1808cf0e23a15a", "Match" => /\d{3}/).and_yield('200')
|
49
49
|
@telnet_mock.stub!(:cmd).with("String" => "url.purge /", "Match" => /\n\n/).and_yield('200')
|
50
|
-
|
50
|
+
|
51
51
|
lambda {
|
52
52
|
Lacquer::Varnish.new.purge('/')
|
53
53
|
}.should_not raise_error
|
@@ -89,7 +89,7 @@ describe "Varnish" do
|
|
89
89
|
}.should_not raise_error(Lacquer::VarnishError)
|
90
90
|
end
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
end
|
94
94
|
|
95
95
|
describe "when sending a stats command" do
|
@@ -1,14 +1,13 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
|
2
2
|
|
3
3
|
describe "Varnishd" do
|
4
|
-
|
5
4
|
before do
|
6
5
|
spec_root = Pathname.new(__FILE__).dirname.join('..').expand_path
|
7
6
|
Lacquer::Varnishd.stub!(:started_check_delay).and_return(0)
|
8
7
|
Lacquer::Varnishd.stub!(:env).and_return('test')
|
9
8
|
Lacquer::Varnishd.stub!(:root_path).and_return(spec_root)
|
10
9
|
end
|
11
|
-
|
10
|
+
|
12
11
|
def executes_with(regexp)
|
13
12
|
new_method = Lacquer::Varnishd.method(:new)
|
14
13
|
Lacquer::Varnishd.stub!(:new).and_return do |*args|
|
@@ -18,11 +17,11 @@ describe "Varnishd" do
|
|
18
17
|
varnishd
|
19
18
|
end
|
20
19
|
end
|
21
|
-
|
20
|
+
|
22
21
|
it "passes settings in the initailizer" do
|
23
22
|
Lacquer::Varnishd.new("listen" => ":80").listen.should == ":80"
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
it "loads settings from varnish_config" do
|
27
26
|
Lacquer::Varnishd.config.should have_key("listen")
|
28
27
|
Lacquer::Varnishd.config.should have_key("telnet")
|
@@ -30,42 +29,41 @@ describe "Varnishd" do
|
|
30
29
|
Lacquer::Varnishd.config.should have_key("storage")
|
31
30
|
Lacquer::Varnishd.config["params"].should have_key('overflow_max')
|
32
31
|
end
|
33
|
-
|
32
|
+
|
34
33
|
it "returns full path to varnishd" do
|
35
34
|
executes_with(%r[/opt/varnishd/sbin/varnishd])
|
36
35
|
Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin").start
|
37
36
|
end
|
38
|
-
|
37
|
+
|
39
38
|
it "returns pid file" do
|
40
39
|
executes_with(/log\/varnishd.test.pid/)
|
41
40
|
Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin").start
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
it "returns params as string" do
|
45
44
|
Lacquer::Varnishd.new("params" => { "max" => 2000, "add" => 2 }).params_args.should == "-p max=2000 -p add=2"
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
it "returns listen arg as string" do
|
49
48
|
Lacquer::Varnishd.new("listen" => ":80").args.should include("-a :80")
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
it "starts varnishd with args and params" do
|
53
52
|
executes_with(%r[/opt/varnishd/sbin.*-P.*log/varnishd.test.pid])
|
54
53
|
Lacquer::Varnishd.new("sbin_path" => "/opt/varnishd/sbin", "params" => { "overflow_max" => 2000 }).start
|
55
54
|
end
|
56
|
-
|
55
|
+
|
57
56
|
it "raises error if vcl_script_file is not present" do
|
58
57
|
Lacquer::Varnishd.stub!(:vcl_script_filename).and_return("config/file_not_found.vcl")
|
59
58
|
expect {
|
60
59
|
Lacquer::Varnishd.new.vcl_script_path
|
61
60
|
}.to raise_error
|
62
61
|
end
|
63
|
-
|
62
|
+
|
64
63
|
it "renders vcl file when erb is present" do
|
65
64
|
Lacquer::Varnishd.stub!(:vcl_script_filename).and_return("config/generate.vcl")
|
66
65
|
result = Lacquer::Varnishd.new.render_vcl
|
67
66
|
result.should include('.host = "0.0.0.0"')
|
68
67
|
result.should include('.port = "3000"')
|
69
68
|
end
|
70
|
-
|
71
|
-
end
|
69
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lacquer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,11 +12,11 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-
|
15
|
+
date: 2012-05-02 00:00:00.000000000Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: activesupport
|
19
|
-
requirement: &
|
19
|
+
requirement: &70253394615980 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - ! '>='
|
@@ -24,10 +24,10 @@ dependencies:
|
|
24
24
|
version: 2.3.10
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
|
-
version_requirements: *
|
27
|
+
version_requirements: *70253394615980
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: i18n
|
30
|
-
requirement: &
|
30
|
+
requirement: &70253394614860 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - ~>
|
@@ -35,10 +35,10 @@ dependencies:
|
|
35
35
|
version: '0.4'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
|
-
version_requirements: *
|
38
|
+
version_requirements: *70253394614860
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: erubis
|
41
|
-
requirement: &
|
41
|
+
requirement: &70253394613740 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - ! '>='
|
@@ -46,10 +46,10 @@ dependencies:
|
|
46
46
|
version: '0'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
|
-
version_requirements: *
|
49
|
+
version_requirements: *70253394613740
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
51
|
name: rake
|
52
|
-
requirement: &
|
52
|
+
requirement: &70253394612340 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - ! '>='
|
@@ -57,10 +57,10 @@ dependencies:
|
|
57
57
|
version: '0'
|
58
58
|
type: :development
|
59
59
|
prerelease: false
|
60
|
-
version_requirements: *
|
60
|
+
version_requirements: *70253394612340
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: rspec
|
63
|
-
requirement: &
|
63
|
+
requirement: &70253394610860 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
@@ -68,10 +68,10 @@ dependencies:
|
|
68
68
|
version: '2.5'
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
|
-
version_requirements: *
|
71
|
+
version_requirements: *70253394610860
|
72
72
|
- !ruby/object:Gem::Dependency
|
73
73
|
name: yard
|
74
|
-
requirement: &
|
74
|
+
requirement: &70253394610320 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ! '>='
|
@@ -79,7 +79,7 @@ dependencies:
|
|
79
79
|
version: '0'
|
80
80
|
type: :development
|
81
81
|
prerelease: false
|
82
|
-
version_requirements: *
|
82
|
+
version_requirements: *70253394610320
|
83
83
|
description: Rails drop in for Varnish support.
|
84
84
|
email: russ@bashme.org
|
85
85
|
executables: []
|