Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

services: add maintenance mode option to snooze alert notifications #2512

Merged
merged 43 commits into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
a0faf0c
add new column to services
Forfold Jul 5, 2022
8c414bb
add schema types for service maintenance
Forfold Jul 5, 2022
9c4f72a
add maintenance expires at field to service schema
Forfold Jul 5, 2022
a6cd5bb
lint
Forfold Jul 5, 2022
74f52c2
[wip] add maintenance expires at select
Forfold Jul 6, 2022
298b78e
[wip] replace mui component
tony-tvu Jul 6, 2022
5386e7a
move maintenance component to its own file, add tooltip info
Forfold Jul 6, 2022
26cd153
fix other queries failing on EP reference
Forfold Jul 7, 2022
7cedea6
pause outgoing notifications while maintenance mode is active
Forfold Jul 7, 2022
f8451c1
add alert notice for maintenance mode
Forfold Jul 7, 2022
f368176
add cancel functionality to notice
Forfold Jul 7, 2022
bc33617
update some styling on dropdown menu
Forfold Jul 7, 2022
8626a4c
add indicator under button for end time
Forfold Jul 7, 2022
ed9ffab
create service maintenance dialog pop-up
tony-tvu Jul 7, 2022
4a954bd
refactor and remove console logs
tony-tvu Jul 8, 2022
625b8b9
refactor
tony-tvu Jul 8, 2022
5409165
cleanup expire date calls
Forfold Jul 8, 2022
79de490
render maintenance notice on alerts list and alert details
Forfold Jul 11, 2022
2ef96ee
fix errors
Forfold Jul 11, 2022
38d5a2c
fix padding issue, disable escalating if maintenance mode active
Forfold Jul 11, 2022
5531a65
fix delayed cancel button
tony-tvu Jul 11, 2022
e96c0c6
[WIP] return error when escalate in maintenance mode
tony-tvu Jul 11, 2022
26e098a
optimistically update ui, increase escalation manager version number,…
Forfold Jul 13, 2022
28ce7a9
add update cleanup, make maint field public, set to null immediately …
Forfold Jul 13, 2022
d869365
add maintenance mode test
tony-tvu Jul 13, 2022
2cf6c76
add maintenance mode cypress test
tony-tvu Jul 14, 2022
bef5dbe
add service maintenance alert test
Forfold Jul 18, 2022
f62b24d
dont use global for initSQL
Forfold Jul 18, 2022
97c59b0
testing escalating during maintenance mode
Forfold Jul 18, 2022
bf17173
cleanup
Forfold Jul 18, 2022
371fd5e
pr comments
Forfold Jul 19, 2022
451ecfe
Update engine/escalationmanager/db.go
Forfold Jul 19, 2022
90df501
Update engine/escalationmanager/db.go
Forfold Jul 19, 2022
8922f25
Update engine/escalationmanager/db.go
Forfold Jul 19, 2022
95c4aa8
Update engine/escalationmanager/db.go
Forfold Jul 19, 2022
98983b0
Update web/src/cypress/integration/services.ts
Forfold Jul 19, 2022
fb98510
test fixes
Forfold Jul 20, 2022
932a677
simplify em queries
mastercactapus Jul 25, 2022
c42d672
simplify escalate many
mastercactapus Jul 25, 2022
3c97509
update sm smoketest for no error scenario
mastercactapus Jul 25, 2022
3ead695
Merge branch 'master' into service-maintenance
mastercactapus Jul 25, 2022
8e74c79
fix countdown type
mastercactapus Jul 25, 2022
73049f1
fix time expired message
mastercactapus Jul 27, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion alert/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,13 @@ func NewStore(ctx context.Context, db *sql.DB, logDB *alertlog.Store) (*Store, e
escalate: p(`
UPDATE escalation_policy_state state
SET force_escalation = true
FROM alerts as a, services as svc
WHERE
state.alert_id = ANY($1) AND
state.force_escalation = false
state.force_escalation = false AND
a.id = state.alert_id AND
svc.id = a.service_id AND
svc.maintenance_expires_at ISNULL
RETURNING state.alert_id
`),

Expand Down
14 changes: 12 additions & 2 deletions engine/escalationmanager/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import (
type DB struct {
lock *processinglock.Lock

cleanupNoSteps *sql.Stmt
clearMaintExpiredSvc *sql.Stmt
cleanupNoSteps *sql.Stmt

lockStmt *sql.Stmt
updateOnCall *sql.Stmt
Expand All @@ -31,7 +32,7 @@ func (db *DB) Name() string { return "Engine.EscalationManager" }
// NewDB creates a new DB.
func NewDB(ctx context.Context, db *sql.DB, log *alertlog.Store) (*DB, error) {
lock, err := processinglock.NewLock(ctx, db, processinglock.Config{
Version: 3,
Version: 4,
Type: processinglock.TypeEscalation,
})
if err != nil {
Expand Down Expand Up @@ -82,6 +83,12 @@ func NewDB(ctx context.Context, db *sql.DB, log *alertlog.Store) (*DB, error) {
returning ep_step_id, user_id
`),

clearMaintExpiredSvc: p.P(`
update services s
set maintenance_expires_at = null
where s.maintenance_expires_at <= now()
`),

cleanupNoSteps: p.P(`
delete from escalation_policy_state state
using escalation_policies pol
Expand All @@ -99,6 +106,7 @@ func NewDB(ctx context.Context, db *sql.DB, log *alertlog.Store) (*DB, error) {
step.escalation_policy_id = state.escalation_policy_id and
step.step_number = 0
join alerts a on a.id = state.alert_id and (a.status = 'triggered' or state.force_escalation)
join services s on a.service_id = s.id and s.maintenance_expires_at isnull
where state.last_escalation isnull
for update skip locked
limit 1000
Expand Down Expand Up @@ -169,6 +177,7 @@ func NewDB(ctx context.Context, db *sql.DB, log *alertlog.Store) (*DB, error) {
WHEN state.escalation_policy_step_number >= ep.step_count THEN 0
ELSE state.escalation_policy_step_number
END
join services s on a.service_id = s.id and s.maintenance_expires_at isnull
where
state.last_escalation notnull and
escalation_policy_step_id isnull
Expand Down Expand Up @@ -248,6 +257,7 @@ func NewDB(ctx context.Context, db *sql.DB, log *alertlog.Store) (*DB, error) {
WHEN state.loop_count < ep.repeat THEN 0
ELSE -1
END
join services s on a.service_id = s.id and s.maintenance_expires_at isnull
where
state.last_escalation notnull and
escalation_policy_step_id notnull and
Expand Down
5 changes: 5 additions & 0 deletions engine/escalationmanager/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ func (db *DB) update(ctx context.Context, all bool, alertID *int) error {
return errors.Wrap(err, "commit on-call update")
}

_, err = db.lock.Exec(ctx, db.clearMaintExpiredSvc)
if err != nil {
return errors.Wrap(err, "set maintenance_expires_at to null where expired")
}

_, err = db.lock.Exec(ctx, db.cleanupNoSteps)
if err != nil {
return errors.Wrap(err, "end policies with no steps")
Expand Down
90 changes: 80 additions & 10 deletions graphql2/generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions graphql2/graphqlapp/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ func (s *Service) EscalationPolicy(ctx context.Context, raw *service.Service) (*
func (s *Service) IsFavorite(ctx context.Context, raw *service.Service) (bool, error) {
return raw.IsUserFavorite(), nil
}

func (s *Service) OnCallUsers(ctx context.Context, raw *service.Service) ([]oncall.ServiceOnCallUser, error) {
return s.OnCallStore.OnCallUsersByService(ctx, raw.ID)
}
Expand Down Expand Up @@ -213,6 +214,10 @@ func (a *Mutation) UpdateService(ctx context.Context, input graphql2.UpdateServi
svc.EscalationPolicyID = *input.EscalationPolicyID
}

if input.MaintenanceExpiresAt != nil {
svc.MaintenanceExpiresAt = *input.MaintenanceExpiresAt
}

err = a.ServiceStore.UpdateTx(ctx, tx, svc)
if err != nil {
return false, err
Expand Down
9 changes: 5 additions & 4 deletions graphql2/models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions graphql2/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ input UpdateServiceInput {
name: String
description: String
escalationPolicyID: ID
maintenanceExpiresAt: ISOTimestamp
}

input UpdateEscalationPolicyInput {
Expand Down Expand Up @@ -968,6 +969,7 @@ type Service {
escalationPolicyID: ID!
escalationPolicy: EscalationPolicy
isFavorite: Boolean!
maintenanceExpiresAt: ISOTimestamp

onCallUsers: [ServiceOnCallUser!]!
integrationKeys: [IntegrationKey!]!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- +migrate Up
UPDATE engine_processing_versions SET "version" = 4 WHERE type_id = 'escalation';
ALTER TABLE services ADD COLUMN maintenance_expires_at TIMESTAMPTZ;

-- +migrate Down
UPDATE engine_processing_versions SET "version" = 3 WHERE type_id = 'escalation';
ALTER TABLE services DROP COLUMN maintenance_expires_at;
23 changes: 18 additions & 5 deletions service/service.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package service

import "github.com/target/goalert/validation/validate"
import (
"time"

"github.com/target/goalert/validation/validate"
)

type Service struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
EscalationPolicyID string `json:"escalation_policy_id"`
ID string
Name string
Description string
EscalationPolicyID string
MaintenanceExpiresAt time.Time

epName string
isUserFavorite bool
Expand All @@ -24,10 +29,18 @@ func (s Service) IsUserFavorite() bool {
// Normalize will validate and 'normalize' the ContactMethod -- such as making email lower-case
// and setting carrier to "" (for non-phone types).
func (s Service) Normalize() (*Service, error) {
dur := time.Until(s.MaintenanceExpiresAt)

if dur <= 0 {
dur = 0
s.MaintenanceExpiresAt = time.Time{}
}

err := validate.Many(
validate.IDName("Name", s.Name),
validate.Text("Description", s.Description, 1, 255),
validate.UUID("EscalationPolicyID", s.EscalationPolicyID),
validate.Duration("MaintenanceExpiresAt", dur, 0, 8*time.Hour),
)
if err != nil {
return nil, err
Expand Down
Loading