Class: RailsInformant::ErrorGroup
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- RailsInformant::ErrorGroup
- Defined in:
- app/models/rails_informant/error_group.rb
Constant Summary collapse
- API_FIELDS =
%i[ controller_action created_at duplicate_of_id error_class fingerprint first_backtrace_line first_seen_at fix_deployed_at fix_pr_url fix_sha id job_class last_seen_at message original_sha resolved_at severity status total_occurrences updated_at ].freeze
- API_DETAIL_FIELDS =
(API_FIELDS + %i[ last_notified_at last_occurrence_stored_at notes ]).freeze
- VALID_TRANSITIONS =
{ "duplicate" => %w[unresolved], "fix_pending" => %w[resolved unresolved], "ignored" => %w[unresolved], "resolved" => %w[unresolved], "unresolved" => %w[duplicate fix_pending ignored resolved] }.freeze
- MAX_DUPLICATE_CHAIN_DEPTH =
10
Class Method Summary collapse
- .circular_duplicate_chain?(target_id, source_id) ⇒ Boolean
- .find_or_create_for(fingerprint, attributes) ⇒ Object
Instance Method Summary collapse
- #circular_duplicate_chain?(original_id) ⇒ Boolean
- #detect_regression! ⇒ Object
- #mark_as_duplicate_of!(target_id) ⇒ Object
- #mark_as_fix_pending!(fix_sha:, original_sha:, fix_pr_url: nil) ⇒ Object
Class Method Details
.circular_duplicate_chain?(target_id, source_id) ⇒ Boolean
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'app/models/rails_informant/error_group.rb', line 92 def self.circular_duplicate_chain?(target_id, source_id) return false unless source_id seen = Set.new([ target_id ]) current_id = source_id MAX_DUPLICATE_CHAIN_DEPTH.times do return false unless current_id return true if seen.include?(current_id) seen << current_id current_id = where(id: current_id).pick(:duplicate_of_id) end true # depth exceeded, treat as circular end |
.find_or_create_for(fingerprint, attributes) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'app/models/rails_informant/error_group.rb', line 65 def find_or_create_for(fingerprint, attributes) now = attributes[:last_seen_at] if (group = find_by(fingerprint:)) increment_counters group, now else group = create!(attributes.merge(fingerprint:)) end group rescue ActiveRecord::RecordNotUnique group = find_by!(fingerprint:) increment_counters group, now group end |
Instance Method Details
#circular_duplicate_chain?(original_id) ⇒ Boolean
108 109 110 |
# File 'app/models/rails_informant/error_group.rb', line 108 def circular_duplicate_chain?(original_id) self.class.circular_duplicate_chain?(original_id, duplicate_of_id) end |
#detect_regression! ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 |
# File 'app/models/rails_informant/error_group.rb', line 133 def detect_regression! return unless status == "resolved" changed = self.class.where(id:, status: "resolved").update_all( status: "unresolved", resolved_at: nil, fix_deployed_at: nil, fix_sha: nil, original_sha: nil, fix_pr_url: nil, updated_at: Time.current) return unless changed > 0 assign_attributes status: "unresolved", resolved_at: nil, fix_deployed_at: nil, fix_sha: nil, original_sha: nil, fix_pr_url: nil end |
#mark_as_duplicate_of!(target_id) ⇒ Object
122 123 124 125 126 127 128 129 130 131 |
# File 'app/models/rails_informant/error_group.rb', line 122 def mark_as_duplicate_of!(target_id) raise RailsInformant::InvalidParameterError, "duplicate_of_id is required" unless target_id.present? target = self.class.find_by(id: target_id) raise RailsInformant::InvalidParameterError, "Target error group not found" unless target raise RailsInformant::InvalidParameterError, "Cannot mark as duplicate of itself" if target.id == id raise RailsInformant::InvalidParameterError, "Circular duplicate chain detected" if target.circular_duplicate_chain?(id) update!(status: "duplicate", duplicate_of: target) end |
#mark_as_fix_pending!(fix_sha:, original_sha:, fix_pr_url: nil) ⇒ Object
112 113 114 115 116 117 118 119 120 |
# File 'app/models/rails_informant/error_group.rb', line 112 def mark_as_fix_pending!(fix_sha:, original_sha:, fix_pr_url: nil) raise RailsInformant::InvalidParameterError, "fix_sha is required" unless fix_sha.present? raise RailsInformant::InvalidParameterError, "original_sha is required" unless original_sha.present? validate_sha_format! fix_sha validate_sha_format! original_sha validate_url_scheme! fix_pr_url if fix_pr_url.present? update!(status: "fix_pending", fix_sha:, original_sha:, fix_pr_url:) end |