Skip to content

Route alert notifications only through escalation rules

Sarah Yasonik requested to merge sy-rule-based-escalations into master

What does this MR do?

The purpose of this MR is to provide a foundation for adding alternate types of escalation rules for Category:Incident Management, specifically routing alerts directly to users (instead of only through an OncallSchedule).

More detailed motivation can be found in #330648 (comment 619885972), but my general goal in this MR is to:

  1. Remove duplicate data from IncidentManagement::PendingEscalation::Alert/IncidentManagement::EscalationRule
  2. Reduce app usages of nullable fields on IncidentManagement::PendingEscalation::Alert/IncidentManagement::EscalationRule

Changes:

  1. Add a is_removed column for incident_management_escalation_rules
    • Similar to IncidentManagement::OncallParticipant, this will allow the association to rules to be preserved from IncidentManagement::PendingEscalations::Alert
  2. When an escalation policy is updated, rules are be marked with is_removed: true on deletion instead of actually deleting
  3. Swap IncidentManagement::EscalationRule to cascade deletions to IncidentManagement::PendingEscalations::Alert, instead of nullifying
  4. Swap null constraints for IncidentManagement::PendingEscalations::Alert -> allow schedule_id/status to be null, enforce rule_id to be present
  5. Swap creation/processing of IncidentManagement::PendingEscalations::Alert records to use only the associated rule, ignoring the schedule/status attributes

Database

BEFORE
% bin/rails dbconsole                          
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_escalation_rules
                                    Table "public.incident_management_escalation_rules"
        Column        |   Type   | Collation | Nullable |                             Default                              
----------------------+----------+-----------+----------+------------------------------------------------------------------
 id                   | bigint   |           | not null | nextval('incident_management_escalation_rules_id_seq'::regclass)
 policy_id            | bigint   |           | not null | 
 oncall_schedule_id   | bigint   |           | not null | 
 status               | smallint |           | not null | 
 elapsed_time_seconds | integer  |           | not null | 
Indexes:
    "incident_management_escalation_rules_pkey" PRIMARY KEY, btree (id)
    "index_on_policy_schedule_status_elapsed_time_escalation_rules" UNIQUE, btree (policy_id, oncall_schedule_id, status, elapsed_time_seconds)
    "index_on_oncall_schedule_escalation_rule" btree (oncall_schedule_id)
Foreign-key constraints:
    "fk_rails_17dbea07a6" FOREIGN KEY (policy_id) REFERENCES incident_management_escalation_policies(id) ON DELETE CASCADE
    "fk_rails_b3c9c17bd4" FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Referenced by:
    TABLE "incident_management_pending_alert_escalations" CONSTRAINT "fk_rails_057c1e3d87" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE SET NULL

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           | not null | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           | not null | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_057c1e3d87" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE SET NULL
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)
20210721174411: Add is_removed to escalation rules
Up
% bin/rails db:migrate VERSION=20210721174411
== 20210721174411 AddIsRemovedToEscalationRules: migrating ====================
-- add_column(:incident_management_escalation_rules, :is_removed, :boolean, {:null=>false, :default=>false})
   -> 0.0082s
== 20210721174411 AddIsRemovedToEscalationRules: migrated (0.0082s) ===========
% gdk psql                                   
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_escalation_rules
                                    Table "public.incident_management_escalation_rules"
        Column        |   Type   | Collation | Nullable |                             Default                              
----------------------+----------+-----------+----------+------------------------------------------------------------------
 id                   | bigint   |           | not null | nextval('incident_management_escalation_rules_id_seq'::regclass)
 policy_id            | bigint   |           | not null | 
 oncall_schedule_id   | bigint   |           | not null | 
 status               | smallint |           | not null | 
 elapsed_time_seconds | integer  |           | not null | 
 is_removed           | boolean  |           | not null | false
Indexes:
    "incident_management_escalation_rules_pkey" PRIMARY KEY, btree (id)
    "index_on_policy_schedule_status_elapsed_time_escalation_rules" UNIQUE, btree (policy_id, oncall_schedule_id, status, elapsed_time_seconds)
    "index_on_oncall_schedule_escalation_rule" btree (oncall_schedule_id)
Foreign-key constraints:
    "fk_rails_17dbea07a6" FOREIGN KEY (policy_id) REFERENCES incident_management_escalation_policies(id) ON DELETE CASCADE
    "fk_rails_b3c9c17bd4" FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Referenced by:
    TABLE "incident_management_pending_alert_escalations" CONSTRAINT "fk_rails_057c1e3d87" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE SET NULL

gitlabhq_development=# \q
Down
% bin/rails db:migrate:down VERSION=20210721174411
== 20210721174411 AddIsRemovedToEscalationRules: reverting ====================
-- remove_column(:incident_management_escalation_rules, :is_removed, :boolean, {:null=>false, :default=>false})
   -> 0.0034s
== 20210721174411 AddIsRemovedToEscalationRules: reverted (0.0086s) ===========
% gdk psql                                        
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_escalation_rules
                                    Table "public.incident_management_escalation_rules"
        Column        |   Type   | Collation | Nullable |                             Default                              
----------------------+----------+-----------+----------+------------------------------------------------------------------
 id                   | bigint   |           | not null | nextval('incident_management_escalation_rules_id_seq'::regclass)
 policy_id            | bigint   |           | not null | 
 oncall_schedule_id   | bigint   |           | not null | 
 status               | smallint |           | not null | 
 elapsed_time_seconds | integer  |           | not null | 
Indexes:
    "incident_management_escalation_rules_pkey" PRIMARY KEY, btree (id)
    "index_on_policy_schedule_status_elapsed_time_escalation_rules" UNIQUE, btree (policy_id, oncall_schedule_id, status, elapsed_time_seconds)
    "index_on_oncall_schedule_escalation_rule" btree (oncall_schedule_id)
Foreign-key constraints:
    "fk_rails_17dbea07a6" FOREIGN KEY (policy_id) REFERENCES incident_management_escalation_policies(id) ON DELETE CASCADE
    "fk_rails_b3c9c17bd4" FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Referenced by:
    TABLE "incident_management_pending_alert_escalations" CONSTRAINT "fk_rails_057c1e3d87" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE SET NULL

gitlabhq_development=# \q
20210721174441: Cascade deletions of escalation rules
Up
% bin/rails db:migrate VERSION=20210721174441 
== 20210721174441 UpdateEscalationRuleFkForPendingAlertEscalations: migrating =
-- foreign_keys(:incident_management_pending_alert_escalations)
   -> 0.0048s
-- remove_foreign_key(:incident_management_pending_alert_escalations, :incident_management_escalation_rules, {:name=>"fk_rails_057c1e3d87"})
   -> 0.0045s
-- foreign_keys(:incident_management_pending_alert_escalations)
   -> 0.0020s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000")
   -> 0.0021s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0028s
-- execute("SET statement_timeout TO 0")
   -> 0.0006s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0044s
-- execute("RESET ALL")
   -> 0.0006s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107")
   -> 0.0022s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0022s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0031s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108")
   -> 0.0024s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0011s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0020s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109")
   -> 0.0024s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0013s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0019s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110")
   -> 0.0022s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0011s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0018s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111")
   -> 0.0021s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0011s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0018s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112")
   -> 0.0021s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0011s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0021s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201")
   -> 0.0024s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201\nADD CONSTRAINT fk_rails_f3d17bc8af\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE CASCADE\nNOT VALID;\n")
   -> 0.0011s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201 VALIDATE CONSTRAINT fk_rails_f3d17bc8af;")
   -> 0.0025s
-- add_foreign_key(:incident_management_pending_alert_escalations, :incident_management_escalation_rules, {:column=>:rule_id, :on_delete=>:cascade, :name=>"fk_rails_f3d17bc8af", :validate=>true})
   -> 0.0048s
== 20210721174441 UpdateEscalationRuleFkForPendingAlertEscalations: migrated (0.1384s) 
% gdk psql                                   
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           | not null | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           | not null | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
Down
% bin/rails db:migrate:down VERSION=20210721174441
== 20210721174441 UpdateEscalationRuleFkForPendingAlertEscalations: reverting =
-- foreign_keys(:incident_management_pending_alert_escalations)
   -> 0.0051s
-- remove_foreign_key(:incident_management_pending_alert_escalations, :incident_management_escalation_rules, {:column=>:rule_id})
   -> 0.0062s
-- foreign_keys(:incident_management_pending_alert_escalations)
   -> 0.0023s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000")
   -> 0.0023s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0049s
-- execute("SET statement_timeout TO 0")
   -> 0.0008s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_000000 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0045s
-- execute("RESET ALL")
   -> 0.0015s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107")
   -> 0.0028s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0017s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202107 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0032s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108")
   -> 0.0023s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0012s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202108 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0027s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109")
   -> 0.0027s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0041s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202109 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0028s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110")
   -> 0.0027s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0031s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202110 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0024s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111")
   -> 0.0045s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0012s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202111 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0025s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112")
   -> 0.0025s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0025s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202112 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0028s
-- transaction_open?()
   -> 0.0000s
-- foreign_keys("gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201")
   -> 0.0023s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201\nADD CONSTRAINT fk_rails_057c1e3d87\nFOREIGN KEY (rule_id)\nREFERENCES incident_management_escalation_rules (id)\nON DELETE SET NULL\nNOT VALID;\n")
   -> 0.0010s
-- execute("ALTER TABLE gitlab_partitions_dynamic.incident_management_pending_alert_escalations_202201 VALIDATE CONSTRAINT fk_rails_057c1e3d87;")
   -> 0.0025s
-- add_foreign_key(:incident_management_pending_alert_escalations, :incident_management_escalation_rules, {:column=>:rule_id, :on_delete=>:nullify, :name=>"fk_rails_057c1e3d87", :validate=>true})
   -> 0.0033s
== 20210721174441 UpdateEscalationRuleFkForPendingAlertEscalations: reverted (0.2088s) 
% gdk psql                                        
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           | not null | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           | not null | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_057c1e3d87" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE SET NULL
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
20210721174453: Remove schedule/status non-null constraints
Up
% bin/rails db:migrate VERSION=20210721174453
== 20210721174453 RemoveScheduleAndStatusNullConstraintsFromPendingEscalationsAlert: migrating 
-- change_column_null(:incident_management_pending_alert_escalations, :status, true)
   -> 0.0024s
-- change_column_null(:incident_management_pending_alert_escalations, :schedule_id, true)
   -> 0.0010s
== 20210721174453 RemoveScheduleAndStatusNullConstraintsFromPendingEscalationsAlert: migrated (0.0034s) 
% gdk psql                                   
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           |          | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           |          | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
Down
% bin/rails db:migrate:down VERSION=20210721174453
== 20210721174453 RemoveScheduleAndStatusNullConstraintsFromPendingEscalationsAlert: reverting 
-- exec_query("UPDATE incident_management_pending_alert_escalations AS escalations\nSET status = rules.status\nFROM incident_management_escalation_rules AS rules\nWHERE rule_id = rules.id\nAND escalations.status IS NULL\n")
   -> 0.0075s
-- change_column_null(:incident_management_pending_alert_escalations, :status, false)
   -> 0.0018s
-- exec_query("UPDATE incident_management_pending_alert_escalations AS escalations\nSET schedule_id = rules.oncall_schedule_id\nFROM incident_management_escalation_rules AS rules\nWHERE rule_id = rules.id\nAND escalations.schedule_id IS NULL\n")
   -> 0.0018s
-- change_column_null(:incident_management_pending_alert_escalations, :schedule_id, false)
   -> 0.0015s
== 20210721174453 RemoveScheduleAndStatusNullConstraintsFromPendingEscalationsAlert: reverted (0.0128s) 
% gdk psql                                        
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           | not null | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           | not null | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
20210721174521: Add rule non-null constraint
Up
% bin/rails db:migrate VERSION=20210721174521
== 20210721174521 AddNonNullConstraintForEscalationRuleOnPendingAlertEscalations: migrating 
-- exec_query("INSERT INTO incident_management_escalation_rules (policy_id, oncall_schedule_id, status, elapsed_time_seconds, is_removed)\nSELECT\n  policies.id,\n  schedule_id,\n  status,\n  ABS(ROUND(\n  EXTRACT(EPOCH FROM (escalations.process_at - escalations.created_at))/60*60\n))\n AS elapsed_time_seconds,\n  TRUE\nFROM incident_management_pending_alert_escalations AS escalations\nINNER JOIN incident_management_oncall_schedules AS schedules ON schedules.id = schedule_id\nINNER JOIN incident_management_escalation_policies AS policies ON policies.project_id = schedules.project_id\nWHERE rule_id IS NULL\nGROUP BY policies.id, schedule_id, status, elapsed_time_seconds\nON CONFLICT DO NOTHING;\n")
   -> 0.0135s
-- exec_query("UPDATE incident_management_pending_alert_escalations AS escalations\nSET rule_id = rules.id\nFROM incident_management_pending_alert_escalations AS through_escalations\nINNER JOIN incident_management_oncall_schedules AS schedules ON schedules.id = through_escalations.schedule_id\nINNER JOIN incident_management_escalation_policies AS policies ON policies.project_id = schedules.project_id\nINNER JOIN incident_management_escalation_rules AS rules ON rules.policy_id = policies.id\nWHERE escalations.rule_id IS NULL\nAND rules.status = escalations.status\nAND rules.oncall_schedule_id = escalations.schedule_id\nAND rules.elapsed_time_seconds = ABS(ROUND(\n  EXTRACT(EPOCH FROM (escalations.process_at - escalations.created_at))/60*60\n))\n;\n")
   -> 0.0073s
-- exec_query("DELETE FROM incident_management_pending_alert_escalations WHERE rule_id IS NULL;")
   -> 0.0011s
-- change_column_null(:incident_management_pending_alert_escalations, :rule_id, false)
   -> 0.0009s
== 20210721174521 AddNonNullConstraintForEscalationRuleOnPendingAlertEscalations: migrated (0.0231s)
% gdk psql                                        
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           | not null | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           |          | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           |          | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
Down
% bin/rails db:migrate:down VERSION=20210721174521
== 20210721174521 AddNonNullConstraintForEscalationRuleOnPendingAlertEscalations: reverting 
-- change_column_null(:incident_management_pending_alert_escalations, :rule_id, true)
   -> 0.0041s
== 20210721174521 AddNonNullConstraintForEscalationRuleOnPendingAlertEscalations: reverted (0.0042s) 
% gdk psql                                        
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                 Partitioned table "public.incident_management_pending_alert_escalations"
   Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
 id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
 rule_id     | bigint                   |           |          | 
 alert_id    | bigint                   |           | not null | 
 schedule_id | bigint                   |           |          | 
 process_at  | timestamp with time zone |           | not null | 
 created_at  | timestamp with time zone |           | not null | 
 updated_at  | timestamp with time zone |           | not null | 
 status      | smallint                 |           |          | 
Partition key: RANGE (process_at)
Indexes:
    "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
    "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
    "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
    "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
    "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
    "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
    "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q
AFTER
% gdk psql            
psql (12.7)
Type "help" for help.

gitlabhq_development=# \d incident_management_escalation_rules
                                   Table "public.incident_management_escalation_rules"
       Column        |   Type   | Collation | Nullable |                             Default                              
----------------------+----------+-----------+----------+------------------------------------------------------------------
id                   | bigint   |           | not null | nextval('incident_management_escalation_rules_id_seq'::regclass)
policy_id            | bigint   |           | not null | 
oncall_schedule_id   | bigint   |           | not null | 
status               | smallint |           | not null | 
elapsed_time_seconds | integer  |           | not null | 
is_removed           | boolean  |           | not null | false
Indexes:
   "incident_management_escalation_rules_pkey" PRIMARY KEY, btree (id)
   "index_on_policy_schedule_status_elapsed_time_escalation_rules" UNIQUE, btree (policy_id, oncall_schedule_id, status, elapsed_time_seconds)
   "index_on_oncall_schedule_escalation_rule" btree (oncall_schedule_id)
Foreign-key constraints:
   "fk_rails_17dbea07a6" FOREIGN KEY (policy_id) REFERENCES incident_management_escalation_policies(id) ON DELETE CASCADE
   "fk_rails_b3c9c17bd4" FOREIGN KEY (oncall_schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Referenced by:
   TABLE "incident_management_pending_alert_escalations" CONSTRAINT "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE

gitlabhq_development=# \d incident_management_pending_alert_escalations
                                Partitioned table "public.incident_management_pending_alert_escalations"
  Column    |           Type           | Collation | Nullable |                                  Default                                  
-------------+--------------------------+-----------+----------+---------------------------------------------------------------------------
id          | bigint                   |           | not null | nextval('incident_management_pending_alert_escalations_id_seq'::regclass)
rule_id     | bigint                   |           | not null | 
alert_id    | bigint                   |           | not null | 
schedule_id | bigint                   |           |          | 
process_at  | timestamp with time zone |           | not null | 
created_at  | timestamp with time zone |           | not null | 
updated_at  | timestamp with time zone |           | not null | 
status      | smallint                 |           |          | 
Partition key: RANGE (process_at)
Indexes:
   "incident_management_pending_alert_escalations_pkey" PRIMARY KEY, btree (id, process_at)
   "index_incident_management_pending_alert_escalations_on_alert_id" btree (alert_id)
   "index_incident_management_pending_alert_escalations_on_rule_id" btree (rule_id)
   "index_incident_management_pending_alert_escalations_on_schedule" btree (schedule_id)
Foreign-key constraints:
   "fk_rails_8d8de95da9" FOREIGN KEY (alert_id) REFERENCES alert_management_alerts(id) ON DELETE CASCADE
   "fk_rails_f3d17bc8af" FOREIGN KEY (rule_id) REFERENCES incident_management_escalation_rules(id) ON DELETE CASCADE
   "fk_rails_fcbfd9338b" FOREIGN KEY (schedule_id) REFERENCES incident_management_oncall_schedules(id) ON DELETE CASCADE
Number of partitions: 8 (Use \d+ to list them.)

gitlabhq_development=# \q

Screenshots or Screencasts (strongly suggested)

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

Does this MR contain changes to processing or storing of credentials or tokens, authorization and authentication methods or other items described in the security review guidelines? If not, then delete this Security section.

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by Sarah Yasonik

Merge request reports