Commit 72a1c96d0f7bb0345cc7f06e89942cf4b58de9f6
Exists in
master
and in
29 other branches
Merge branch 'stable' into postgres-tests
Showing
19 changed files
with
151 additions
and
52 deletions
Show diff stats
app/models/profile.rb
... | ... | @@ -298,7 +298,7 @@ class Profile < ActiveRecord::Base |
298 | 298 | validate :valid_template |
299 | 299 | |
300 | 300 | def valid_template |
301 | - if template_id.present? and !template.is_template | |
301 | + if template_id.present? && template && !template.is_template | |
302 | 302 | errors.add(:template, _('is not a template.')) |
303 | 303 | end |
304 | 304 | end | ... | ... |
app/views/blocks/location.html.erb
1 | 1 | <% if profile.lat %> |
2 | 2 | <%= block_title block.title %> |
3 | 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 | 5 | </div> |
6 | 6 | </div> |
7 | 7 | <% else %> | ... | ... |
app/views/maps/edit_location.rhtml
... | ... | @@ -29,5 +29,5 @@ |
29 | 29 | |
30 | 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 | 33 | <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %> | ... | ... |
db/schema.rb
... | ... | @@ -221,7 +221,6 @@ ActiveRecord::Schema.define(:version => 20130711213046) do |
221 | 221 | t.string "source_type" |
222 | 222 | t.string "user_agent" |
223 | 223 | t.string "referrer" |
224 | - t.integer "group_id" | |
225 | 224 | end |
226 | 225 | |
227 | 226 | add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" | ... | ... |
debian/changelog
lib/feed_updater.rb
... | ... | @@ -19,6 +19,18 @@ end |
19 | 19 | # stops the process. |
20 | 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 | 34 | # indicates how much time one feed will be left without updates |
23 | 35 | # (ActiveSupport::Duration). Default: <tt>4.hours</tt> |
24 | 36 | cattr_accessor :update_interval |
... | ... | @@ -79,6 +91,8 @@ class FeedUpdater |
79 | 91 | feed_handler.process(container) |
80 | 92 | end |
81 | 93 | end |
94 | + rescue Exception => e | |
95 | + FeedUpdater::ExceptionNotification.deliver_mail e if NOOSFERO_CONF['exception_recipients'].present? | |
82 | 96 | end |
83 | 97 | end |
84 | 98 | ... | ... |
lib/noosfero.rb
plugins/solr/lib/solr_plugin/search_helper.rb
... | ... | @@ -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 | 37 | def class_asset(klass) |
42 | 38 | klass.name.underscore.pluralize.to_sym |
43 | 39 | end |
... | ... | @@ -111,6 +107,8 @@ module SolrPlugin::SearchHelper |
111 | 107 | |
112 | 108 | def asset_class(asset) |
113 | 109 | asset.to_s.singularize.camelize.constantize |
110 | + rescue | |
111 | + asset.to_s.singularize.camelize.gsub('Plugin', 'Plugin::').constantize | |
114 | 112 | end |
115 | 113 | |
116 | 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 | 208 | # using eager loading for indexed associations. |
209 | 209 | def rebuild_solr_index(batch_size=300, options = {}, &finder) |
210 | 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 | 212 | end |
213 | 213 | start_time = Time.now |
214 | 214 | options[:offset] ||= 0 | ... | ... |
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/acts_as_solr/instance_methods.rb
1 | 1 | module ActsAsSolr #:nodoc: |
2 | - | |
2 | + | |
3 | 3 | module InstanceMethods |
4 | 4 | |
5 | 5 | # Solr id is <class.name>:<id> to be unique across all models |
... | ... | @@ -10,7 +10,7 @@ module ActsAsSolr #:nodoc: |
10 | 10 | # saves to the Solr index |
11 | 11 | def solr_save |
12 | 12 | return true if indexing_disabled? |
13 | - if evaluate_condition(:if, self) | |
13 | + if evaluate_condition(:if, self) | |
14 | 14 | debug "solr_save: #{self.class.name} : #{record_id(self)}" |
15 | 15 | solr_add to_solr_doc |
16 | 16 | solr_commit if configuration[:auto_commit] |
... | ... | @@ -38,9 +38,9 @@ module ActsAsSolr #:nodoc: |
38 | 38 | debug "to_solr_doc: creating doc for class: #{self.class.name}, id: #{record_id(self)}" |
39 | 39 | doc = Solr::Document.new |
40 | 40 | doc.boost = validate_boost(configuration[:boost]) if configuration[:boost] |
41 | - | |
41 | + | |
42 | 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 | 44 | solr_configuration[:primary_key_field] => record_id(self).to_s} |
45 | 45 | |
46 | 46 | # iterate through the fields and add them to the document, |
... | ... | @@ -50,7 +50,7 @@ module ActsAsSolr #:nodoc: |
50 | 50 | field_boost = options[:boost] || solr_configuration[:default_boost] |
51 | 51 | field_type = get_solr_field_type(options[:type]) |
52 | 52 | solr_name = options[:as] || field_name |
53 | - | |
53 | + | |
54 | 54 | value = self.send("#{field_name}_for_solr") rescue nil |
55 | 55 | next if value.nil? |
56 | 56 | |
... | ... | @@ -63,18 +63,18 @@ module ActsAsSolr #:nodoc: |
63 | 63 | field.boost = processed_boost |
64 | 64 | doc << field |
65 | 65 | end |
66 | - | |
66 | + | |
67 | 67 | add_dynamic_attributes(doc) |
68 | 68 | add_includes(doc) |
69 | 69 | add_tags(doc) |
70 | 70 | add_space(doc) |
71 | - | |
71 | + | |
72 | 72 | debug doc.to_json |
73 | 73 | doc |
74 | 74 | end |
75 | 75 | |
76 | 76 | private |
77 | - | |
77 | + | |
78 | 78 | def debug(text) |
79 | 79 | logger.debug text rescue nil |
80 | 80 | end |
... | ... | @@ -85,14 +85,14 @@ module ActsAsSolr #:nodoc: |
85 | 85 | doc << Solr::Field.new(:name => "lng_f", :value => local.longitude) |
86 | 86 | end |
87 | 87 | end |
88 | - | |
88 | + | |
89 | 89 | def add_tags(doc) |
90 | 90 | taggings.each do |tagging| |
91 | 91 | doc << Solr::Field.new(:name => "tag_facet", :value => tagging.tag.name) |
92 | 92 | doc << Solr::Field.new(:name => "tag_t", :value => tagging.tag.name) |
93 | 93 | end if configuration[:taggable] |
94 | 94 | end |
95 | - | |
95 | + | |
96 | 96 | def add_dynamic_attributes(doc) |
97 | 97 | dynamic_attributes.each do |attribute| |
98 | 98 | value = ERB::Util.html_escape(attribute.value) |
... | ... | @@ -130,7 +130,7 @@ module ActsAsSolr #:nodoc: |
130 | 130 | end |
131 | 131 | end |
132 | 132 | end |
133 | - | |
133 | + | |
134 | 134 | def include_value(record, options) |
135 | 135 | if options[:using].is_a? Proc |
136 | 136 | options[:using].call(record) |
... | ... | @@ -159,14 +159,14 @@ module ActsAsSolr #:nodoc: |
159 | 159 | self.send(boost) |
160 | 160 | end |
161 | 161 | end |
162 | - | |
162 | + | |
163 | 163 | boost_value || solr_configuration[:default_boost] |
164 | 164 | end |
165 | - | |
165 | + | |
166 | 166 | def condition_block?(condition) |
167 | 167 | condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1) |
168 | 168 | end |
169 | - | |
169 | + | |
170 | 170 | def evaluate_condition(which_condition, field) |
171 | 171 | condition = configuration[which_condition] |
172 | 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 | 127 | classes = [self] + (self.subclasses || []) + (options[:models] || []) |
128 | 128 | classes.map do |klass| |
129 | 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 | 131 | end.compact.join(' OR ') |
132 | 132 | end |
133 | 133 | ... | ... |
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/solr/request/select.rb
... | ... | @@ -12,22 +12,22 @@ |
12 | 12 | |
13 | 13 | # "Abstract" base class, only useful with subclasses that add parameters |
14 | 14 | class Solr::Request::Select < Solr::Request::Base |
15 | - | |
15 | + | |
16 | 16 | attr_reader :query_type |
17 | - | |
17 | + | |
18 | 18 | def initialize(qt=nil, params={}) |
19 | 19 | @query_type = qt |
20 | 20 | @select_params = params |
21 | 21 | end |
22 | - | |
22 | + | |
23 | 23 | def response_format |
24 | 24 | :ruby |
25 | 25 | end |
26 | - | |
26 | + | |
27 | 27 | def handler |
28 | 28 | 'select' |
29 | 29 | end |
30 | - | |
30 | + | |
31 | 31 | def content_type |
32 | 32 | 'application/x-www-form-urlencoded; charset=utf-8' |
33 | 33 | end |
... | ... | @@ -35,7 +35,7 @@ class Solr::Request::Select < Solr::Request::Base |
35 | 35 | def to_hash |
36 | 36 | return {:qt => query_type, :wt => 'ruby', 'json.nl' => 'arrarr'}.merge(@select_params) |
37 | 37 | end |
38 | - | |
38 | + | |
39 | 39 | def to_s |
40 | 40 | raw_params = self.to_hash |
41 | 41 | |
... | ... | @@ -50,5 +50,5 @@ class Solr::Request::Select < Solr::Request::Base |
50 | 50 | |
51 | 51 | http_params.join("&") |
52 | 52 | end |
53 | - | |
53 | + | |
54 | 54 | end | ... | ... |
plugins/solr/vendor/plugins/acts_as_solr_reloaded/lib/tasks/solr.rake
1 | 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 | 4 | SOLR_VERSION = '3.6.2' |
5 | 5 | SOLR_FILENAME = "apache-solr-#{SOLR_VERSION}.tgz" |
6 | 6 | SOLR_MD5SUM = 'e9c51f51265b070062a9d8ed50b84647' |
... | ... | @@ -177,7 +177,7 @@ namespace :solr do |
177 | 177 | models.each do |model| |
178 | 178 | if clear_first |
179 | 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 | 181 | ActsAsSolr::Post.execute(Solr::Request::Commit.new) |
182 | 182 | end |
183 | 183 | ... | ... |
public/500.html
... | ... | @@ -55,13 +55,13 @@ |
55 | 55 | |
56 | 56 | |
57 | 57 | <div id='es' style='display: none' class='message'> |
58 | - <h1>Temporary system problem</h1> | |
58 | + <h1>Problema temporal del sistema</h1> | |
59 | 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 | 61 | </p> |
62 | 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 | 65 | </ul> |
66 | 66 | </div> |
67 | 67 | |
... | ... | @@ -90,6 +90,18 @@ |
90 | 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 | 105 | <div id='pt' style='display: none' class='message'> |
94 | 106 | <h1>Problema temporário no sistema</h1> |
95 | 107 | <p> |
... | ... | @@ -127,6 +139,8 @@ |
127 | 139 | |
128 | 140 | <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> |
129 | 141 | |
142 | + <a href="javascript: display_error_message('it')">Italiano</a> | |
143 | + | |
130 | 144 | <a href="javascript: display_error_message('pt')">Português</a> |
131 | 145 | |
132 | 146 | <a href="javascript: display_error_message('ru')">русский язык</a> | ... | ... |
public/503.html
... | ... | @@ -43,9 +43,9 @@ |
43 | 43 | |
44 | 44 | |
45 | 45 | <div id='es' style='display: none' class='message'> |
46 | - <h1>System maintainance</h1> | |
46 | + <h1>Mantenimeinto del sistema</h1> | |
47 | 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 | 49 | </p> |
50 | 50 | </div> |
51 | 51 | |
... | ... | @@ -66,6 +66,14 @@ |
66 | 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 | 77 | <div id='pt' style='display: none' class='message'> |
70 | 78 | <h1>Manutenção do sistema</h1> |
71 | 79 | <p> |
... | ... | @@ -95,6 +103,8 @@ |
95 | 103 | |
96 | 104 | <a href="javascript: display_error_message('hy')">հայերեն լեզու</a> |
97 | 105 | |
106 | + <a href="javascript: display_error_message('it')">Italiano</a> | |
107 | + | |
98 | 108 | <a href="javascript: display_error_message('pt')">Português</a> |
99 | 109 | |
100 | 110 | <a href="javascript: display_error_message('ru')">русский язык</a> | ... | ... |
test/unit/location_block_test.rb
... | ... | @@ -29,11 +29,11 @@ class LocationBlockTest < ActiveSupport::TestCase |
29 | 29 | assert_equal '', LocationBlock.new.title |
30 | 30 | end |
31 | 31 | |
32 | - should 'use google maps api v3' do | |
32 | + should 'use google maps api v3 with ssl' do | |
33 | 33 | @block.owner.lat = '-12.34'; @block.owner.save! |
34 | 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 | 37 | assert_no_match /key=/, content |
38 | 38 | end |
39 | 39 | ... | ... |
test/unit/profile_test.rb
... | ... | @@ -1379,6 +1379,16 @@ class ProfileTest < ActiveSupport::TestCase |
1379 | 1379 | assert_not_includes Profile.templates(Environment.default), profile |
1380 | 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 | 1392 | should 'provide URL to leave' do |
1383 | 1393 | profile = build(Profile, :identifier => 'testprofile') |
1384 | 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 | 10 | self.max_attempts = 25 |
11 | 11 | self.max_run_time = 4.hours |
12 | 12 | self.default_priority = 0 |
13 | - | |
13 | + | |
14 | 14 | # By default failed jobs are destroyed after too many attempts. If you want to keep them around |
15 | 15 | # (perhaps to inspect the reason for the failure), set this to false. |
16 | 16 | cattr_accessor :destroy_failed_jobs |
17 | 17 | self.destroy_failed_jobs = true |
18 | - | |
18 | + | |
19 | 19 | self.logger = if defined?(Merb::Logger) |
20 | 20 | Merb.logger |
21 | 21 | elsif defined?(RAILS_DEFAULT_LOGGER) |
... | ... | @@ -24,9 +24,9 @@ module Delayed |
24 | 24 | |
25 | 25 | # name_prefix is ignored if name is set directly |
26 | 26 | attr_accessor :name_prefix |
27 | - | |
27 | + | |
28 | 28 | cattr_reader :backend |
29 | - | |
29 | + | |
30 | 30 | def self.backend=(backend) |
31 | 31 | if backend.is_a? Symbol |
32 | 32 | require "delayed/backend/#{backend}" |
... | ... | @@ -35,7 +35,7 @@ module Delayed |
35 | 35 | @@backend = backend |
36 | 36 | silence_warnings { ::Delayed.const_set(:Job, backend) } |
37 | 37 | end |
38 | - | |
38 | + | |
39 | 39 | def self.guess_backend |
40 | 40 | self.backend ||= if defined?(ActiveRecord) |
41 | 41 | :active_record |
... | ... | @@ -97,7 +97,7 @@ module Delayed |
97 | 97 | ensure |
98 | 98 | Delayed::Job.clear_locks!(name) |
99 | 99 | end |
100 | - | |
100 | + | |
101 | 101 | # Do num jobs and return stats on success/failure. |
102 | 102 | # Exit early if interrupted. |
103 | 103 | def work_off(num = 100) |
... | ... | @@ -117,7 +117,7 @@ module Delayed |
117 | 117 | |
118 | 118 | return [success, failure] |
119 | 119 | end |
120 | - | |
120 | + | |
121 | 121 | def run(job) |
122 | 122 | runtime = Benchmark.realtime do |
123 | 123 | Timeout.timeout(self.class.max_run_time.to_i) { job.invoke_job } |
... | ... | @@ -129,7 +129,7 @@ module Delayed |
129 | 129 | handle_failed_job(job, e) |
130 | 130 | return false # work failed |
131 | 131 | end |
132 | - | |
132 | + | |
133 | 133 | # Reschedule the job in the future (when a job fails). |
134 | 134 | # Uses an exponential scale depending on the number of failed attempts. |
135 | 135 | def reschedule(job, time = nil) |
... | ... | @@ -162,13 +162,13 @@ module Delayed |
162 | 162 | end |
163 | 163 | |
164 | 164 | protected |
165 | - | |
165 | + | |
166 | 166 | def handle_failed_job(job, error) |
167 | 167 | job.last_error = error.message + "\n" + error.backtrace.join("\n") |
168 | 168 | say "#{job.name} failed with #{error.class.name}: #{error.message} - #{job.attempts} failed attempts", Logger::ERROR |
169 | 169 | reschedule(job) |
170 | 170 | end |
171 | - | |
171 | + | |
172 | 172 | # Run the next job we can get an exclusive lock on. |
173 | 173 | # If no jobs are left we return nil |
174 | 174 | def reserve_and_run_one_job | ... | ... |
vendor/plugins/monkey_patches/rescue_delayed_job_crashes/init.rb
0 → 100644
... | ... | @@ -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 | ... | ... |