Commit 72a1c96d0f7bb0345cc7f06e89942cf4b58de9f6

Authored by Rodrigo Souto
2 parents f12dd0f6 ae71aa62

Merge branch 'stable' into postgres-tests

app/models/profile.rb
@@ -298,7 +298,7 @@ class Profile < ActiveRecord::Base @@ -298,7 +298,7 @@ class Profile < ActiveRecord::Base
298 validate :valid_template 298 validate :valid_template
299 299
300 def valid_template 300 def valid_template
301 - if template_id.present? and !template.is_template 301 + if template_id.present? && template && !template.is_template
302 errors.add(:template, _('is not a template.')) 302 errors.add(:template, _('is not a template.'))
303 end 303 end
304 end 304 end
app/views/blocks/location.html.erb
1 <% if profile.lat %> 1 <% if profile.lat %>
2 <%= block_title block.title %> 2 <%= block_title block.title %>
3 <div class='the-localization-map'> 3 <div class='the-localization-map'>
4 - <img src="http://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/> 4 + <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 </div> 5 </div>
6 </div> 6 </div>
7 <% else %> 7 <% else %>
app/views/maps/edit_location.rhtml
@@ -29,5 +29,5 @@ @@ -29,5 +29,5 @@
29 29
30 <% end %> 30 <% end %>
31 31
32 -<%= content_tag('script', '', :src => "http://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %> 32 +<%= content_tag('script', '', :src => "https://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %>
33 <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %> 33 <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %>
@@ -221,7 +221,6 @@ ActiveRecord::Schema.define(:version =&gt; 20130711213046) do @@ -221,7 +221,6 @@ ActiveRecord::Schema.define(:version =&gt; 20130711213046) do
221 t.string "source_type" 221 t.string "source_type"
222 t.string "user_agent" 222 t.string "user_agent"
223 t.string "referrer" 223 t.string "referrer"
224 - t.integer "group_id"  
225 end 224 end
226 225
227 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" 226 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
debian/changelog
  1 +noosfero (0.44.3) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 14 Aug 2013 19:38:33 -0300
  6 +
1 noosfero (0.44.2) unstable; urgency=low 7 noosfero (0.44.2) unstable; urgency=low
2 8
3 * Bugfixes release 9 * Bugfixes release
lib/feed_updater.rb
@@ -19,6 +19,18 @@ end @@ -19,6 +19,18 @@ end
19 # stops the process. 19 # stops the process.
20 class FeedUpdater 20 class FeedUpdater
21 21
  22 + class ExceptionNotification < ActionMailer::Base
  23 + def mail error
  24 + environment = Environment.default
  25 +
  26 + recipients NOOSFERO_CONF['exception_recipients']
  27 + from environment.contact_email
  28 + reply_to environment.contact_email
  29 + subject "[#{environment.name}] Feed-updater: #{error.message}"
  30 + body render(:text => error.backtrace.join("\n"))
  31 + end
  32 + end
  33 +
22 # indicates how much time one feed will be left without updates 34 # indicates how much time one feed will be left without updates
23 # (ActiveSupport::Duration). Default: <tt>4.hours</tt> 35 # (ActiveSupport::Duration). Default: <tt>4.hours</tt>
24 cattr_accessor :update_interval 36 cattr_accessor :update_interval
@@ -79,6 +91,8 @@ class FeedUpdater @@ -79,6 +91,8 @@ class FeedUpdater
79 feed_handler.process(container) 91 feed_handler.process(container)
80 end 92 end
81 end 93 end
  94 + rescue Exception => e
  95 + FeedUpdater::ExceptionNotification.deliver_mail e if NOOSFERO_CONF['exception_recipients'].present?
82 end 96 end
83 end 97 end
84 98
lib/noosfero.rb
@@ -3,7 +3,7 @@ require &#39;fast_gettext&#39; @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3
4 module Noosfero 4 module Noosfero
5 PROJECT = 'noosfero' 5 PROJECT = 'noosfero'
6 - VERSION = '0.44.2' 6 + VERSION = '0.44.3'
7 7
8 def self.pattern_for_controllers_in_directory(dir) 8 def self.pattern_for_controllers_in_directory(dir)
9 disjunction = controllers_in_directory(dir).join('|') 9 disjunction = controllers_in_directory(dir).join('|')
plugins/solr/lib/solr_plugin/search_helper.rb
@@ -34,10 +34,6 @@ module SolrPlugin::SearchHelper @@ -34,10 +34,6 @@ module SolrPlugin::SearchHelper
34 ], 34 ],
35 } 35 }
36 36
37 -# def asset_class(asset)  
38 -# asset.to_s.singularize.camelize.constantize  
39 -# end  
40 -  
41 def class_asset(klass) 37 def class_asset(klass)
42 klass.name.underscore.pluralize.to_sym 38 klass.name.underscore.pluralize.to_sym
43 end 39 end
@@ -111,6 +107,8 @@ module SolrPlugin::SearchHelper @@ -111,6 +107,8 @@ module SolrPlugin::SearchHelper
111 107
112 def asset_class(asset) 108 def asset_class(asset)
113 asset.to_s.singularize.camelize.constantize 109 asset.to_s.singularize.camelize.constantize
  110 + rescue
  111 + asset.to_s.singularize.camelize.gsub('Plugin', 'Plugin::').constantize
114 end 112 end
115 113
116 def set_facets_variables 114 def set_facets_variables
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/class_methods.rb
@@ -208,7 +208,7 @@ module ActsAsSolr #:nodoc: @@ -208,7 +208,7 @@ module ActsAsSolr #:nodoc:
208 # using eager loading for indexed associations. 208 # using eager loading for indexed associations.
209 def rebuild_solr_index(batch_size=300, options = {}, &finder) 209 def rebuild_solr_index(batch_size=300, options = {}, &finder)
210 finder ||= lambda do |ar, sql_options| 210 finder ||= lambda do |ar, sql_options|
211 - ar.all sql_options.merge!({:order => self.primary_key, :include => configuration[:solr_includes].keys}) 211 + ar.all sql_options.merge!({:order => self.primary_key})
212 end 212 end
213 start_time = Time.now 213 start_time = Time.now
214 options[:offset] ||= 0 214 options[:offset] ||= 0
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/instance_methods.rb
1 module ActsAsSolr #:nodoc: 1 module ActsAsSolr #:nodoc:
2 - 2 +
3 module InstanceMethods 3 module InstanceMethods
4 4
5 # Solr id is <class.name>:<id> to be unique across all models 5 # Solr id is <class.name>:<id> to be unique across all models
@@ -10,7 +10,7 @@ module ActsAsSolr #:nodoc: @@ -10,7 +10,7 @@ module ActsAsSolr #:nodoc:
10 # saves to the Solr index 10 # saves to the Solr index
11 def solr_save 11 def solr_save
12 return true if indexing_disabled? 12 return true if indexing_disabled?
13 - if evaluate_condition(:if, self) 13 + if evaluate_condition(:if, self)
14 debug "solr_save: #{self.class.name} : #{record_id(self)}" 14 debug "solr_save: #{self.class.name} : #{record_id(self)}"
15 solr_add to_solr_doc 15 solr_add to_solr_doc
16 solr_commit if configuration[:auto_commit] 16 solr_commit if configuration[:auto_commit]
@@ -38,9 +38,9 @@ module ActsAsSolr #:nodoc: @@ -38,9 +38,9 @@ module ActsAsSolr #:nodoc:
38 debug "to_solr_doc: creating doc for class: #{self.class.name}, id: #{record_id(self)}" 38 debug "to_solr_doc: creating doc for class: #{self.class.name}, id: #{record_id(self)}"
39 doc = Solr::Document.new 39 doc = Solr::Document.new
40 doc.boost = validate_boost(configuration[:boost]) if configuration[:boost] 40 doc.boost = validate_boost(configuration[:boost]) if configuration[:boost]
41 - 41 +
42 doc << {:id => solr_id, 42 doc << {:id => solr_id,
43 - solr_configuration[:type_field] => self.class.name, 43 + solr_configuration[:type_field] => Solr::Util.query_parser_escape(self.class.name),
44 solr_configuration[:primary_key_field] => record_id(self).to_s} 44 solr_configuration[:primary_key_field] => record_id(self).to_s}
45 45
46 # iterate through the fields and add them to the document, 46 # iterate through the fields and add them to the document,
@@ -50,7 +50,7 @@ module ActsAsSolr #:nodoc: @@ -50,7 +50,7 @@ module ActsAsSolr #:nodoc:
50 field_boost = options[:boost] || solr_configuration[:default_boost] 50 field_boost = options[:boost] || solr_configuration[:default_boost]
51 field_type = get_solr_field_type(options[:type]) 51 field_type = get_solr_field_type(options[:type])
52 solr_name = options[:as] || field_name 52 solr_name = options[:as] || field_name
53 - 53 +
54 value = self.send("#{field_name}_for_solr") rescue nil 54 value = self.send("#{field_name}_for_solr") rescue nil
55 next if value.nil? 55 next if value.nil?
56 56
@@ -63,18 +63,18 @@ module ActsAsSolr #:nodoc: @@ -63,18 +63,18 @@ module ActsAsSolr #:nodoc:
63 field.boost = processed_boost 63 field.boost = processed_boost
64 doc << field 64 doc << field
65 end 65 end
66 - 66 +
67 add_dynamic_attributes(doc) 67 add_dynamic_attributes(doc)
68 add_includes(doc) 68 add_includes(doc)
69 add_tags(doc) 69 add_tags(doc)
70 add_space(doc) 70 add_space(doc)
71 - 71 +
72 debug doc.to_json 72 debug doc.to_json
73 doc 73 doc
74 end 74 end
75 75
76 private 76 private
77 - 77 +
78 def debug(text) 78 def debug(text)
79 logger.debug text rescue nil 79 logger.debug text rescue nil
80 end 80 end
@@ -85,14 +85,14 @@ module ActsAsSolr #:nodoc: @@ -85,14 +85,14 @@ module ActsAsSolr #:nodoc:
85 doc << Solr::Field.new(:name => "lng_f", :value => local.longitude) 85 doc << Solr::Field.new(:name => "lng_f", :value => local.longitude)
86 end 86 end
87 end 87 end
88 - 88 +
89 def add_tags(doc) 89 def add_tags(doc)
90 taggings.each do |tagging| 90 taggings.each do |tagging|
91 doc << Solr::Field.new(:name => "tag_facet", :value => tagging.tag.name) 91 doc << Solr::Field.new(:name => "tag_facet", :value => tagging.tag.name)
92 doc << Solr::Field.new(:name => "tag_t", :value => tagging.tag.name) 92 doc << Solr::Field.new(:name => "tag_t", :value => tagging.tag.name)
93 end if configuration[:taggable] 93 end if configuration[:taggable]
94 end 94 end
95 - 95 +
96 def add_dynamic_attributes(doc) 96 def add_dynamic_attributes(doc)
97 dynamic_attributes.each do |attribute| 97 dynamic_attributes.each do |attribute|
98 value = ERB::Util.html_escape(attribute.value) 98 value = ERB::Util.html_escape(attribute.value)
@@ -130,7 +130,7 @@ module ActsAsSolr #:nodoc: @@ -130,7 +130,7 @@ module ActsAsSolr #:nodoc:
130 end 130 end
131 end 131 end
132 end 132 end
133 - 133 +
134 def include_value(record, options) 134 def include_value(record, options)
135 if options[:using].is_a? Proc 135 if options[:using].is_a? Proc
136 options[:using].call(record) 136 options[:using].call(record)
@@ -159,14 +159,14 @@ module ActsAsSolr #:nodoc: @@ -159,14 +159,14 @@ module ActsAsSolr #:nodoc:
159 self.send(boost) 159 self.send(boost)
160 end 160 end
161 end 161 end
162 - 162 +
163 boost_value || solr_configuration[:default_boost] 163 boost_value || solr_configuration[:default_boost]
164 end 164 end
165 - 165 +
166 def condition_block?(condition) 166 def condition_block?(condition)
167 condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1) 167 condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1)
168 end 168 end
169 - 169 +
170 def evaluate_condition(which_condition, field) 170 def evaluate_condition(which_condition, field)
171 condition = configuration[which_condition] 171 condition = configuration[which_condition]
172 case condition 172 case condition
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/parser_methods.rb
@@ -127,7 +127,7 @@ module ActsAsSolr #:nodoc: @@ -127,7 +127,7 @@ module ActsAsSolr #:nodoc:
127 classes = [self] + (self.subclasses || []) + (options[:models] || []) 127 classes = [self] + (self.subclasses || []) + (options[:models] || [])
128 classes.map do |klass| 128 classes.map do |klass|
129 next if klass.name.empty? 129 next if klass.name.empty?
130 - "#{solr_configuration[:type_field]}:\"#{klass.name}\"" 130 + "#{solr_configuration[:type_field]}:\"#{Solr::Util.query_parser_escape klass.name}\""
131 end.compact.join(' OR ') 131 end.compact.join(' OR ')
132 end 132 end
133 133
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/select.rb
@@ -12,22 +12,22 @@ @@ -12,22 +12,22 @@
12 12
13 # "Abstract" base class, only useful with subclasses that add parameters 13 # "Abstract" base class, only useful with subclasses that add parameters
14 class Solr::Request::Select < Solr::Request::Base 14 class Solr::Request::Select < Solr::Request::Base
15 - 15 +
16 attr_reader :query_type 16 attr_reader :query_type
17 - 17 +
18 def initialize(qt=nil, params={}) 18 def initialize(qt=nil, params={})
19 @query_type = qt 19 @query_type = qt
20 @select_params = params 20 @select_params = params
21 end 21 end
22 - 22 +
23 def response_format 23 def response_format
24 :ruby 24 :ruby
25 end 25 end
26 - 26 +
27 def handler 27 def handler
28 'select' 28 'select'
29 end 29 end
30 - 30 +
31 def content_type 31 def content_type
32 'application/x-www-form-urlencoded; charset=utf-8' 32 'application/x-www-form-urlencoded; charset=utf-8'
33 end 33 end
@@ -35,7 +35,7 @@ class Solr::Request::Select &lt; Solr::Request::Base @@ -35,7 +35,7 @@ class Solr::Request::Select &lt; Solr::Request::Base
35 def to_hash 35 def to_hash
36 return {:qt => query_type, :wt => 'ruby', 'json.nl' => 'arrarr'}.merge(@select_params) 36 return {:qt => query_type, :wt => 'ruby', 'json.nl' => 'arrarr'}.merge(@select_params)
37 end 37 end
38 - 38 +
39 def to_s 39 def to_s
40 raw_params = self.to_hash 40 raw_params = self.to_hash
41 41
@@ -50,5 +50,5 @@ class Solr::Request::Select &lt; Solr::Request::Base @@ -50,5 +50,5 @@ class Solr::Request::Select &lt; Solr::Request::Base
50 50
51 http_params.join("&") 51 http_params.join("&")
52 end 52 end
53 - 53 +
54 end 54 end
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/solr.rake
1 namespace :solr do 1 namespace :solr do
2 2
3 - APACHE_MIRROR = ENV['APACHE_MIRROR'] || "http://ftp.unicamp.br/pub/apache" 3 + APACHE_MIRROR = ENV['APACHE_MIRROR'] || "https://archive.apache.org/dist"
4 SOLR_VERSION = '3.6.2' 4 SOLR_VERSION = '3.6.2'
5 SOLR_FILENAME = "apache-solr-#{SOLR_VERSION}.tgz" 5 SOLR_FILENAME = "apache-solr-#{SOLR_VERSION}.tgz"
6 SOLR_MD5SUM = 'e9c51f51265b070062a9d8ed50b84647' 6 SOLR_MD5SUM = 'e9c51f51265b070062a9d8ed50b84647'
@@ -177,7 +177,7 @@ namespace :solr do @@ -177,7 +177,7 @@ namespace :solr do
177 models.each do |model| 177 models.each do |model|
178 if clear_first 178 if clear_first
179 puts "Clearing index for #{model}..." 179 puts "Clearing index for #{model}..."
180 - ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "#{model.solr_configuration[:type_field]}:#{Solr::Util.query_parser_escape(model.name)}")) 180 + ActsAsSolr::Post.execute(Solr::Request::Delete.new(:query => "#{model.solr_configuration[:type_field]}:#{model.name.gsub ':', "\\:"}"))
181 ActsAsSolr::Post.execute(Solr::Request::Commit.new) 181 ActsAsSolr::Post.execute(Solr::Request::Commit.new)
182 end 182 end
183 183
public/500.html
@@ -55,13 +55,13 @@ @@ -55,13 +55,13 @@
55 55
56 56
57 <div id='es' style='display: none' class='message'> 57 <div id='es' style='display: none' class='message'>
58 - <h1>Temporary system problem</h1> 58 + <h1>Problema temporal del sistema</h1>
59 <p> 59 <p>
60 - Our technical team is working on it, please try again later. Sorry for the inconvenience. 60 + Nuestro equipo técnico está trabajando en ello, por favor, inténtalo de nuevo más tarde. Disculpa las molestias.
61 </p> 61 </p>
62 <ul> 62 <ul>
63 - <li><a href='javascript: history.back()'>Go back</a></li>  
64 - <li><a href='/'>Go to the site home page</a></li> 63 + <li><a href='javascript: history.back()'>Regresar</a></li>
  64 + <li><a href='/'>Ir a la página de inicio del sitio</a></li>
65 </ul> 65 </ul>
66 </div> 66 </div>
67 67
@@ -90,6 +90,18 @@ @@ -90,6 +90,18 @@
90 </div> 90 </div>
91 91
92 92
  93 + <div id='it' style='display: none' class='message'>
  94 + <h1>Temporary system problem</h1>
  95 + <p>
  96 + Our technical team is working on it, please try again later. Sorry for the inconvenience.
  97 + </p>
  98 + <ul>
  99 + <li><a href='javascript: history.back()'>Go back</a></li>
  100 + <li><a href='/'>Go to the site home page</a></li>
  101 + </ul>
  102 + </div>
  103 +
  104 +
93 <div id='pt' style='display: none' class='message'> 105 <div id='pt' style='display: none' class='message'>
94 <h1>Problema temporário no sistema</h1> 106 <h1>Problema temporário no sistema</h1>
95 <p> 107 <p>
@@ -127,6 +139,8 @@ @@ -127,6 +139,8 @@
127 139
128 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> 140 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a>
129 141
  142 + <a href="javascript: display_error_message('it')">Italiano</a>
  143 +
130 <a href="javascript: display_error_message('pt')">Português</a> 144 <a href="javascript: display_error_message('pt')">Português</a>
131 145
132 <a href="javascript: display_error_message('ru')">русский язык</a> 146 <a href="javascript: display_error_message('ru')">русский язык</a>
public/503.html
@@ -43,9 +43,9 @@ @@ -43,9 +43,9 @@
43 43
44 44
45 <div id='es' style='display: none' class='message'> 45 <div id='es' style='display: none' class='message'>
46 - <h1>System maintainance</h1> 46 + <h1>Mantenimeinto del sistema</h1>
47 <p> 47 <p>
48 - This system is under maintainance. It should be back in a few moments. 48 + Este sistema está en mantenimiento. Debería regresar en unos momentos.
49 </p> 49 </p>
50 </div> 50 </div>
51 51
@@ -66,6 +66,14 @@ @@ -66,6 +66,14 @@
66 </div> 66 </div>
67 67
68 68
  69 + <div id='it' style='display: none' class='message'>
  70 + <h1>System maintainance</h1>
  71 + <p>
  72 + This system is under maintainance. It should be back in a few moments.
  73 + </p>
  74 + </div>
  75 +
  76 +
69 <div id='pt' style='display: none' class='message'> 77 <div id='pt' style='display: none' class='message'>
70 <h1>Manutenção do sistema</h1> 78 <h1>Manutenção do sistema</h1>
71 <p> 79 <p>
@@ -95,6 +103,8 @@ @@ -95,6 +103,8 @@
95 103
96 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> 104 <a href="javascript: display_error_message('hy')">հայերեն լեզու</a>
97 105
  106 + <a href="javascript: display_error_message('it')">Italiano</a>
  107 +
98 <a href="javascript: display_error_message('pt')">Português</a> 108 <a href="javascript: display_error_message('pt')">Português</a>
99 109
100 <a href="javascript: display_error_message('ru')">русский язык</a> 110 <a href="javascript: display_error_message('ru')">русский язык</a>
test/unit/location_block_test.rb
@@ -29,11 +29,11 @@ class LocationBlockTest &lt; ActiveSupport::TestCase @@ -29,11 +29,11 @@ class LocationBlockTest &lt; ActiveSupport::TestCase
29 assert_equal '', LocationBlock.new.title 29 assert_equal '', LocationBlock.new.title
30 end 30 end
31 31
32 - should 'use google maps api v3' do 32 + should 'use google maps api v3 with ssl' do
33 @block.owner.lat = '-12.34'; @block.owner.save! 33 @block.owner.lat = '-12.34'; @block.owner.save!
34 content = extract_block_content(@block.content) 34 content = extract_block_content(@block.content)
35 35
36 - assert_match 'http://maps.google.com/maps/api/staticmap', content 36 + assert_match 'https://maps.google.com/maps/api/staticmap', content
37 assert_no_match /key=/, content 37 assert_no_match /key=/, content
38 end 38 end
39 39
test/unit/profile_test.rb
@@ -1379,6 +1379,16 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1379,6 +1379,16 @@ class ProfileTest &lt; ActiveSupport::TestCase
1379 assert_not_includes Profile.templates(Environment.default), profile 1379 assert_not_includes Profile.templates(Environment.default), profile
1380 end 1380 end
1381 1381
  1382 + should 'not crash on a profile update with a destroyed template' do
  1383 + template = fast_create(Profile, :is_template => true)
  1384 + profile = fast_create(Profile, :template_id => template.id)
  1385 + template.destroy
  1386 +
  1387 + assert_nothing_raised do
  1388 + Profile.find(profile.id).save!
  1389 + end
  1390 + end
  1391 +
1382 should 'provide URL to leave' do 1392 should 'provide URL to leave' do
1383 profile = build(Profile, :identifier => 'testprofile') 1393 profile = build(Profile, :identifier => 'testprofile')
1384 assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => false}, profile.leave_url) 1394 assert_equal({ :profile => 'testprofile', :controller => 'profile', :action => 'leave', :reload => false}, profile.leave_url)
vendor/plugins/delayed_job/lib/delayed/worker.rb
@@ -10,12 +10,12 @@ module Delayed @@ -10,12 +10,12 @@ module Delayed
10 self.max_attempts = 25 10 self.max_attempts = 25
11 self.max_run_time = 4.hours 11 self.max_run_time = 4.hours
12 self.default_priority = 0 12 self.default_priority = 0
13 - 13 +
14 # By default failed jobs are destroyed after too many attempts. If you want to keep them around 14 # By default failed jobs are destroyed after too many attempts. If you want to keep them around
15 # (perhaps to inspect the reason for the failure), set this to false. 15 # (perhaps to inspect the reason for the failure), set this to false.
16 cattr_accessor :destroy_failed_jobs 16 cattr_accessor :destroy_failed_jobs
17 self.destroy_failed_jobs = true 17 self.destroy_failed_jobs = true
18 - 18 +
19 self.logger = if defined?(Merb::Logger) 19 self.logger = if defined?(Merb::Logger)
20 Merb.logger 20 Merb.logger
21 elsif defined?(RAILS_DEFAULT_LOGGER) 21 elsif defined?(RAILS_DEFAULT_LOGGER)
@@ -24,9 +24,9 @@ module Delayed @@ -24,9 +24,9 @@ module Delayed
24 24
25 # name_prefix is ignored if name is set directly 25 # name_prefix is ignored if name is set directly
26 attr_accessor :name_prefix 26 attr_accessor :name_prefix
27 - 27 +
28 cattr_reader :backend 28 cattr_reader :backend
29 - 29 +
30 def self.backend=(backend) 30 def self.backend=(backend)
31 if backend.is_a? Symbol 31 if backend.is_a? Symbol
32 require "delayed/backend/#{backend}" 32 require "delayed/backend/#{backend}"
@@ -35,7 +35,7 @@ module Delayed @@ -35,7 +35,7 @@ module Delayed
35 @@backend = backend 35 @@backend = backend
36 silence_warnings { ::Delayed.const_set(:Job, backend) } 36 silence_warnings { ::Delayed.const_set(:Job, backend) }
37 end 37 end
38 - 38 +
39 def self.guess_backend 39 def self.guess_backend
40 self.backend ||= if defined?(ActiveRecord) 40 self.backend ||= if defined?(ActiveRecord)
41 :active_record 41 :active_record
@@ -97,7 +97,7 @@ module Delayed @@ -97,7 +97,7 @@ module Delayed
97 ensure 97 ensure
98 Delayed::Job.clear_locks!(name) 98 Delayed::Job.clear_locks!(name)
99 end 99 end
100 - 100 +
101 # Do num jobs and return stats on success/failure. 101 # Do num jobs and return stats on success/failure.
102 # Exit early if interrupted. 102 # Exit early if interrupted.
103 def work_off(num = 100) 103 def work_off(num = 100)
@@ -117,7 +117,7 @@ module Delayed @@ -117,7 +117,7 @@ module Delayed
117 117
118 return [success, failure] 118 return [success, failure]
119 end 119 end
120 - 120 +
121 def run(job) 121 def run(job)
122 runtime = Benchmark.realtime do 122 runtime = Benchmark.realtime do
123 Timeout.timeout(self.class.max_run_time.to_i) { job.invoke_job } 123 Timeout.timeout(self.class.max_run_time.to_i) { job.invoke_job }
@@ -129,7 +129,7 @@ module Delayed @@ -129,7 +129,7 @@ module Delayed
129 handle_failed_job(job, e) 129 handle_failed_job(job, e)
130 return false # work failed 130 return false # work failed
131 end 131 end
132 - 132 +
133 # Reschedule the job in the future (when a job fails). 133 # Reschedule the job in the future (when a job fails).
134 # Uses an exponential scale depending on the number of failed attempts. 134 # Uses an exponential scale depending on the number of failed attempts.
135 def reschedule(job, time = nil) 135 def reschedule(job, time = nil)
@@ -162,13 +162,13 @@ module Delayed @@ -162,13 +162,13 @@ module Delayed
162 end 162 end
163 163
164 protected 164 protected
165 - 165 +
166 def handle_failed_job(job, error) 166 def handle_failed_job(job, error)
167 job.last_error = error.message + "\n" + error.backtrace.join("\n") 167 job.last_error = error.message + "\n" + error.backtrace.join("\n")
168 say "#{job.name} failed with #{error.class.name}: #{error.message} - #{job.attempts} failed attempts", Logger::ERROR 168 say "#{job.name} failed with #{error.class.name}: #{error.message} - #{job.attempts} failed attempts", Logger::ERROR
169 reschedule(job) 169 reschedule(job)
170 end 170 end
171 - 171 +
172 # Run the next job we can get an exclusive lock on. 172 # Run the next job we can get an exclusive lock on.
173 # If no jobs are left we return nil 173 # If no jobs are left we return nil
174 def reserve_and_run_one_job 174 def reserve_and_run_one_job
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb 0 → 100644
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +Delayed::Worker.module_eval do
  2 + # based on https://groups.google.com/forum/#!topic/delayed_job/ZGMUFFppNgs
  3 + class Delayed::Worker::ExceptionNotification < ActionMailer::Base
  4 + def mail error
  5 + environment = Environment.default
  6 +
  7 + recipients NOOSFERO_CONF['exception_recipients']
  8 + from environment.contact_email
  9 + reply_to environment.contact_email
  10 + subject "[#{environment.name}] DelayedJob: #{error.message}"
  11 + body render(:text => error.backtrace.join("\n"))
  12 + end
  13 + end
  14 +
  15 + def handle_failed_job_with_notification(job, error)
  16 + Delayed::Worker::ExceptionNotification.deliver_mail error if NOOSFERO_CONF['exception_recipients'].present?
  17 + handle_failed_job_without_notification job, error
  18 + end
  19 + alias_method_chain :handle_failed_job, :notification
  20 +
  21 + def handle_failed_job_with_rescue(job, error)
  22 + handle_failed_job_without_rescue(job, error)
  23 + rescue => e # don't crash here
  24 + end
  25 + alias_method_chain :handle_failed_job, :rescue
  26 +
  27 + protected
  28 +
  29 + # This code must be replicated because there is no other way to pass the job
  30 + # through and use alias_method_chain as we used on the previous method
  31 + def reserve_and_run_one_job
  32 + # We get up to 5 jobs from the db. In case we cannot get exclusive access to a job we try the next.
  33 + # this leads to a more even distribution of jobs across the worker processes
  34 + job = Delayed::Job.find_available(name, 5, self.class.max_run_time).detect do |job|
  35 + if job.lock_exclusively!(self.class.max_run_time, name)
  36 + say "acquired lock on #{job.name}"
  37 + true
  38 + else
  39 + say "failed to acquire exclusive lock for #{job.name}", Logger::WARN
  40 + false
  41 + end
  42 + end
  43 +
  44 + run(job) if job
  45 + rescue => e
  46 + handle_failed_job(job, e)
  47 + end
  48 +end