diff options
27 files changed, 387 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore index 527bccb44..1155b055d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ TAGS /public/download /public/*theme /vendor/bundle -.bundle
\ No newline at end of file +.bundle +bin/
\ No newline at end of file @@ -16,6 +16,7 @@ gem 'json', '~> 1.5.1' gem 'mahoro' gem 'memcache-client', :require => 'memcache' gem 'locale', '>= 2.0.5' +gem 'net-purge' gem 'rack', '~> 1.1.0' gem 'rdoc', '~> 2.4.3' gem 'recaptcha', '~> 0.3.1', :require => 'recaptcha/rails' @@ -37,3 +38,7 @@ group :test do gem 'fakeweb' gem 'rspec-rails', '~> 1.3.4' end + +group :develop do + gem 'ruby-debug' +end diff --git a/Gemfile.lock b/Gemfile.lock index 36ef12525..f92be20a9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -17,14 +17,18 @@ GEM activeresource (2.3.14) activesupport (= 2.3.14) activesupport (2.3.14) + columnize (0.3.6) fakeweb (1.3.0) fast_gettext (0.6.1) gettext (2.1.0) locale (>= 2.0.5) json (1.5.4) + linecache (0.46) + rbx-require-relative (> 0.0.4) locale (2.0.5) mahoro (0.3) memcache-client (1.8.5) + net-purge (0.1.0) pg (0.11.0) rack (1.1.0) rails (2.3.14) @@ -35,6 +39,7 @@ GEM activesupport (= 2.3.14) rake (>= 0.8.3) rake (0.9.2) + rbx-require-relative (0.0.9) rdoc (2.4.3) recaptcha (0.3.1) rmagick (2.13.1) @@ -44,6 +49,11 @@ GEM rspec-rails (1.3.4) rack (>= 1.0.0) rspec (~> 1.3.1) + ruby-debug (0.10.4) + columnize (>= 0.1) + ruby-debug-base (~> 0.10.4.0) + ruby-debug-base (0.10.4) + linecache (>= 0.3) ruby-msg (1.5.0) ruby-ole (>= 1.2.8) vpim (>= 0.360) @@ -64,6 +74,7 @@ DEPENDENCIES locale (>= 2.0.5) mahoro memcache-client + net-purge pg rack (~> 1.1.0) rails (= 2.3.14) @@ -73,6 +84,7 @@ DEPENDENCIES routing-filter (~> 0.2.4) rspec (~> 1.3.2) rspec-rails (~> 1.3.4) + ruby-debug ruby-msg (~> 1.5.0) vpim will_paginate (~> 2.3.11) diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index adb506b91..1612e5179 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -36,6 +36,8 @@ class AdminController < ApplicationController # also force a search reindexing (so changed text reflected in search) info_request.reindex_request_events + # and remove from varnsi + info_request.purge_in_cache end # Expire cached attachment files for a user diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0ec8e206e..0d0cca3e4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # controllers/application.rb: # Parent class of all controllers in FOI site. Filters added to this controller # apply to all controllers in the application. Likewise, all the methods added @@ -543,16 +544,6 @@ class ApplicationController < ActionController::Base return country end - def quietly_try_to_open(url) - begin - result = open(url).read.strip - rescue OpenURI::HTTPError, SocketError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH - logger.warn("Unable to open third-party URL #{url}") - result = "" - end - return result - end - # URL generating functions are needed by all controllers (for redirects), # views (for links) and mailers (for use in emails), so include them into # all of all. diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index cbbcf5aa6..2896de68a 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -816,7 +816,6 @@ class IncomingMessage < ActiveRecord::Base :filename => _get_part_file_name(leaf), :charset => leaf.charset, :within_rfc822_subject => within_rfc822_subject, - :display_size => "0K", :body => body) attachment.save! attachments << attachment.id diff --git a/app/models/info_request.rb b/app/models/info_request.rb index b5a1cd833..78121f5ea 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -23,6 +23,9 @@ require 'digest/sha1' class InfoRequest < ActiveRecord::Base + include ActionView::Helpers::UrlHelper + include ActionController::UrlWriter + strip_attributes! validates_presence_of :title, :message => N_("Please enter a summary of your request") @@ -453,7 +456,6 @@ public # An annotation (comment) is made def add_comment(body, user) comment = Comment.new - ActiveRecord::Base.transaction do comment.body = body comment.user = user @@ -1042,6 +1044,18 @@ public end return ret end + + before_save :purge_in_cache + def purge_in_cache + if !MySociety::Config.get('VARNISH_HOST').nil? && !self.id.nil? + # we only do this for existing info_requests (new ones have a nil id) + path = url_for(:controller => 'request', :action => 'show', :url_title => self.url_title, :only_path => true, :locale => :none) + req = PurgeRequest.new(:url => path, + :model => self.class.base_class.to_s, + :model_id => self.id) + req.save() + end + end end diff --git a/app/models/outgoing_message.rb b/app/models/outgoing_message.rb index cc561b21d..de3c916aa 100644 --- a/app/models/outgoing_message.rb +++ b/app/models/outgoing_message.rb @@ -267,7 +267,10 @@ class OutgoingMessage < ActiveRecord::Base end end - + after_save(:purge_in_cache) + def purge_in_cache + self.info_request.purge_in_cache + end end diff --git a/app/models/public_body.rb b/app/models/public_body.rb index a18af8c69..2a0661fab 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -240,7 +240,7 @@ class PublicBody < ActiveRecord::Base # Return the short name if present, or else long name def short_or_long_name if self.short_name.nil? || self.short_name.empty? # 'nil' can happen during construction - self.name + self.name.nil? ? "" : self.name else self.short_name end @@ -547,6 +547,11 @@ class PublicBody < ActiveRecord::Base } end + after_save(:purge_in_cache) + def purge_in_cache + self.info_requests.each {|x| x.purge_in_cache} + end + end diff --git a/app/models/purge_request.rb b/app/models/purge_request.rb new file mode 100644 index 000000000..1450058b1 --- /dev/null +++ b/app/models/purge_request.rb @@ -0,0 +1,41 @@ +# models/purge_request.rb: +# A queue of URLs to purge +# +# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. +# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ +# + +class PurgeRequest < ActiveRecord::Base + def self.purge_all + done_something = false + for item in PurgeRequest.all() + item.purge + done_something = true + end + return done_something + end + + def self.purge_all_loop + # Run purge_all in an endless loop, sleeping when there is nothing to do + while true + sleep_seconds = 1 + while !purge_all + sleep sleep_seconds + sleep_seconds *= 2 + sleep_seconds = 300 if sleep_seconds > 300 + end + end + end + + def purge + config = MySociety::Config.load_default() + varnish_url = config['VARNISH_HOST'] + result = quietly_try_to_purge(varnish_url, self.url) + if result == "200" + self.delete() + end + end +end + + + diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index 58d70ed86..3d147b8e6 100644 --- a/app/models/track_thing.rb +++ b/app/models/track_thing.rb @@ -108,7 +108,7 @@ class TrackThing < ActiveRecord::Base end descriptions = [] if varieties.include? _("requests") - descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).join(_(' or '))) + descriptions << _("requests which are {{list_of_statuses}}", :list_of_statuses => Array(statuses).sort.join(_(' or '))) varieties -= [_("requests")] end if descriptions.empty? and varieties.empty? @@ -116,7 +116,7 @@ class TrackThing < ActiveRecord::Base end descriptions += Array(varieties) parsed_text = parsed_text.strip - descriptions = descriptions.join(_(" or ")) + descriptions = descriptions.sort.join(_(" or ")) if !parsed_text.empty? descriptions += _("{{list_of_things}} matching text '{{search_query}}'", :list_of_things => "", :search_query => parsed_text) end diff --git a/app/models/user.rb b/app/models/user.rb index 59a84b7aa..73d65a8ca 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -422,5 +422,12 @@ class User < ActiveRecord::Base end return true end + + after_save(:purge_in_cache) + def purge_in_cache + # XXX should only be if specific attributes have changed + self.info_requests.each {|x| x.purge_in_cache} + end + end diff --git a/config/environment.rb b/config/environment.rb index e35194bc7..b958c6475 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -135,6 +135,7 @@ require 'i18n_fixes.rb' require 'rack_quote_monkeypatch.rb' require 'world_foi_websites.rb' require 'alaveteli_external_command.rb' +require 'quiet_opener.rb' ExceptionNotification::Notifier.sender_address = MySociety::Config::get('EXCEPTION_NOTIFICATIONS_FROM') ExceptionNotification::Notifier.exception_recipients = MySociety::Config::get('EXCEPTION_NOTIFICATIONS_TO') diff --git a/config/environments/development.rb b/config/environments/development.rb index d5f2f5772..a1e8133a8 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,5 +1,7 @@ # Settings specified here will take precedence over those in config/environment.rb +config.log_level = :info + # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the webserver when you make code changes. diff --git a/config/general.yml-example b/config/general.yml-example index ed04e0fd5..84980c353 100644 --- a/config/general.yml-example +++ b/config/general.yml-example @@ -142,3 +142,7 @@ EXCEPTION_NOTIFICATIONS_TO: # This rate limiting can be turned off per-user via the admin interface MAX_REQUESTS_PER_USER_PER_DAY: 6 + +# This is used to work out where to send purge requests. Should be +# unset if you aren't running behind varnish +VARNISH_HOST: localhost diff --git a/config/purge-varnish-debian.ugly b/config/purge-varnish-debian.ugly new file mode 100644 index 000000000..3e77c09c3 --- /dev/null +++ b/config/purge-varnish-debian.ugly @@ -0,0 +1,81 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: purge-varnish +# Required-Start: $local_fs $syslog +# Required-Stop: $local_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: purge-varnish is a daemon running the Alaveteli email alerts +# Description: purge-varnish send Alaveteli email alerts as required +### END INIT INFO +# +# !!(*= $daemon_name *)!! Start the Alaveteli email alert daemon + +NAME=!!(*= $daemon_name *)!! +DAEMON=/data/vhost/!!(*= $vhost *)!!/alaveteli/script/runner +DAEMON_ARGS="--daemon PurgeRequest.purge_all_loop" +PIDFILE=/data/vhost/!!(*= $vhost *)!!/purge-varnish.pid +LOGFILE=/data/vhost/!!(*= $vhost *)!!/logs/purge-varnish.log +DUSER=!!(*= $user *)!! + +trap "" 1 + +export PIDFILE LOGFILE + +quietly_start_daemon() { + /sbin/start-stop-daemon --quiet --start --pidfile "$PIDFILE" --chuid "$DUSER" --startas "$DAEMON" -- $DAEMON_ARGS +} + +start_daemon() { + /sbin/start-stop-daemon --start --pidfile "$PIDFILE" --chuid "$DUSER" --startas "$DAEMON" -- $DAEMON_ARGS +} + +stop_daemon() { + /sbin/start-stop-daemon --stop --oknodo --pidfile "$PIDFILE" +} + +restart() { stop; start; } + +case "$1" in + check) + quietly_start_daemon + if [ $? -ne 1 ] + then + echo "Alaveteli alert daemon was not running; now restarted" + exit 1 + else + exit 0 + fi + ;; + + start) + echo -n "Starting Alaveteli alert daemon: $NAME" + start_daemon + ;; + + stop) + echo -n "Stopping Alaveteli alert daemon: $NAME" + stop_daemon + ;; + + restart) + echo -n "Restarting Alaveteli alert daemon: $NAME" + stop_daemon + start_daemon + ;; + + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|check}" + exit 1 + ;; +esac + +if [ $? -eq 0 ]; then + echo . + exit 0 +else + echo " failed" + exit 1 +fi + diff --git a/config/test.yml b/config/test.yml index 90689395a..c35001747 100644 --- a/config/test.yml +++ b/config/test.yml @@ -124,3 +124,4 @@ EXCEPTION_NOTIFICATIONS_TO: MAX_REQUESTS_PER_USER_PER_DAY: 2 +VARNISH_HOST: varnish.localdomain diff --git a/config/varnish-alaveteli.vcl b/config/varnish-alaveteli.vcl index 7eedf83fc..f81ec2295 100644 --- a/config/varnish-alaveteli.vcl +++ b/config/varnish-alaveteli.vcl @@ -9,12 +9,18 @@ backend default { .host = "127.0.0.1"; - .port = "80"; + .port = "3000"; .connect_timeout = 600s; .first_byte_timeout = 600s; .between_bytes_timeout = 600s; } +// set the servers alaveteli can issue a purge from +acl purge { + "localhost"; + "127.0.0.1"; +} + sub vcl_recv { # Handle IPv6 @@ -54,12 +60,13 @@ sub vcl_recv { req.request != "HEAD" && req.request != "POST" && req.request != "PUT" && + req.request != "PURGE" && req.request != "DELETE" ) { # We don't allow any other methods. error 405 "Method Not Allowed"; } - if (req.request != "GET" && req.request != "HEAD") { + if (req.request != "GET" && req.request != "HEAD" && req.request != "PURGE") { /* We only deal with GET and HEAD by default, the rest get passed direct to backend */ return (pass); } @@ -73,15 +80,21 @@ sub vcl_recv { if (req.http.Authorization || req.http.Cookie) { return (pass); } - # Let's have a little grace set req.grace = 30s; + # Handle PURGE requests + if (req.request == "PURGE") { + if (!client.ip ~ purge) { + error 405 "Not allowed."; + } + ban("obj.http.x-url ~ " + req.url); + error 200 "Banned"; + } return (lookup); } - sub vcl_fetch { - + set beresp.http.x-url = req.url; if (req.url ~ "\.(png|gif|jpg|jpeg|swf|css|js|rdf|ico|txt)(\?.*|)$") { # Ignore backend headers.. remove beresp.http.set-Cookie; @@ -94,3 +107,4 @@ sub vcl_fetch { return (deliver); } } + diff --git a/db/migrate/111_create_purge_requests.rb b/db/migrate/111_create_purge_requests.rb new file mode 100644 index 000000000..0b4fd1d1d --- /dev/null +++ b/db/migrate/111_create_purge_requests.rb @@ -0,0 +1,14 @@ +class CreatePurgeRequests < ActiveRecord::Migration + def self.up + create_table :purge_requests do |t| + t.column :url, :string + t.column :created_at, :datetime, :null => false + t.column :model, :string, :null => false + t.column :model_id, :integer, :null => false + end + end + + def self.down + drop_table :purge_requests + end +end diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 51da903b1..fe79a6e13 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -3,6 +3,10 @@ ## Highlighted features * Ruby dependencies are now handled by Bundler +* Support for invalidating accelerator cache -- this makes it much + less likely, when using Varnish, that users will be presented with + stale content. Fixes + [issue #436](https://github.com/sebbacon/alaveteli/issues/436) ## Upgrade notes @@ -14,6 +18,13 @@ install various things. Part of this is compiling xapian, which may take a *long* time (subsequent deployments should be much faster) +* To support invalidating the Varnish cache, ensure that there's a + value for `VARNISH_HOST` in `general.yml` (normally this would be + `localhost`). You will also need to update your Varnish server to + support PURGE requests. The example configuration provided at + `config/varnish-alaveteli.vcl` will work for Varnish 3 and above. If + you leave `VARNISH_HOST` blank, it will have no effect. + # Version 0.5.1 ## Highlighted features diff --git a/lib/quiet_opener.rb b/lib/quiet_opener.rb new file mode 100644 index 000000000..a077ca323 --- /dev/null +++ b/lib/quiet_opener.rb @@ -0,0 +1,34 @@ +require 'open-uri' +require 'net-purge' + +def quietly_try_to_open(url) + begin + result = open(url).read.strip + rescue OpenURI::HTTPError, SocketError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH + logger.warn("Unable to open third-party URL #{url}") + result = "" + end + return result +end + +def quietly_try_to_purge(host, url) + begin + result = "" + result_body = "" + Net::HTTP.start(host) {|http| + request = Net::HTTP::Purge.new(url) + response = http.request(request) + result = response.code + result_body = response.body + } + rescue OpenURI::HTTPError, SocketError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH + logger.warn("Unable to reach host #{host}") + end + if result == "200" + logger.info("Purged URL #{url} at #{host}: #{result}") + else + logger.warn("Unable to purge URL #{url} at #{host}: status #{result}") + end + return result +end + diff --git a/script/purge-varnish b/script/purge-varnish new file mode 100755 index 000000000..932cf6635 --- /dev/null +++ b/script/purge-varnish @@ -0,0 +1,11 @@ +#!/bin/bash + +LOC=`dirname $0` + +if [ "$1" == "--loop" ] +then + "$LOC/runner" 'PurgeRequest.purge_all_loop' +else + "$LOC/runner" 'PurgeRequest.purge_all' +fi + diff --git a/spec/controllers/admin_censor_rule_controller_spec.rb b/spec/controllers/admin_censor_rule_controller_spec.rb new file mode 100644 index 000000000..8893a858b --- /dev/null +++ b/spec/controllers/admin_censor_rule_controller_spec.rb @@ -0,0 +1,19 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') + +describe AdminCensorRuleController, "when making censor rules from the admin interface" do + integrate_views + before { basic_auth_login @request } + + it "should create a censor rule and purge the corresponding request from varnish" do + ir = info_requests(:fancy_dog_request) + post :create, :censor_rule => { + :text => "meat", + :replacement => "tofu", + :last_edit_comment => "none", + :info_request => ir + } + PurgeRequest.all().first.model_id.should == ir.id + end + + +end diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 81c69db76..c79ddab36 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -117,6 +117,57 @@ describe RequestController, "when listing recent requests" do end +describe RequestController, "when changing things that appear on the request page" do + + integrate_views + + it "should purge the downstream cache when mail is received" do + ir = info_requests(:fancy_dog_request) + receive_incoming_mail('incoming-request-plain.email', ir.incoming_email) + PurgeRequest.all().first.model_id.should == ir.id + end + it "should purge the downstream cache when a comment is added" do + ir = info_requests(:fancy_dog_request) + new_comment = info_requests(:fancy_dog_request).add_comment('I also love making annotations.', users(:bob_smith_user)) + PurgeRequest.all().first.model_id.should == ir.id + end + it "should purge the downstream cache when a followup is made" do + session[:user_id] = users(:bob_smith_user).id + ir = info_requests(:fancy_dog_request) + post :show_response, :outgoing_message => { :body => "What a useless response! You suck.", :what_doing => 'normal_sort' }, :id => ir.id, :incoming_message_id => incoming_messages(:useless_incoming_message), :submitted_followup => 1 + PurgeRequest.all().first.model_id.should == ir.id + end + it "should purge the downstream cache when the request is categorised" do + ir = info_requests(:fancy_dog_request) + ir.set_described_state('waiting_clarification') + PurgeRequest.all().first.model_id.should == ir.id + end + it "should purge the downstream cache when the authority data is changed" do + ir = info_requests(:fancy_dog_request) + ir.public_body.name = "Something new" + ir.public_body.save! + PurgeRequest.all().map{|x| x.model_id}.should =~ ir.public_body.info_requests.map{|x| x.id} + end + it "should purge the downstream cache when the user details are changed" do + ir = info_requests(:fancy_dog_request) + ir.user.name = "Something new" + ir.user.save! + PurgeRequest.all().map{|x| x.model_id}.should =~ ir.user.info_requests.map{|x| x.id} + end + it "should purge the downstream cache when censor rules have changed" do + # XXX really, CensorRules should execute expiry logic as part + # of the after_save of the model. Currently this is part of + # the AdminCensorRuleController logic, so must be tested from + # there. Leaving this stub test in place as a reminder + end + it "should purge the downstream cache when something is hidden by an admin" do + ir = info_requests(:fancy_dog_request) + ir.prominence = 'hidden' + ir.save! + PurgeRequest.all().first.model_id.should == ir.id + end +end + describe RequestController, "when showing one request" do before(:each) do @@ -185,7 +236,7 @@ describe RequestController, "when showing one request" do describe 'when handling incoming mail' do integrate_views - + it "should receive incoming messages, send email to creator, and show them" do ir = info_requests(:fancy_dog_request) ir.incoming_messages.each { |x| x.parse_raw_email! } @@ -991,6 +1042,7 @@ describe RequestController, "when classifying an information request" do session[:user_id] = @admin_user.id @dog_request = info_requests(:fancy_dog_request) InfoRequest.stub!(:find).and_return(@dog_request) + @dog_request.stub!(:each).and_return([@dog_request]) end it 'should update the status of the request' do @@ -1032,6 +1084,7 @@ describe RequestController, "when classifying an information request" do @dog_request.user = @admin_user @dog_request.save! InfoRequest.stub!(:find).and_return(@dog_request) + @dog_request.stub!(:each).and_return([@dog_request]) end it 'should update the status of the request' do @@ -1068,6 +1121,7 @@ describe RequestController, "when classifying an information request" do @request_owner = users(:bob_smith_user) session[:user_id] = @request_owner.id @dog_request.awaiting_description.should == true + @dog_request.stub!(:each).and_return([@dog_request]) end it "should successfully classify response if logged in as user controlling request" do @@ -1135,6 +1189,7 @@ describe RequestController, "when classifying an information request" do @request_owner = users(:bob_smith_user) session[:user_id] = @request_owner.id @dog_request = info_requests(:fancy_dog_request) + @dog_request.stub!(:each).and_return([@dog_request]) InfoRequest.stub!(:find).and_return(@dog_request) @old_filters = ActionController::Routing::Routes.filters ActionController::Routing::Routes.filters = RoutingFilter::Chain.new @@ -1768,6 +1823,7 @@ describe RequestController, "when showing similar requests" do get :similar, :url_title => "there_is_really_no_such_path_owNAFkHR" }.should raise_error(ActiveRecord::RecordNotFound) end + end diff --git a/spec/models/purge_request_spec.rb b/spec/models/purge_request_spec.rb new file mode 100644 index 000000000..f7d01f784 --- /dev/null +++ b/spec/models/purge_request_spec.rb @@ -0,0 +1,32 @@ +require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') +require 'fakeweb' + +describe PurgeRequest, "purging things" do + before do + FakeWeb.last_request = nil + end + + it 'should issue purge requests to the server' do + req = PurgeRequest.new(:url => "/begone_from_here", + :model => "don't care", + :model_id => "don't care") + req.save() + PurgeRequest.all().count.should == 1 + PurgeRequest.purge_all() + PurgeRequest.all().count.should == 0 + end + + it 'should fail silently for a misconfigured server' do + FakeWeb.register_uri(:get, %r|brokenv|, :body => "BROKEN") + config = MySociety::Config.load_default() + config['VARNISH_HOST'] = "brokencache" + req = PurgeRequest.new(:url => "/begone_from_here", + :model => "don't care", + :model_id => "don't care") + req.save() + PurgeRequest.all().count.should == 1 + PurgeRequest.purge_all() + PurgeRequest.all().count.should == 1 + end +end + diff --git a/spec/models/track_thing_spec.rb b/spec/models/track_thing_spec.rb index bd122941a..93f407475 100644 --- a/spec/models/track_thing_spec.rb +++ b/spec/models/track_thing_spec.rb @@ -36,7 +36,7 @@ describe TrackThing, "when tracking changes" do it "will make some sane descriptions of search-based tracks" do tests = [['bob variety:user', "users matching text 'bob'"], - ['bob (variety:sent OR variety:followup_sent OR variety:response OR variety:comment) (latest_status:successful OR latest_status:partially_successful OR latest_status:rejected OR latest_status:not_held)', "requests which are successful or unsuccessful or comments matching text 'bob'"], + ['bob (variety:sent OR variety:followup_sent OR variety:response OR variety:comment) (latest_status:successful OR latest_status:partially_successful OR latest_status:rejected OR latest_status:not_held)', "comments or requests which are successful or unsuccessful matching text 'bob'"], ['(latest_status:waiting_response OR latest_status:waiting_clarification OR waiting_classification:true)', 'requests which are awaiting a response']] for query, description in tests track_thing = TrackThing.create_track_for_search_query(query) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 99cf8a2c8..a98a5113d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -13,6 +13,9 @@ config['ADMIN_PASSWORD'] = 'baz' # tests assume 20 days config['REPLY_LATE_AFTER_DAYS'] = 20 +# register a fake Varnish server +require 'fakeweb' +FakeWeb.register_uri(:purge, %r|varnish.localdomain|, :body => "OK") # Uncomment the next line to use webrat's matchers #require 'webrat/integrations/rspec-rails' |