diff options
23 files changed, 182 insertions, 51 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7aa522389..2633aca4d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -371,7 +371,7 @@ class ApplicationController < ActionController::Base # XXX this is a result of the OR hack below -- should fix by # allowing a parameter to perform_search to control the # default operator! - query = query.strip.gsub(/(\s-\s|&)/, "") + query = query.strip.gsub(/(\s-\s|&|\(|\))/, "") query = query.split(/ +(?![-+]+)/) if query.last.nil? || query.last.strip.length < 3 xapian_requests = nil @@ -435,7 +435,7 @@ class ApplicationController < ActionController::Base params[:latest_status] = [params[:latest_status]] end if params[:latest_status].include?("recent") || params[:latest_status].include?("all") - query += " variety:sent" + query += " (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)" end if params[:latest_status].include? "successful" statuses << ['latest_status:successful', 'latest_status:partially_successful'] @@ -444,7 +444,7 @@ class ApplicationController < ActionController::Base statuses << ['latest_status:rejected', 'latest_status:not_held'] end if params[:latest_status].include? "awaiting" - statuses << ['latest_status:waiting_response', 'latest_status:waiting_clarification', 'waiting_classification:true'] + statuses << ['latest_status:waiting_response', 'latest_status:waiting_clarification', 'waiting_classification:true', 'latest_status:internal_review','latest_status:gone_postal', 'latest_status:error_message', 'latest_status:requires_admin'] end if params[:latest_status].include? "internal_review" statuses << ['status:internal_review'] diff --git a/app/controllers/general_controller.rb b/app/controllers/general_controller.rb index 194a1cec0..6cdfb9d5f 100644 --- a/app/controllers/general_controller.rb +++ b/app/controllers/general_controller.rb @@ -99,7 +99,7 @@ class GeneralController < ApplicationController @variety_postfix = path.pop end @variety_postfix = "bodies" if @variety_postfix.nil? && !params[:bodies].nil? - @variety_postfix = "requests" if @variety_postfix.nil? + @variety_postfix = "all" if @variety_postfix.nil? if @variety_postfix != "users" @common_query = get_tags_from_params end diff --git a/app/controllers/request_controller.rb b/app/controllers/request_controller.rb index 99aa3c7ea..af0ac4a46 100644 --- a/app/controllers/request_controller.rb +++ b/app/controllers/request_controller.rb @@ -601,12 +601,13 @@ class RequestController < ApplicationController before_filter :authenticate_attachment, :only => [ :get_attachment, :get_attachment_as_html ] def authenticate_attachment - # Test for hidden - if request.path =~ /\/$/ + if request.path =~ /\/$/ || !(params[:part] =~ /^\d+$/) raise PermissionDenied.new("Directory listing not allowed") else + # Test for hidden incoming_message = IncomingMessage.find(params[:incoming_message_id]) if !incoming_message.info_request.user_can_view?(authenticated_user) + @info_request = incoming_message.info_request # used by view render :template => 'request/hidden', :status => 410 # gone end end diff --git a/app/models/foi_attachment.rb b/app/models/foi_attachment.rb index d12df688a..20c40abea 100644 --- a/app/models/foi_attachment.rb +++ b/app/models/foi_attachment.rb @@ -34,6 +34,9 @@ class FoiAttachment < ActiveRecord::Base before_validation :ensure_filename!, :only => [:filename] before_destroy :delete_cached_file! + BODY_MAX_TRIES = 3 + BODY_MAX_DELAY = 5 + def directory base_dir = File.join(File.dirname(__FILE__), "../../cache", "attachments_#{ENV['RAILS_ENV']}") return File.join(base_dir, self.hexdigest[0..2]) @@ -45,6 +48,7 @@ class FoiAttachment < ActiveRecord::Base def delete_cached_file! begin + @cached_body = nil File.delete(self.filepath) rescue end @@ -57,7 +61,6 @@ class FoiAttachment < ActiveRecord::Base end File.open(self.filepath, "wb") { |file| file.write d - file.fsync } update_display_size! @cached_body = d @@ -65,12 +68,23 @@ class FoiAttachment < ActiveRecord::Base def body if @cached_body.nil? + tries = 0 + delay = 1 begin @cached_body = File.open(self.filepath, "rb" ).read rescue Errno::ENOENT # we've lost our cached attachments for some reason. Reparse them. + if tries > BODY_MAX_TRIES + raise + else + sleep delay + end + tries += 1 + delay *= 2 + delay = BODY_MAX_DELAY if delay > BODY_MAX_DELAY force = true self.incoming_message.parse_raw_email!(force) + retry end end return @cached_body diff --git a/app/models/info_request.rb b/app/models/info_request.rb index a0652ecd8..b5a1cd833 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -21,7 +21,6 @@ require 'digest/sha1' -require File.join(File.dirname(__FILE__),'../../vendor/plugins/acts_as_xapian/lib/acts_as_xapian') class InfoRequest < ActiveRecord::Base strip_attributes! diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb index 272f2ea83..83cce9045 100644 --- a/app/models/request_mailer.rb +++ b/app/models/request_mailer.rb @@ -353,7 +353,18 @@ class RequestMailer < ApplicationMailer # That that patch has not been applied, despite bribes of beer, is # typical of the lack of quality of Rails. - info_requests = InfoRequest.find(:all, :conditions => [ "(select id from info_request_events where event_type = 'comment' and info_request_events.info_request_id = info_requests.id and created_at > ? limit 1) is not null", Time.now() - 1.month ], :include => [ { :info_request_events => :user_info_request_sent_alerts } ], :order => "info_requests.id, info_request_events.created_at" ) + info_requests = InfoRequest.find(:all, + :conditions => [ + "info_requests.id in ( + select info_request_id + from info_request_events + where event_type = 'comment' + and created_at > (now() - '1 month'::interval) + )" + ], + :include => [ { :info_request_events => :user_info_request_sent_alerts } ], + :order => "info_requests.id, info_request_events.created_at" + ) for info_request in info_requests # Count number of new comments to alert on diff --git a/app/views/admin_public_body/new.rhtml b/app/views/admin_public_body/new.rhtml index b859fdf6a..047d5a5bb 100644 --- a/app/views/admin_public_body/new.rhtml +++ b/app/views/admin_public_body/new.rhtml @@ -11,9 +11,9 @@ <%= render :partial => 'tag_help' %> <div id="public_body_form"> - <% form_for :public_body, @public_body, :url => {:action => "create"} do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <p><%= f.submit "Create" %></p> + <% form_tag './create/' + @public_body.id.to_s do %> + <%= render :partial => 'form' %> + <p><%= submit_tag "Create" %></p> <% end %> <p> diff --git a/app/views/user/show.rhtml b/app/views/user/show.rhtml index 2d2394f5c..4fa29f00d 100644 --- a/app/views/user/show.rhtml +++ b/app/views/user/show.rhtml @@ -147,7 +147,7 @@ <% end %> <% else %> <h2 class="foi_results" id="foi_requests"> - <%= @is_you ? n_('Your %d Freedom of Information request', 'Your %d Freedom of Information requests', @xapian_requests.results.size) % @xapian_requests.results.size : n_('This person\'s %d Freedom of Information request', 'This person\'s %d Freedom of Information requests', @xapian_requests.matches_estimated.to_s) % @xapian_requests.matches_estimated %> + <%= @is_you ? n_('Your %d Freedom of Information request', 'Your %d Freedom of Information requests', @xapian_requests.matches_estimated.to_s) % @xapian_requests.matches_estimated.to_s : n_('This person\'s %d Freedom of Information request', 'This person\'s %d Freedom of Information requests', @xapian_requests.matches_estimated.to_s) % @xapian_requests.matches_estimated %> <!-- matches_estimated <%=@xapian_requests.matches_estimated%> --> <%= @match_phrase %> <%= @page_desc %> diff --git a/config/httpd.conf b/config/httpd.conf index 14197d8e4..3bbe50fb3 100644 --- a/config/httpd.conf +++ b/config/httpd.conf @@ -38,6 +38,7 @@ RewriteRule /files/(.+) http://files.whatdotheyknow.com/$1 PassengerResolveSymlinksInDocumentRoot on # Recommend setting this to 3 or less on servers with 512MB RAM PassengerMaxPoolSize 6 + RailsEnv production </IfModule> # Gzip font resources diff --git a/config/routes.rb b/config/routes.rb index 39c6ba70f..0af353fab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,7 +26,7 @@ ActionController::Routing::Routes.draw do |map| # Couldn't find a way to do this in routes which also picked up multiple other slashes # and dots and other characters that can appear in search query. So we sort it all # out in the controller. - general.search_general '/search/*combined/requests', :action => 'search', :view => 'requests' + general.search_general '/search/*combined/all', :action => 'search', :view => 'requests' general.search_general '/search/*combined', :action => 'search' general.advanced_search '/advancedsearch', :action => 'search_redirect', :advanced => true diff --git a/spec/controllers/admin_public_body_controller_spec.rb b/spec/controllers/admin_public_body_controller_spec.rb index 22af3df80..97636023a 100644 --- a/spec/controllers/admin_public_body_controller_spec.rb +++ b/spec/controllers/admin_public_body_controller_spec.rb @@ -44,6 +44,9 @@ describe AdminPublicBodyController, "when administering public bodies" do it "destroys a public body" do PublicBody.count.should == 2 + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy post :destroy, { :id => 3 } PublicBody.count.should == 1 end @@ -74,6 +77,9 @@ describe AdminPublicBodyController, "when administering public bodies and paying config['ADMIN_PASSWORD'] = '' @request.env["HTTP_AUTHORIZATION"] = "" PublicBody.count.should == 2 + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy post :destroy, { :id => 3 } PublicBody.count.should == 1 session[:using_admin].should == 1 @@ -84,6 +90,9 @@ describe AdminPublicBodyController, "when administering public bodies and paying config['ADMIN_PASSWORD'] = 'fuz' @request.env["HTTP_AUTHORIZATION"] = "" PublicBody.count.should == 2 + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy post :destroy, { :id => 3 } PublicBody.count.should == 1 session[:using_admin].should == 1 @@ -95,6 +104,9 @@ describe AdminPublicBodyController, "when administering public bodies and paying @request.env["HTTP_AUTHORIZATION"] = "" PublicBody.count.should == 2 basic_auth_login(@request, "baduser", "badpassword") + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy post :destroy, { :id => 3 } response.code.should == "401" PublicBody.count.should == 2 @@ -168,6 +180,9 @@ describe AdminPublicBodyController, "when administering public bodies with i18n" it "destroy a public body" do PublicBody.count.should == 2 + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy post :destroy, { :id => 3 } PublicBody.count.should == 1 end diff --git a/spec/controllers/public_body_controller_spec.rb b/spec/controllers/public_body_controller_spec.rb index 3996bd520..a563b92ad 100644 --- a/spec/controllers/public_body_controller_spec.rb +++ b/spec/controllers/public_body_controller_spec.rb @@ -6,6 +6,11 @@ describe PublicBodyController, "when showing a body" do integrate_views fixtures :public_bodies, :public_body_translations, :public_body_versions, :users, :info_requests, :raw_emails, :incoming_messages, :outgoing_messages, :comments, :info_request_events, :track_things + before(:each) do + load_raw_emails_data(raw_emails) + rebuild_xapian_index + end + it "should be successful" do get :show, :url_name => "dfh", :view => 'all' response.should be_success @@ -26,6 +31,8 @@ describe PublicBodyController, "when showing a body" do assigns[:xapian_requests].results.count.should == 2 get :show, :url_name => "tgq", :view => 'successful' assigns[:xapian_requests].results.count.should == 0 + get :show, :url_name => "dfh", :view => 'all' + assigns[:xapian_requests].results.count.should == 1 end it "should assign the body using different locale from that used for url_name" do diff --git a/spec/controllers/request_controller_spec.rb b/spec/controllers/request_controller_spec.rb index 96786a0a3..40cb168f4 100644 --- a/spec/controllers/request_controller_spec.rb +++ b/spec/controllers/request_controller_spec.rb @@ -23,7 +23,9 @@ describe RequestController, "when listing recent requests" do it "should filter requests" do get :list, :view => 'all' - assigns[:list_results].size.should == 2 + assigns[:list_results].size.should == 3 + # default sort order is the request with the most recently created event first + assigns[:list_results][0].info_request.id.should == 104 get :list, :view => 'successful' assigns[:list_results].size.should == 0 end @@ -32,9 +34,20 @@ describe RequestController, "when listing recent requests" do get :list, :view => 'all', :request_date_before => '13/10/2007' assigns[:list_results].size.should == 1 get :list, :view => 'all', :request_date_after => '13/10/2007' + assigns[:list_results].size.should == 3 + get :list, :view => 'all', :request_date_after => '13/10/2007', :request_date_before => '01/11/2007' + assigns[:list_results].size.should == 1 + end + + it "should list internal_review requests as unresolved ones" do + get :list, :view => 'awaiting' + assigns[:list_results].size.should == 0 + event = info_request_events(:useless_incoming_message_event) + event.calculated_state = "internal_review" + event.save! + rebuild_xapian_index + get :list, :view => 'awaiting' assigns[:list_results].size.should == 1 - get :list, :view => 'all', :request_date_after => '10/10/2007', :request_date_before => '01/01/2010' - assigns[:list_results].size.should == 2 end it "should assign the first page of results" do @@ -43,7 +56,7 @@ describe RequestController, "when listing recent requests" do :matches_estimated => 103) InfoRequest.should_receive(:full_search). - with([InfoRequestEvent]," variety:sent", "created_at", anything, anything, anything, anything). + with([InfoRequestEvent]," (variety:sent OR variety:followup_sent OR variety:response OR variety:comment)", "created_at", anything, anything, anything, anything). and_return(xap_results) get :list, :view => 'recent' assigns[:list_results].size.should == 25 @@ -1111,8 +1124,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /promptly, as normally/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email @@ -1139,8 +1152,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /promptly, as normally/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email end @@ -1164,8 +1177,8 @@ describe RequestController, "sending overdue request alerts" do RequestMailer.alert_overdue_requests deliveries = ActionMailer::Base.deliveries - deliveries.size.should == 1 - mail = deliveries[0] + deliveries.size.should == 2 + mail = deliveries[1] mail.body.should =~ /required by law/ mail.to_addrs.first.to_s.should == info_requests(:naughty_chicken_request).user.name_and_email @@ -1509,7 +1522,8 @@ describe RequestController, "when doing type ahead searches" do for phrase in ["Marketing/PR activities - Aldborough E-Act Free Schoo", "Request for communications between DCMS/Ed Vaizey and ICO from Jan 1st 2011 - May ", "Bellevue Road Ryde Isle of Wight PO33 2AR - what is the", - "NHS Ayrshire & Arran"] + "NHS Ayrshire & Arran", + "uda ( units of dent"] lambda { get :search_typeahead, :q => phrase }.should_not raise_error(StandardError) diff --git a/spec/controllers/user_controller_spec.rb b/spec/controllers/user_controller_spec.rb index 30ad61706..0cf574aa9 100644 --- a/spec/controllers/user_controller_spec.rb +++ b/spec/controllers/user_controller_spec.rb @@ -45,7 +45,7 @@ describe UserController, "when showing a user" do it "should search the user's contributions" do get :show, :url_name => "bob_smith" - assigns[:xapian_requests].results.count.should == 2 + assigns[:xapian_requests].results.count.should == 3 get :show, :url_name => "bob_smith", :user_query => "money" assigns[:xapian_requests].results.count.should == 1 end diff --git a/spec/fixtures/info_request_events.yml b/spec/fixtures/info_request_events.yml index 5e3c13083..9c6aa393d 100644 --- a/spec/fixtures/info_request_events.yml +++ b/spec/fixtures/info_request_events.yml @@ -38,4 +38,13 @@ silly_comment_event: event_type: comment outgoing_message_id: created_at: 2008-08-12 23:05:12.500942 +badger_outgoing_message_event: + params_yaml: "--- \n\ + :outgoing_message_id: 3\n" + id: 904 + info_request_id: 104 + event_type: sent + created_at: 2011-10-12 01:56:58.586598 + described_state: + outgoing_message_id: 3 diff --git a/spec/fixtures/info_requests.yml b/spec/fixtures/info_requests.yml index c1e3c1910..7b7e55ba6 100644 --- a/spec/fixtures/info_requests.yml +++ b/spec/fixtures/info_requests.yml @@ -20,3 +20,14 @@ naughty_chicken_request: described_state: waiting_response awaiting_description: false idhash: e8d18c84 +badger_request: + id: 104 + title: Are you really a badger? + url_title: are_you_really_a_badger + created_at: 2011-10-13 18:15:57 + updated_at: 2011-10-13 18:15:57 + public_body_id: 3 + user_id: 1 + described_state: waiting_response + awaiting_description: false + idhash: e8d18c84 diff --git a/spec/fixtures/outgoing_messages.yml b/spec/fixtures/outgoing_messages.yml index b89492aa5..0cebdd5c5 100644 --- a/spec/fixtures/outgoing_messages.yml +++ b/spec/fixtures/outgoing_messages.yml @@ -33,4 +33,16 @@ silly_outgoing_message: last_sent_at: 2007-10-14 10:41:12.686264 created_at: 2007-10-14 01:56:58.586598 what_doing: normal_sort +badger_outgoing_message: + id: 3 + info_request_id: 104 + message_type: initial_request + status: sent + updated_at: 2011-10-14 01:56:58.586598 + body: "Is it true that you are really a badger, in fact?" + last_sent_at: 2011-10-14 10:41:12.686264 + created_at: 2011-10-14 01:56:58.586598 + what_doing: normal_sort + + diff --git a/spec/integration/errors_spec.rb b/spec/integration/errors_spec.rb index 8084bb35a..705c1fff8 100644 --- a/spec/integration/errors_spec.rb +++ b/spec/integration/errors_spec.rb @@ -48,6 +48,8 @@ describe "When rendering errors" do it "should render a 403 for attempts at directory listing for attachments" do get("/request/5/response/4/attach/html/3/" ) response.code.should == "403" + get("/request/5/response/4/attach/html" ) + response.code.should == "403" end it "should render a 404 for non-existent 'details' pages for requests" do get("/details/request/wobble" ) diff --git a/spec/lib/tmail_extensions_spec.rb b/spec/lib/tmail_extensions_spec.rb index 6a55c34da..02ef8b82e 100644 --- a/spec/lib/tmail_extensions_spec.rb +++ b/spec/lib/tmail_extensions_spec.rb @@ -5,6 +5,11 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe "when using TMail" do + fixtures :info_requests, :incoming_messages + + before(:each) do + ActionMailer::Base.deliveries.clear + end it "should load an email with funny MIME settings" do # just send it to the holding pen diff --git a/spec/models/foi_attachment_spec.rb b/spec/models/foi_attachment_spec.rb index d8166dddc..05c4fc5fd 100644 --- a/spec/models/foi_attachment_spec.rb +++ b/spec/models/foi_attachment_spec.rb @@ -20,17 +20,17 @@ describe FoiAttachment, " when calculating due date" do attachment.display_size.should == "0K" end it "reparses the body if it disappears" do - mail_body = load_file_fixture('incoming-request-attach-attachments.email') - mail = TMail::Mail.parse(mail_body) - mail.base64_decode im = incoming_messages(:useless_incoming_message) - im.stub!(:mail).and_return(mail) - #im.extract_attachments! - attachments = im.get_attachments_for_display - FileUtils.rm attachments[0].filepath + im.extract_attachments! + main = im.get_main_body_text_part + orig_body = main.body + main.delete_cached_file! lambda { - attachments = im.get_attachments_for_display - body = attachments[0].body + im.get_main_body_text_part.body }.should_not raise_error(Errno::ENOENT) + main.delete_cached_file! + main = im.get_main_body_text_part + main.body.should == orig_body + end end diff --git a/spec/models/xapian_spec.rb b/spec/models/xapian_spec.rb index ec11c944b..ebd6b1890 100644 --- a/spec/models/xapian_spec.rb +++ b/spec/models/xapian_spec.rb @@ -63,6 +63,9 @@ describe PublicBody, " when indexing public bodies with Xapian" do xapian_object.results.size.should == 1 xapian_object.results[0][:model].should == public_bodies(:humpadink_public_body) + info_request_events(:badger_outgoing_message_event).destroy + outgoing_messages(:badger_outgoing_message).destroy + info_requests(:badger_request).destroy public_bodies(:humpadink_public_body).destroy update_xapian_index @@ -141,16 +144,16 @@ describe User, " when indexing requests by user they are from" do it "should find requests from the user" do rebuild_xapian_index xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) - xapian_object.results.size.should == 4 + xapian_object.results.size.should == 5 end it "should find just the sent message events from a particular user" do rebuild_xapian_index # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith variety:sent", 'created_at', true, nil, 100, 1) - xapian_object.results.size.should == 2 - xapian_object.results[1][:model].should == info_request_events(:useless_outgoing_message_event) - xapian_object.results[0][:model].should == info_request_events(:silly_outgoing_message_event) + xapian_object.results.size.should == 3 + xapian_object.results[2][:model].should == info_request_events(:useless_outgoing_message_event) + xapian_object.results[1][:model].should == info_request_events(:silly_outgoing_message_event) end it "should not find it when one of the request's users is changed" do @@ -164,8 +167,8 @@ describe User, " when indexing requests by user they are from" do # def InfoRequest.full_search(models, query, order, ascending, collapse, per_page, page) xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, 'request_collapse', 100, 1) - xapian_object.results.size.should == 1 - xapian_object.results[0][:model].should == info_request_events(:silly_comment_event) + xapian_object.results.size.should == 2 + xapian_object.results[1][:model].should == info_request_events(:silly_comment_event) end it "should not get confused searching for requests when one user has a name which has same stem as another" do @@ -198,7 +201,7 @@ describe User, " when indexing requests by user they are from" do # initial search rebuild_xapian_index xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) - xapian_object.results.size.should == 4 + xapian_object.results.size.should == 5 models_found_before = xapian_object.results.map { |x| x[:model] } # change the URL name of the body @@ -212,7 +215,7 @@ describe User, " when indexing requests by user they are from" do xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:bob_smith", 'created_at', true, nil, 100, 1) xapian_object.results.size.should == 0 xapian_object = InfoRequest.full_search([InfoRequestEvent], "requested_by:robert_smith", 'created_at', true, nil, 100, 1) - xapian_object.results.size.should == 4 + xapian_object.results.size.should == 5 models_found_after = xapian_object.results.map { |x| x[:model] } models_found_before.should == models_found_after diff --git a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb index 70605ad04..98ec93a14 100644 --- a/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb +++ b/vendor/plugins/acts_as_xapian/lib/acts_as_xapian.rb @@ -30,14 +30,19 @@ module ActsAsXapian class NoXapianRubyBindingsError < StandardError end - # XXX global class intializers here get loaded more than once, don't know why. Protect them. - if not $acts_as_xapian_class_var_init - @@db = nil - @@db_path = nil - @@writable_db = nil - @@init_values = [] + @@db = nil + @@db_path = nil + @@writable_db = nil + @@init_values = [] + + # There used to be a problem with this module being loaded more than once. + # Keep a check here, so we can tell if the problem recurs. + if $acts_as_xapian_class_var_init + raise "The acts_as_xapian module has already been loaded" + else $acts_as_xapian_class_var_init = true end + def ActsAsXapian.db @@db end @@ -248,6 +253,8 @@ module ActsAsXapian end end + MSET_MAX_TRIES = 5 + MSET_MAX_DELAY = 5 # Set self.query before calling this def initialize_query(options) #raise options.to_yaml @@ -278,7 +285,28 @@ module ActsAsXapian ActsAsXapian.enquire.collapse_key = value end - self.matches = ActsAsXapian.enquire.mset(offset, limit, 100) + tries = 0 + delay = 1 + begin + self.matches = ActsAsXapian.enquire.mset(offset, limit, 100) + rescue IOError => e + if e.message =~ /DatabaseModifiedError: / + # This should be a transient error, so back off and try again, up to a point + if tries > MSET_MAX_TRIES + raise "Received DatabaseModifiedError from Xapian even after retrying #{MAX_TRIES} times" + else + sleep delay + end + tries += 1 + delay *= 2 + delay = MSET_MAX_DELAY if delay > MSET_MAX_DELAY + + @@db.reopen() + retry + else + raise + end + end self.cached_results = nil } end diff --git a/vendor/plugins/acts_as_xapian/lib/tasks/xapian.rake b/vendor/plugins/acts_as_xapian/lib/tasks/xapian.rake index 470016420..c1986ce1e 100644 --- a/vendor/plugins/acts_as_xapian/lib/tasks/xapian.rake +++ b/vendor/plugins/acts_as_xapian/lib/tasks/xapian.rake @@ -2,7 +2,6 @@ require 'rubygems' require 'rake' require 'rake/testtask' require 'active_record' -require File.dirname(__FILE__) + '/../acts_as_xapian.rb' namespace :xapian do # Parameters - specify "flush=true" to save changes to the Xapian database |