Module: NdrWorkflow::EActionProgress
- Included in:
- EAction
- Defined in:
- lib/ndr_workflow/e_action_progress.rb
Overview
Logic to be shared by EAction and QueuedJob:
Constant Summary collapse
- COMMENT_CLASSES =
Classes allowed inside YAML-serialized comments
[Ourdate, DateTime, Time, Date, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, ActiveSupport::HashWithIndifferentAccess, Symbol].freeze
Instance Method Summary collapse
-
#log_error(error, extramessage = nil) ⇒ Object
This method takes an exception and updates the e_action so that it can be seen easily through the UI.
- #progress ⇒ Object
-
#update_percentage(i, total, min_percent = 0, max_percent = 100) ⇒ Object
Set the progress percentage of an activity.
Instance Method Details
#log_error(error, extramessage = nil) ⇒ Object
This method takes an exception and updates the e_action so that it can be seen easily through the UI.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/ndr_workflow/e_action_progress.rb', line 81 def log_error(error, = nil) self.reload unless new_record? error_info = { 'error_message' => [error., ].compact.join(': '), 'updated_at' => Time.now } begin if defined?(NdrError) fingerprint, log = NdrError.log(error, { :user_id => self.startedby, :user_roles => '(BATCH)' }, nil) error_info['error_fingerprint'] = fingerprint.id if fingerprint else logger.warn("Failed to log EAction exception in the DB! (#{$!.to_s})") end rescue logger.warn("Failed to log EAction exception in the DB! (#{$!.to_s})") end data = progress.merge(error_info) max_len = (EAction.columns_hash['comments'].sql_type.match(/([0-9]*)\)/).nil? ? 0 : EAction.columns_hash['comments'].sql_type.match(/([0-9]*)\)/)[1]).to_i # if Era.db_oracle? # max_len = EAction.columns_hash['comments'].sql_type.match(/VARCHAR2\(([0-9]*)\)/)[1].to_i # elsif Era.db_postgres? # max_len = EAction.columns_hash['comments'].sql_type.match(/character varying\(([0-9]*)\)/)[1].to_i # end if YAML.dump(data).length > max_len # Horribly inefficient; preserve as much information as possible. len2 = max_len - YAML.dump(data.merge('error_message' => nil)).size while YAML.dump(data).length > max_len do len2 -= 1 data['error_message'] = [error., ].compact.collect{|s| "#{s.to_s[0..len2]}#{'...' if len2 < s.to_s.length}" }.join(': ') end logger.warn("EAction#log_error: Warning: Truncated error message: #{[error., ].inspect} for EAction(#{id})") end update(comments: YAML.dump(data)) end |
#progress ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/ndr_workflow/e_action_progress.rb', line 62 def progress if comments deserialised_comments = YAML.safe_load(comments, permitted_classes: COMMENT_CLASSES.freeze, aliases: true) case deserialised_comments when Integer # Legacy number return {'percentage' => comments.to_i} when String return {'message' => deserialised_comments} when Hash return deserialised_comments end end return {} end |
#update_percentage(i, total, min_percent = 0, max_percent = 100) ⇒ Object
Set the progress percentage of an activity. Progress will range from min_percent to max_percent as i varies from 0 to total. Sample usage:
total = items.length
items.each_with_index do |item, i|
do_something
action.update_percentage(i+1, total)
end
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/ndr_workflow/e_action_progress.rb', line 20 def update_percentage(i, total, min_percent = 0, max_percent = 100) @last_updated_at ||= progress['updated_at'] @last_percentage ||= progress['percentage'] current_percentage = total == 0 ? 0 : (min_percent + i * (max_percent - min_percent) / total).to_i if @last_updated_at.nil? || @last_percentage.nil? || (current_percentage < @last_percentage) || # Always show negative changes (current_percentage > @last_percentage && @last_updated_at < 5.minutes.ago) || # Rate limit positive changes to once every 5 minutes... (current_percentage.divmod(5).first > @last_percentage.divmod(5).first && @last_updated_at < 1.minute.ago) # ...but allow >5% changes every 1 minute @last_updated_at = Time.now @last_percentage = current_percentage # yaml = YAML.dump( progress.merge({'percentage' => @last_percentage, 'updated_at' => @last_updated_at})) yaml = YAML.dump({'percentage' => @last_percentage, 'updated_at' => @last_updated_at}) begin raise(ActiveRecord::StatementInvalid, <<-DESC) if Rails.env.test? libutils is not reliably available in the test schema, so we test the fallback behaviour. This ensures it is the fallback behaviour that we get, even if libutils is present. DESC # Try to update the progress in an anonymous transaction, providing feedback when we # wouldn't otherwise get any (i.e. when the update is in a transaction) # TODO: Test for the corner case where the e_action is updateed within a transaction and # where this is blocked, causing it to fail over to a standard (transaction based) update. # The SQL statement is sanitized for security. # SECURE: BNS 2012-10-09 sanitized_sql = self.class.send(:sanitize_sql_array,[ "BEGIN libutils.set_e_action_comments(?, ?); END;", self.e_actionid, yaml ]) ActiveRecord::Base.connection.execute(sanitized_sql) rescue ActiveRecord::StatementInvalid => e # Update the old way, using standard update Rails.logger.warn("EAction#update_percentage failed to use libutils.set_e_action_comments (#{e.})") puts "EAction#update_percentage failed to use libutils.set_e_action_comments (#{e.})" unless Rails.env.test? # The EAction could be stale as a result of PREP. Eg ChildhoodPreallocator reload unless changed? update(comments: yaml) end end end |