diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-18 09:11:01 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-18 09:11:01 +0300 |
commit | 514ace363222f19595375f59b123b5e27c2b9b8a (patch) | |
tree | 955d0b886197f5ae104fa29706084dc13061112f /app/models/concerns/incident_management | |
parent | 25d4a24f831382d37fabc1b6dd3fde26a6c34d4b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/models/concerns/incident_management')
-rw-r--r-- | app/models/concerns/incident_management/escalatable.rb | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/app/models/concerns/incident_management/escalatable.rb b/app/models/concerns/incident_management/escalatable.rb new file mode 100644 index 00000000000..78dce63f59e --- /dev/null +++ b/app/models/concerns/incident_management/escalatable.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: true + +module IncidentManagement + # Shared functionality for a `#status` field, representing + # whether action is required. In EE, this corresponds + # to paging functionality with EscalationPolicies. + # + # This module is only responsible for setting the status and + # possible status-related timestamps (EX triggered_at/resolved_at) + # for the implementing class. The relationships between these + # values and other related timestamps/logic should be managed from + # the object class itself. (EX Alert#ended_at = Alert#resolved_at) + module Escalatable + extend ActiveSupport::Concern + + STATUSES = { + triggered: 0, + acknowledged: 1, + resolved: 2, + ignored: 3 + }.freeze + + STATUS_DESCRIPTIONS = { + triggered: 'Investigation has not started', + acknowledged: 'Someone is actively investigating the problem', + resolved: 'The problem has been addressed', + ignored: 'No action will be taken' + }.freeze + + included do + validates :status, presence: true + + # Ascending sort order sorts statuses: Ignored > Resolved > Acknowledged > Triggered + # Descending sort order sorts statuses: Triggered > Acknowledged > Resolved > Ignored + # https://gitlab.com/gitlab-org/gitlab/-/issues/221242#what-is-the-expected-correct-behavior + scope :order_status, -> (sort_order) { order(status: sort_order == :asc ? :desc : :asc) } + + state_machine :status, initial: :triggered do + state :triggered, value: STATUSES[:triggered] + + state :acknowledged, value: STATUSES[:acknowledged] + + state :resolved, value: STATUSES[:resolved] do + validates :resolved_at, presence: true + end + + state :ignored, value: STATUSES[:ignored] + + state :triggered, :acknowledged, :ignored do + validates :resolved_at, absence: true + end + + event :trigger do + transition any => :triggered + end + + event :acknowledge do + transition any => :acknowledged + end + + event :resolve do + transition any => :resolved + end + + event :ignore do + transition any => :ignored + end + + before_transition to: [:triggered, :acknowledged, :ignored] do |escalatable, _transition| + escalatable.resolved_at = nil + end + + before_transition to: :resolved do |escalatable, transition| + resolved_at = transition.args.first + escalatable.resolved_at = resolved_at || Time.current + end + end + + class << self + def status_value(name) + state_machine_statuses[name] + end + + def status_name(raw_status) + state_machine_statuses.key(raw_status) + end + + def status_names + @status_names ||= state_machine_statuses.keys + end + + private + + def state_machine_statuses + @state_machine_statuses ||= state_machines[:status].states.to_h { |s| [s.name, s.value] } + end + end + + def status_event_for(status) + self.class.state_machines[:status].events.transitions_for(self, to: status.to_s.to_sym).first&.event + end + end + end +end |