• Stars
    star
    209
  • Rank 188,325 (Top 4 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 14 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rails drop in for Varnish support.

http://travis-ci.org/russ/lacquer

Lacquer

Rails drop in for Varnish support.

Install

This gem requires ruby 1.9+

gem install lacquer  
rails generate lacquer:install

config/initializers/lacquer.rb

Lacquer.configure do |config|
  # Globally enable/disable cache
  config.enable_cache = true

  # Unless overridden in a controller or action, the default will be used
  config.default_ttl = 1.week

  # Can be :none, :delayed_job, :resque, :sidekiq
  config.job_backend = :none

  # Array of Varnish servers to manage
  config.varnish_servers << {
    :host => "0.0.0.0", :port => 6082 # if you have authentication enabled, add :secret => "your secret"
  }

  # Number of retries
  config.retries = 5

  # config handler (optional, if you use Hoptoad or another error tracking service)
  config.command_error_handler = lambda { |s| HoptoadNotifier.notify(s) }


  ### Varnish - 2.x  /  3.x  .. VCL-Changes
  ### https://www.varnish-cache.org/docs/trunk/installation/upgrade.html

  # => Purge Command  ( "url.purge" for Varnish 2.x .. "ban.url" for Varnish 3.x )
  # => purges are now called bans in Varnish 3.x .. purge() and purge_url() are now respectively ban() and ban_url()
  config.purge_command = "ban.url"

  # => VCL_Fetch Pass Command  ( "pass" for Varnish 2.x .. "hit_for_pass" for Varnish 3.x )
  # => pass in vcl_fetch renamed to hit_for_pass in Varnish 3.x
  config.pass_command = "pass"
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  include Lacquer::CacheUtils
end

config/varnishd.yml

development:
  listen: localhost:3001
  telnet: localhost:6082
  sbin_path: /usr/local/sbin # path to varnishd
  bin_path: /usr/local/bin   # path to varnishadm
  storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"

test:
  listen: localhost:3002
  telnet: localhost:6083
  sbin_path: /usr/local/sbin
  bin_path: /usr/local/bin
  storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"

production:
  listen: :80
  telnet: localhost:6082
  sbin_path: /usr/local/sbin
  bin_path: /usr/local/bin
  storage: "file,#{Rails.root}/log/varnishd.#{Rails.env}.cache,100MB"
  params:
    overflow_max: 2000          # for Varnish 2.x ... use "queue_max: 2000" for Varnish 3.x
    thread_pool_add_delay: 2
    thread_pools: 4             # <Number of cpu cores>
    thread_pool_min: 200        # <800/number of cpu cores>
    thread_pool_max: 4000

If only some urls of the application should be cached by varnish, Lacquer::CacheControl will be helpful.

config/initializers/caches.rb

require "lacquer/cache_control"

Lacquer.cache_control.configure do |config|
  config.register :static,              :url => "^/images",
                                        :expires_in => "365d"

  config.register :static,              :url => "^/stylesheets",
                                        :expires_in => "365d"

  config.register :static,              :url => "^/javascripts",
                                        :expires_in => "365d"

  config.register :class_section,       :url => "^(/[a-z]{2})?/(info_screens|class_sections)/%s.*$",
                                        :args => "[0-9]+",
                                        :expires_in => "1m"

  config.register :open_scoring,        :url => "^(/[a-z]{2})?/class_sections/%s/open_scoring.*$",
                                        :args => "[0-9]+",
                                        :expires_in => "1m"

end

In the sweeper we can do something like this

  class_section = ClassSection.find(1)
  Lacquer.cache_control.purge(:open_scoring, class_section)

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)

The varnish.vcl is preprocssed when starting varnishd with the rake tasks

rake lacquer:varnishd:start

config/varnish.vcl.erb

sub vcl_recv {
  # Lookup requests that we know should be cached
  if (<%= Lacquer.cache_control.to_vcl_conditions %>) {
    # Clear cookie and authorization headers, set grace time, lookup in the cache
    unset req.http.Cookie;
    unset req.http.Authorization;
    return(lookup);
  }

  # Generates
  #
  # if(req.url ~ "^/images" ||
  #    req.url ~ "^/stylesheets" ||
  #    req.url ~ "^/javascripts" ||
  #    req.url ~ "^(/[a-z]{2})?/(info_screens|class_sections)/[0-9]+.*$" ||
  #    req.url ~ "^(/[a-z]{2})?/class_sections/[0-9]+/open_scoring.*$") {
  #    unset req.http.Cookie;
  #    unset req.http.Authorization;
  #    return(lookup);
  # }
}

sub vcl_fetch {
  <%= Lacquer.cache_control.to_vcl_override_ttl_urls %>

  # Generates
  #
  # if(req.url ~ "^/images" || req.url ~ "^/stylesheets" || req.url ~ "^/javascripts") {
  #   unset beresp.http.Set-Cookie;
  #   set beresp.ttl = 365d;
  #   return(deliver);
  # }
  #
  # if(req.url ~ "^(/[a-z]{2})?/(info_screens|class_sections)/[0-9]+.*$" ||
  #   req.url ~ "^(/[a-z]{2})?/class_sections/[0-9]+/open_scoring.*$") {
  #   unset beresp.http.Set-Cookie;
  #   set beresp.ttl = 1m;
  #   return(deliver);
  # }
}

This makes it much simpler to perform cacheing, it's only setuped in one place, purge it or just let it expire.

Usage

To set a custom ttl for a controller:

before_filter { |controller| controller.set_cache_ttl(15.minutes) }

Clearing the cache:

class Posts < ApplicationController
  after_filter :clear_cache, :only => [ :create, :update, :destroy ]

private

  def clear_cache
    clear_cache_for(
      root_path,
      posts_path,
      post_path(@post))
  end
end

Control varnishd with the following rake tasks

rake lacquer:varnishd:start
rake lacquer:varnishd:stop
rake lacquer:varnishd:restart
rake lacquer:varnishd:reload
rake lacquer:varnishd:status
rake lacquer:varnishd:global_purge  

Deployment

Lacquer supports Capistrano 2.5+

For Capistrano 2.5 just add require 'lacquer/capistrano' to your config/deploy.rb file.

For Capistrano 3+ add require 'lacquer/capistrano' to your Capfile.

# Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'lacquer/capistrano'

Adding this will give you the following cap tasks

cap lacquer:global_purge           # global_purge varnish
cap lacquer:restart                # restart varnish
cap lacquer:start                  # start varnish
cap lacquer:status                 # status varnish
cap lacquer:stop                   # stop varnish

Gotchas

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:

Cache-Control: max-age=0, no-cache, private

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.

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.

As a result, all you have to do to set a cacheable action is the before filter above.

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • 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)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) 2015 Russ Smith. See LICENSE for details.

More Repositories

1

sidekiq-history

Sidekiq History
Ruby
57
star
2

country_code_select

Country Code Select Form Helper for Rails
Ruby
31
star
3

openpoker

A scalable poker server written in Erlang
Erlang
19
star
4

eighttrack

VCR for Crystal
Crystal
11
star
5

gitnub-gtk

A port of gitnub to gtk.
Ruby
11
star
6

smarty_streets

smartystreets.com ruby gem
Ruby
8
star
7

jacks-php

I am Jacks PHP framework.
PHP
6
star
8

devise_password_sharing_extension

Password Sharing Security Tool
Ruby
6
star
9

thumbor

Crystal Lang library for creating thumbor image urls.
Crystal
6
star
10

gosu-tetris

Gosu implementation of classic Tetris
Ruby
5
star
11

wander

Maybe a Router?
Crystal
5
star
12

base58

base58 for Crystal
Crystal
5
star
13

crystal-bigquery

A Bigquery client for Crystal
Crystal
4
star
14

ics_builder

ICS template Rails plugin
Ruby
4
star
15

Rubybooty

Rubybooty
Ruby
4
star
16

distributed

Distributed Rails Objects
Ruby
3
star
17

bear

Rails 3 application generator.
Ruby
2
star
18

listmonk-crystal

Listmonk integration for Crystal
Crystal
2
star
19

jshq

jshq
Ruby
2
star
20

stathat

Crystal client to post data to stathat.com
Crystal
2
star
21

litespeed-rails-runner

Rails using Rack on Litespeed
Ruby
2
star
22

russ.github.com

russ.github.com
2
star
23

antmediacr

AntMedia for Crystal
Crystal
1
star
24

Facebook-Focker

Facebook Focker
Ruby
1
star
25

dotfiles

dotfiles
Lua
1
star
26

easypost-crystal

EasyPost Shipping API Client Library for Crystal
Crystal
1
star
27

rocker

Arduino and MIDI powered art installation.
Java
1
star
28

kata-template-scala-scalatest-flatspec

Scala/ScalaTest-FlatSpec Kata Template
Scala
1
star
29

SimPoll

SimPoll
CoffeeScript
1
star
30

webcam-capture

Webcam Image Capturing
Crystal
1
star
31

rails-up

rails-up
Ruby
1
star
32

Sheen

Ruby port of varnish.
Ruby
1
star
33

haitatsu

Push oriented deployment.
Ruby
1
star
34

SimpleTestExample

SimpleTestExample
PHP
1
star
35

Monocle

A history of view events.
Ruby
1
star
36

pokerplayer

pokerplayer
1
star
37

directed-graph

directed-graph
Ruby
1
star
38

hyouki

A better way to view and design emails.
Ruby
1
star
39

try_git

1
star
40

lv-rspec-demo

Las Vegas RSpec Demo
Ruby
1
star
41

tj_lavin

A small wrapper around LavinMQ for job management.
Crystal
1
star
42

redis_wrapper

redis_wrapper
Elixir
1
star