posterous-lacquer 0.2.3

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Russ Smith
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,72 @@
1
+ = lacquer
2
+
3
+ Rails drop in for Varnish support.
4
+
5
+ == Install
6
+ Basic installation
7
+
8
+ rails generate lacquer install
9
+
10
+ config/initializers/lacquer.rb
11
+
12
+ Lacquer.configure do |config|
13
+ # Globally enable/disable cache
14
+ config.enable_cache = true
15
+
16
+ # Unless overridden in a controller or action, the default will be used
17
+ config.default_ttl = 1.week
18
+
19
+ # Can be :none, :delayed_job, :resque
20
+ config.job_backend = :none
21
+
22
+ # Array of Varnish servers to manage
23
+ config.varnish_servers << {
24
+ :host => '0.0.0.0', :port => 6082
25
+ }
26
+
27
+ # Number of retries
28
+ config.retries = 5
29
+
30
+ # config handler (optional, if you use Hoptoad or another error tracking service)
31
+ config.command_error_handler = lambda {|s| HoptoadNotifier.notify(s) }
32
+ end
33
+
34
+ app/controllers/application_controller.rb
35
+
36
+ class ApplicationController < ActionController::Base
37
+ include Lacquer::CacheUtils
38
+ end
39
+
40
+ == Usage
41
+ To set a custom ttl for a controller:
42
+
43
+ before_filter { |controller| controller.set_cache_ttl(15.minutes) }
44
+
45
+ Clearing the cache:
46
+
47
+ class Posts < ApplicationController
48
+ after_filter :clear_cache, :only => [ :create, :update, :destroy ]
49
+
50
+ private
51
+
52
+ def clear_cache
53
+ clear_cache_for(
54
+ root_path,
55
+ posts_path,
56
+ post_path(@post))
57
+ end
58
+ end
59
+
60
+ == Note on Patches/Pull Requests
61
+
62
+ * Fork the project.
63
+ * Make your feature addition or bug fix.
64
+ * Add tests for it. This is important so I don't break it in a
65
+ future version unintentionally.
66
+ * Commit, do not mess with rakefile, version, or history.
67
+ (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)
68
+ * Send me a pull request. Bonus points for topic branches.
69
+
70
+ == Copyright
71
+
72
+ Copyright (c) 2010 Russ Smith. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "posterous-lacquer"
8
+ gem.summary = %Q{Rails drop in for Varnish support.}
9
+ gem.description = %Q{Rails drop in for Varnish support.}
10
+ gem.email = "garry@posterous.com"
11
+ gem.homepage = "http://github.com/russ/lacquer"
12
+ gem.authors = ["Garry Tan", "Russ Smith"]
13
+ gem.add_development_dependency "rspec", ">= 1.3.0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "testing #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.3
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'lib', 'lacquer')
data/lacquer.gemspec ADDED
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{lacquer}
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Russ Smith"]
12
+ s.date = %q{2010-06-14}
13
+ s.description = %q{Rails drop in for Varnish support.}
14
+ s.email = %q{russ@bashme.org}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "init.rb",
27
+ "lacquer.gemspec",
28
+ "lib/generators/USAGE",
29
+ "lib/generators/lacquer_generator.rb",
30
+ "lib/generators/templates/initializer.rb",
31
+ "lib/generators/templates/varnish.sample.vcl",
32
+ "lib/lacquer.rb",
33
+ "lib/lacquer/cache_utils.rb",
34
+ "lib/lacquer/configuration.rb",
35
+ "lib/lacquer/delayed_job_job.rb",
36
+ "lib/lacquer/resque_job.rb",
37
+ "lib/lacquer/varnish.rb",
38
+ "rails/init.rb",
39
+ "test.rb",
40
+ "test/helper.rb",
41
+ "test/test_cache_utils.rb",
42
+ "test/test_varnish_interface.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/russ/lacquer}
45
+ s.rdoc_options = ["--charset=UTF-8"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.3.6}
48
+ s.summary = %q{Rails drop in for Varnish support.}
49
+ s.test_files = [
50
+ "test/helper.rb",
51
+ "test/test_cache_utils.rb",
52
+ "test/test_varnish_interface.rb"
53
+ ]
54
+
55
+ if s.respond_to? :specification_version then
56
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
57
+ s.specification_version = 3
58
+
59
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
60
+ else
61
+ end
62
+ else
63
+ end
64
+ end
65
+
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Installs Lacquer into your Rails application.
3
+
4
+ Example:
5
+ rails generate lacquer install
@@ -0,0 +1,10 @@
1
+ require 'rails/generators'
2
+
3
+ class LacquerGenerator < Rails::Generators::NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def install
7
+ copy_file('varnish.sample.vcl', 'config/varnish.sample.vcl')
8
+ copy_file('initializer.rb', 'config/initializers/lacquer.rb')
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ Lacquer.configure do |config|
2
+ # Globally enable/disable cache
3
+ config.enable_cache = true
4
+
5
+ # Unless overridden in a controller or action, the default will be used
6
+ config.default_ttl = 1.week
7
+
8
+ # Can be :none, :delayed_job, :resque
9
+ config.job_backend = :none
10
+
11
+ # Array of Varnish servers to manage
12
+ config.varnish_servers << {
13
+ :host => '0.0.0.0', :port => 6082
14
+ }
15
+ end
@@ -0,0 +1,117 @@
1
+ backend default {
2
+ .host = "0.0.0.0";
3
+ .port = "10000";
4
+ }
5
+
6
+
7
+ #
8
+ # Handling of requests that are received from clients.
9
+ # First decide whether or not to lookup data in the cache.
10
+ #
11
+ sub vcl_recv {
12
+ # Pipe requests that are non-RFC2616 or CONNECT which is weird.
13
+ if (req.request != "GET" &&
14
+ req.request != "HEAD" &&
15
+ req.request != "PUT" &&
16
+ req.request != "POST" &&
17
+ req.request != "TRACE" &&
18
+ req.request != "OPTIONS" &&
19
+ req.request != "DELETE") {
20
+ pipe;
21
+ }
22
+
23
+ # Pass requests that are not GET or HEAD
24
+ if (req.request != "GET" && req.request != "HEAD") {
25
+ pass;
26
+ }
27
+
28
+ # Pass requests that we know we aren't caching
29
+ if (req.url ~ "^/admin") {
30
+ pass;
31
+ }
32
+
33
+ #
34
+ # Everything below here should be cached
35
+ #
36
+
37
+ # Handle compression correctly. Varnish treats headers literally, not
38
+ # semantically. So it is very well possible that there are cache misses
39
+ # because the headers sent by different browsers aren't the same.
40
+ # @see: http://varnish.projects.linpro.no/wiki/FAQ/Compression
41
+ if (req.http.Accept-Encoding) {
42
+ if (req.http.Accept-Encoding ~ "gzip") {
43
+ # if the browser supports it, we'll use gzip
44
+ set req.http.Accept-Encoding = "gzip";
45
+ } elsif (req.http.Accept-Encoding ~ "deflate") {
46
+ # next, try deflate if it is supported
47
+ set req.http.Accept-Encoding = "deflate";
48
+ } else {
49
+ # unknown algorithm. Probably junk, remove it
50
+ remove req.http.Accept-Encoding;
51
+ }
52
+ }
53
+
54
+ # Clear cookie and authorization headers, set grace time, lookup in the cache
55
+ unset req.http.Cookie;
56
+ unset req.http.Authorization;
57
+ set req.grace = 30s;
58
+ lookup;
59
+ }
60
+
61
+ #
62
+ # Called when entering pipe mode
63
+ #
64
+ sub vcl_pipe {
65
+ # If we don't set the Connection: close header, any following
66
+ # requests from the client will also be piped through and
67
+ # left untouched by varnish. We don't want that.
68
+ set req.http.connection = "close";
69
+ pipe;
70
+ }
71
+
72
+ #
73
+ # Called when the requested object has been retrieved from the
74
+ # backend, or the request to the backend has failed
75
+ #
76
+ sub vcl_fetch {
77
+ # Do not cache the object if the backend application does not want us to.
78
+ if (obj.http.Cache-Control ~ "(no-cache|no-store|private|must-revalidate)") {
79
+ pass;
80
+ }
81
+
82
+ # Do not cache the object if the status is not in the 200s
83
+ if (obj.status >= 300) {
84
+ # Remove the Set-Cookie header
85
+ remove obj.http.Set-Cookie;
86
+ pass;
87
+ }
88
+
89
+ #
90
+ # Everything below here should be cached
91
+ #
92
+
93
+ # Remove the Set-Cookie header
94
+ remove obj.http.Set-Cookie;
95
+
96
+ # Set the grace time
97
+ set obj.grace = 30s;
98
+
99
+ # Deliver the object
100
+ deliver;
101
+ }
102
+
103
+ #
104
+ # Called before the response is sent back to the client
105
+ #
106
+ sub vcl_deliver {
107
+ # Force browsers and intermediary caches to always check back with us
108
+ set resp.http.Cache-Control = "private, max-age=0, must-revalidate";
109
+ set resp.http.Pragma = "no-cache";
110
+
111
+ # Add a header to indicate a cache HIT/MISS
112
+ if (obj.hits > 0) {
113
+ set resp.http.X-Cache = "HIT";
114
+ } else {
115
+ set resp.http.X-Cache = "MISS";
116
+ }
117
+ }
@@ -0,0 +1,50 @@
1
+ module Lacquer
2
+ module CacheUtils
3
+ def self.included(base)
4
+ base.class_eval do
5
+ attr_reader :cache_ttl
6
+
7
+ before_filter :set_default_cache_ttl
8
+ after_filter :send_cache_control_headers
9
+ end
10
+ end
11
+
12
+ # Instance variable for the action ttl.
13
+ def set_cache_ttl(ttl)
14
+ @cache_ttl = ttl
15
+ end
16
+
17
+ # Called as a before filter to set default ttl
18
+ # for the entire application.
19
+ def set_default_cache_ttl
20
+ set_cache_ttl(Lacquer.configuration.default_ttl)
21
+ end
22
+
23
+ # Sends url.purge command to varnish to clear cache.
24
+ #
25
+ # clear_cache_for(root_path, blog_posts_path, '/other/content/*')
26
+ def clear_cache_for(*paths)
27
+ paths.each do |path|
28
+ case Lacquer.configuration.job_backend
29
+ when :delayed_job
30
+ require 'lacquer/delayed_job_job'
31
+ Delayed::Job.enqueue(Lacquer::DelayedJobJob.new('url.purge ' << path))
32
+ when :resque
33
+ require 'lacquer/resque_job'
34
+ Resque.enqueue(Lacquer::ResqueJob, 'url.purge ' << path)
35
+ when :none
36
+ Varnish.new.purge('url.purge ' << path)
37
+ end
38
+ end
39
+ end
40
+
41
+ # Sends cache control headers with page.
42
+ # These are the headers that varnish responds to
43
+ # to set cache properly.
44
+ def send_cache_control_headers
45
+ if Lacquer.configuration.enable_cache
46
+ expires_in(@cache_ttl, :public => true)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ module Lacquer
2
+ class Configuration
3
+ OPTIONS = [ :varnish_servers ]
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
+ # Application default ttl
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
+ def initialize
24
+ @enable_cache = true
25
+ @varnish_servers = []
26
+ @default_ttl = 1.week
27
+ @job_backend = :none
28
+ @retries = 5
29
+ @command_error_handler = nil
30
+ end
31
+
32
+ # Returns a hash of all configurable options
33
+ def to_hash
34
+ OPTIONS.inject({}) do |hash, option|
35
+ hash.merge(option.to_sym => send(option))
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ module Lacquer
2
+ class DelayedJobJob < Struct.new(:command)
3
+ def perform
4
+ Varnish.new.purge(command)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Lacquer
2
+ class ResqueJob
3
+ @queue = :lacquer
4
+
5
+ def self.perform(command)
6
+ VarnishInterface.new.purge(command)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,58 @@
1
+ module Lacquer
2
+ class Varnish
3
+ def stats
4
+ send_command('stats').collect do |stats|
5
+ stats = stats.split("\n")
6
+ stats.shift
7
+
8
+ stats = stats.collect do |stat|
9
+ stat = stat.strip.match(/(\d+)\s+(.+)$/)
10
+ { :key => stat[2], :value => stat[1] }
11
+ end
12
+ end
13
+ end
14
+
15
+ def purge(path)
16
+ send_command('url.purge ' << path).all? do |result|
17
+ result =~ /200/
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ # Sends commands over telnet to varnish servers listed in the config.
24
+ def send_command(command)
25
+ Lacquer.configuration.varnish_servers.collect do |server|
26
+ retries = 0
27
+ begin
28
+ retries += 1
29
+ response = []
30
+ connection = Net::Telnet.new(
31
+ 'Host' => server[:host],
32
+ 'Port' => server[:port],
33
+ 'Timeout' => server[:timeout] || 5)
34
+ connection.cmd(command) do |c|
35
+ response.push c.strip
36
+ c.strip
37
+ end
38
+ rescue Exception => e
39
+ if retries < Lacquer.configuration.retries
40
+ retry
41
+ else
42
+ if Lacquer.configuration.command_error_handler
43
+ Lacquer.configuration.command_error_handler.call({
44
+ :error_class => "Varnish Error, retried #{Lacquer.configuration.retries} times",
45
+ :error_message => "Error while trying to connect to #{server[:host]}:#{server[:port]}: #{e}",
46
+ :parameters => server,
47
+ :response => response.join("\n")})
48
+ else
49
+ raise VarnishError.new("Error while trying to connect to #{server[:host]}:#{server[:port]} #{e}")
50
+ end
51
+ end
52
+ ensure
53
+ connection.close rescue nil
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/lacquer.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'net/telnet'
3
+ require 'active_support/core_ext'
4
+
5
+ require 'lacquer/configuration'
6
+ require 'lacquer/cache_utils'
7
+ require 'lacquer/varnish'
8
+
9
+ module Lacquer
10
+ class VarnishError < Exception; end
11
+
12
+ class << self
13
+ attr_accessor :configuration
14
+
15
+ # Call this method to modify defaults in your initailizers.
16
+ #
17
+ # Lacquer.configure do |config|
18
+ # config.varnish_servers << { :host => '0.0.0.0', :port => 6082, :timeout => 5 }
19
+ # end
20
+ def configure
21
+ self.configuration ||= Configuration.new
22
+ yield(configuration)
23
+ end
24
+ end
25
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'lacquer'
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe "Lacquer" do
4
+ before(:each) do
5
+ @controller = ControllerClass.new
6
+ end
7
+
8
+ describe "talking to varnish" do
9
+ before(:each) do
10
+ @varnish_stub = mock('varnish')
11
+ Lacquer::Varnish.stub!(:new).and_return(@varnish_stub)
12
+ end
13
+
14
+ describe "when backend is :none" do
15
+ it "sends commands to varnish instantly" do
16
+ Lacquer.configuration.job_backend = :none
17
+
18
+ @varnish_stub.should_receive(:purge).twice
19
+ @controller.clear_cache_for('/', '/blog/posts')
20
+ end
21
+ end
22
+
23
+ describe "when backend is :delayed_job" do
24
+ it "sends commands to a delayed_job queue" do
25
+ Lacquer.configuration.job_backend = :delayed_job
26
+
27
+ Delayed::Job.should_receive(:enqueue).twice
28
+ @controller.clear_cache_for('/', '/blog/posts')
29
+ end
30
+ end
31
+
32
+ describe "when backend is :resque" do
33
+ it "sends commands to a resque queue" do
34
+ Lacquer.configuration.job_backend = :resque
35
+
36
+ Resque.should_receive(:enqueue).twice
37
+ @controller.clear_cache_for('/', '/blog/posts')
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "when cache is enabled" do
43
+ describe "when no custom ttl is set" do
44
+ it "should send cache control headers based on default ttl" do
45
+ Lacquer.configuration.enable_cache = true
46
+ Lacquer.configuration.default_ttl = 1.week
47
+
48
+ @controller.set_default_cache_ttl
49
+ @controller.should_receive(:expires_in).with(1.week, :public => true)
50
+ @controller.send_cache_control_headers
51
+ end
52
+ end
53
+
54
+ describe "when custom ttl is set" do
55
+ it "should send cache control headers based on custom set ttl" do
56
+ Lacquer.configuration.enable_cache = true
57
+
58
+ @controller.set_cache_ttl(10.week)
59
+ @controller.should_receive(:expires_in).with(10.week, :public => true)
60
+ @controller.send_cache_control_headers
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../spec_helper')
2
+
3
+ describe "Varnish" do
4
+ before(:each) do
5
+ @telnet_mock = mock('Net::Telnet')
6
+ Net::Telnet.stub!(:new).and_return(@telnet_mock)
7
+ @telnet_mock.stub!(:close)
8
+ @telnet_mock.stub!(:cmd)
9
+ Lacquer.configuration.retries.should == 5
10
+ end
11
+
12
+ describe "with any command" do
13
+ describe "when connection is unsuccessful" do
14
+ it "should raise a Lacquer::VarnishError" do
15
+ @telnet_mock.stub!(:cmd).and_raise(Timeout::Error)
16
+ lambda {
17
+ Lacquer::Varnish.new.purge('/')
18
+ }.should raise_error(Lacquer::VarnishError)
19
+ end
20
+
21
+ it "should retry on failure before erroring" do
22
+ @telnet_mock.stub!(:cmd).and_raise(Timeout::Error)
23
+ Net::Telnet.should_receive(:new).exactly(5).times
24
+ lambda {
25
+ Lacquer::Varnish.new.purge('/')
26
+ }.should raise_error(Lacquer::VarnishError)
27
+ end
28
+
29
+ it "should close the connection afterwards" do
30
+ @telnet_mock.should_receive(:close).exactly(1).times
31
+ Lacquer::Varnish.new.purge('/')
32
+ end
33
+ end
34
+
35
+ describe "when connection is unsuccessful and an error handler is set" do
36
+ before(:each) do
37
+ Lacquer.configuration.command_error_handler = mock("command_error_handler")
38
+ end
39
+ it "should call handler on error" do
40
+ @telnet_mock.stub!(:cmd).and_raise(Timeout::Error)
41
+ Lacquer.configuration.command_error_handler.should_receive(:call).exactly(1).times
42
+ lambda {
43
+ Lacquer::Varnish.new.purge('/')
44
+ }.should_not raise_error(Lacquer::VarnishError)
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "when sending a stats command" do
50
+ it "should return an array of stats" do
51
+ @telnet_mock.stub!(:cmd).and_yield("200 200\n1000 Connections")
52
+ stats = Lacquer::Varnish.new.stats
53
+ stats.size.should be(1)
54
+ end
55
+ end
56
+
57
+ describe "when sending a purge command" do
58
+ it "should return successfully" do
59
+ @telnet_mock.stub!(:cmd).and_yield('200')
60
+ Lacquer::Varnish.new.purge('/').should be(true)
61
+ end
62
+ end
63
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,29 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'lacquer'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+
8
+ class ControllerClass
9
+ def self.before_filter(arg); end
10
+ def self.after_filter(arg); end
11
+
12
+ include Lacquer::CacheUtils
13
+ end
14
+
15
+ module Delayed;
16
+ module Job; end
17
+ end
18
+
19
+ module Resque; end
20
+
21
+ Lacquer.configure do |config|
22
+ config.enable_cache = true
23
+ config.default_ttl = 1.week
24
+ config.job_backend = :none
25
+ config.varnish_servers << { :host => '0.0.0.0', :port => 6082 }
26
+ end
27
+
28
+ Spec::Runner.configure do |config|
29
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: posterous-lacquer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 17
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 3
10
+ version: 0.2.3
11
+ platform: ruby
12
+ authors:
13
+ - Garry Tan
14
+ - Russ Smith
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-09-02 00:00:00 -07:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rspec
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 27
31
+ segments:
32
+ - 1
33
+ - 3
34
+ - 0
35
+ version: 1.3.0
36
+ type: :development
37
+ version_requirements: *id001
38
+ description: Rails drop in for Varnish support.
39
+ email: garry@posterous.com
40
+ executables: []
41
+
42
+ extensions: []
43
+
44
+ extra_rdoc_files:
45
+ - LICENSE
46
+ - README.rdoc
47
+ files:
48
+ - .document
49
+ - .gitignore
50
+ - LICENSE
51
+ - README.rdoc
52
+ - Rakefile
53
+ - VERSION
54
+ - init.rb
55
+ - lacquer.gemspec
56
+ - lib/generators/USAGE
57
+ - lib/generators/lacquer_generator.rb
58
+ - lib/generators/templates/initializer.rb
59
+ - lib/generators/templates/varnish.sample.vcl
60
+ - lib/lacquer.rb
61
+ - lib/lacquer/cache_utils.rb
62
+ - lib/lacquer/configuration.rb
63
+ - lib/lacquer/delayed_job_job.rb
64
+ - lib/lacquer/resque_job.rb
65
+ - lib/lacquer/varnish.rb
66
+ - rails/init.rb
67
+ - spec/lacquer/cache_utils_spec.rb
68
+ - spec/lacquer/varnish_spec.rb
69
+ - spec/spec.opts
70
+ - spec/spec_helper.rb
71
+ has_rdoc: true
72
+ homepage: http://github.com/russ/lacquer
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options:
77
+ - --charset=UTF-8
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Rails drop in for Varnish support.
105
+ test_files:
106
+ - spec/lacquer/cache_utils_spec.rb
107
+ - spec/lacquer/varnish_spec.rb
108
+ - spec/spec_helper.rb