blob: a44e36deec0a7ea7d76dc6346cf47970f23b3932 [file]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package rotang handles the scheduling of oncall rotations.
package rotang
import (
"time"
"go.chromium.org/gae/service/mail"
"golang.org/x/net/context"
"golang.org/x/oauth2"
)
// Rota represents a named rotation and it's shift entries.
type Rota struct {
// Name of the Rota, should match a Configuration.
Name string
// Entries contain the shift entries for this rota.
Entries []*ShiftEntry
}
// Configuration represents a rota configuration.
type Configuration struct {
Config Config
Members []ShiftMember
}
// Config contains the rota configuration.
type Config struct {
Name string
Description string
Calendar string
TokenID string
Owners []string // TODO(olakar): Change from email to groups.
Email Email
DaysToSchedule int
Shifts ShiftConfig
Expiration int
}
// ShiftConfig holds the Shift configuration.
type ShiftConfig struct {
// StartTime represents the start-time of the first shift.
// Only the Time of day is considered.
// Defaults to 00:00 PDT.
StartTime time.Time
// Length sets the number of days a shift lasts.
Length int
// Skip defines a number of days with no oncalls.
Skip int
// Shifts represents the shifts over a 24hour period.
Shifts []Shift
// ShiftMembers specifides number of members per shift.
ShiftMembers int
// Generator used to schedule new shifts.
Generator string
}
// Shift represents a shift in a 24h rotation.
type Shift struct {
// Name of the shift - Eg. "MTV Shift"
Name string
// Duration is the duration of the shift.
Duration time.Duration
}
// ShiftEntry represents one scheduled shift.
type ShiftEntry struct {
// Name of the Shift this entry belongs to.
Name string
// OnCall are the members on-call for this shift.
OnCall []ShiftMember
StartTime time.Time
EndTime time.Time
// Comment is an optional comment where the rota algo
// can add some extra information.
Comment string
}
// Email contains the Subject and Body templates for email generated by the rota.
type Email struct {
// Subject is a string used as a template run against the Member structure to generate the e-mail Subject
// text.
Subject string
// Body is a string used as a template run againste the Member structure to generate the e-mail Body.
Body string
// DaysBeforeWarn sets the number of days before an on-call shift the notification e-mail is sent.
DaysBeforeNotify int
}
// ShiftMember holds the information needed for a member of a shift.
type ShiftMember struct {
Email string
ShiftName string
}
// Member represents one member of a rotation.
type Member struct {
Name string `json:"full_name"`
Email string `json:"email_address"`
TZ time.Location
OOO []OOO
Preferences []Preference
}
// OOO contains one Out-of-Office event.
type OOO struct {
Start time.Time
Duration time.Duration
Comment string
}
// Preference is used for Members to signal shift preferences.
type Preference int
// Possible preferences for a Member.
const (
NoPreferences Preference = iota
NoWeekends
NoMonday
NoTuesday
NoWednesday
NoThursday
NoFriday
NoSaturday
NoSunday
NoOncall
)
// ConfigStorer defines the Store interface.
type ConfigStorer interface {
// CreateRotaConfig stores a Configuration in backend storage.
CreateRotaConfig(ctx context.Context, cfg *Configuration) error
// UpdateRotaConfig updates the specified configuration.
UpdateRotaConfig(ctx context.Context, cfg *Configuration) error
// RotaConfig fetches the specified rota Configuration from backend storage.
// Leaving `name` empty will return a slice of all stored rota configurations.
RotaConfig(ctx context.Context, name string) ([]*Configuration, error)
// DeleteRotaConfig removes the specified rota from backend storage.
DeleteRotaConfig(ctx context.Context, name string) error
// AddRotaMember add a member to the backend store.
AddRotaMember(ctx context.Context, rota string, member *ShiftMember) error
// DeleteRotaMember deletes the specified member from backend storage.
DeleteRotaMember(ctx context.Context, rota, email string) error
// MemberOf returns the rotations the specified email is a member of.
MemberOf(ctx context.Context, email string) ([]string, error)
}
// MemberStorer defines the member store interface.
type MemberStorer interface {
Member(ctx context.Context, email string) (*Member, error)
AllMembers(ctx context.Context) ([]Member, error)
CreateMember(ctx context.Context, member *Member) error
UpdateMember(cxt context.Context, in *Member) error
DeleteMember(ctx context.Context, email string) error
}
// TokenStorer is used to store OAuth2 tokens.
type TokenStorer interface {
CreateToken(ctx context.Context, email string, token *oauth2.Token) error
Token(ctx context.Context, email string) (*oauth2.Token, error)
DeleteToken(ctx context.Context, email string) error
}
// ShiftStorer is used to store Shift entries.
type ShiftStorer interface {
AddShifts(ctx context.Context, rota string, entries []ShiftEntry) error
AllShifts(cxt context.Context, rota string) ([]ShiftEntry, error)
Shift(cxt context.Context, rota string, start time.Time) (*ShiftEntry, error)
DeleteAllShifts(ctx context.Context, rota string) error
DeleteShift(ctx context.Context, rota string, start time.Time) error
UpdateShift(ctx context.Context, rota string, shift *ShiftEntry) error
Oncall(ctx context.Context, at time.Time, rota string) (*ShiftEntry, error)
}
// RotaGenerator is used to generate oncall rotations.
type RotaGenerator interface {
Name() string
Generate(sc *Configuration, start time.Time, previous []ShiftEntry, members []Member, shiftsToSchedule int) ([]ShiftEntry, error)
}
// MailSender is used to send E-mails.
type MailSender interface {
Send(context.Context, *mail.Message) error
}
// MailInfo contains the information usable by the Email subject/body templates.
type MailInfo struct {
RotaName string
ShiftConfig ShiftConfig
ShiftEntry ShiftEntry
Member Member
MemberURL string
}