diff --git a/analyses.go b/analyses.go index 94ce051..c303b84 100644 --- a/analyses.go +++ b/analyses.go @@ -41,6 +41,21 @@ type Job struct { ExternalID string `json:"external_id"` } +// getJobDuration takes a job and returns a duration string and the start time of the job +func getJobDuration(j *Job) (string, time.Time, error) { + starttime, err := time.ParseInLocation(TimestampFromDBFormat, j.StartDate, time.Local) + if err != nil { + return "", starttime, errors.Wrapf(err, "failed to parse start date %s", j.StartDate) + } + + // just print H(HH):MM format + dur := time.Since(starttime).Round(time.Minute) + h := dur / time.Hour + dur -= h * time.Hour + m := dur / time.Minute + return fmt.Sprintf("%d:%02d", h, m), starttime, nil +} + const jobsToKillQuery = ` select jobs.id, jobs.app_id, diff --git a/main.go b/main.go index 0622752..ef15868 100644 --- a/main.go +++ b/main.go @@ -45,7 +45,7 @@ iplant_groups: const warningSentKey = "warningsent" const oneDayWarningKey = "onedaywarning" -func sendNotif(ctx context.Context, j *Job, status, subject, msg string) error { +func sendNotif(ctx context.Context, j *Job, status, subject, msg, email_template string) error { var err error // Don't send notification if things aren't configured correctly. It's @@ -68,16 +68,22 @@ func sendNotif(ctx context.Context, j *Job, status, subject, msg string) error { } sdmillis := sd.UnixNano() / 1000000 + durString, _, err := getJobDuration(j) + if err != nil { + return errors.Wrapf(err, "failed to parse job duration from %s", j.StartDate) + } + p := NewPayload() p.AnalysisName = j.Name p.AnalysisDescription = j.Description p.AnalysisStatus = status p.AnalysisStartDate = strconv.FormatInt(sdmillis, 10) p.AnalysisResultsFolder = j.ResultFolder + p.RunDuration = durString p.Email = user.Email p.User = u - notif := NewNotification(u, subject, msg, p) + notif := NewNotification(u, subject, msg, email_template, p) resp, err := notif.Send(ctx) if err != nil { @@ -137,7 +143,7 @@ func SendKillNotification(ctx context.Context, j *Job, killNotifKey string) erro endtime.UTC().Format(time.UnixDate), j.ResultFolder, ) - err = sendNotif(ctx, j, "Canceled", subject, msg) + err = sendNotif(ctx, j, "Canceled", subject, msg, "analysis_status_change") return err } @@ -161,22 +167,15 @@ func SendWarningNotification(ctx context.Context, j *Job) error { j.ResultFolder, ) - return sendNotif(ctx, j, j.Status, subject, msg) + return sendNotif(ctx, j, j.Status, subject, msg, "analysis_status_change") } func SendPeriodicNotification(ctx context.Context, j *Job) error { - starttime, err := time.ParseInLocation(TimestampFromDBFormat, j.StartDate, time.Local) + durString, starttime, err := getJobDuration(j) if err != nil { - return errors.Wrapf(err, "failed to parse start date %s", j.StartDate) + return err } - // just print H(HH):MM format - dur := time.Since(starttime).Round(time.Minute) - h := dur / time.Hour - dur -= h * time.Hour - m := dur / time.Minute - durString := fmt.Sprintf("%d:%02d", h, m) - subject := fmt.Sprintf(PeriodicSubjectFormat, j.Name, starttime, durString) msg := fmt.Sprintf( @@ -184,10 +183,10 @@ func SendPeriodicNotification(ctx context.Context, j *Job) error { j.Name, j.ID, starttime, - dur, + durString, ) - return sendNotif(ctx, j, j.Status, subject, msg) + return sendNotif(ctx, j, j.Status, subject, msg, "analysis_periodic_notification") } func ensureNotifRecord(ctx context.Context, vicedb *VICEDatabaser, job Job) error { diff --git a/notifications.go b/notifications.go index 4c895d8..64fd2ad 100644 --- a/notifications.go +++ b/notifications.go @@ -71,12 +71,13 @@ type Payload struct { AnalysisStatus string `json:"analysisstatus"` AnalysisStartDate string `json:"analysisstartdate"` AnalysisResultsFolder string `json:"analysisresultsfolder"` + RunDuration string `json:"runduration"` Email string `json:"email_address"` Action string `json:"action"` User string `json:"user"` } -// NewPayload returns a newly constructed *Payload +// NewPayload returns a newly constructed *Payload with the Action set to "job_status_change" func NewPayload() *Payload { return &Payload{ Action: "job_status_change", @@ -84,7 +85,7 @@ func NewPayload() *Payload { } // NewNotification returns a newly initialized *Notification. -func NewNotification(user, subject, msg string, payload *Payload) *Notification { +func NewNotification(user, subject, msg, emailTemplate string, payload *Payload) *Notification { return &Notification{ URI: NotifsURI, Type: "analysis", @@ -92,7 +93,7 @@ func NewNotification(user, subject, msg string, payload *Payload) *Notification Subject: subject, Message: msg, Email: true, - EmailTemplate: "analysis_status_change", + EmailTemplate: emailTemplate, Payload: payload, } } diff --git a/notifications_test.go b/notifications_test.go index 1228eee..1de7cb4 100644 --- a/notifications_test.go +++ b/notifications_test.go @@ -22,8 +22,9 @@ func TestNewNotification(t *testing.T) { expectedURI := "foo" expectedUser := "user" expectedSubject := "subject" + expectedTemplate := "analysis_status_change" NotifsInit(expectedURI) - n := NewNotification(expectedUser, expectedSubject, "", nil) + n := NewNotification(expectedUser, expectedSubject, "", expectedTemplate, nil) if n.URI != expectedURI { t.Errorf("URI was %s, not %s", n.URI, expectedURI) } @@ -33,12 +34,15 @@ func TestNewNotification(t *testing.T) { if n.Subject != expectedSubject { t.Errorf("Subject was %s, not %s", n.Subject, expectedSubject) } + if n.EmailTemplate != expectedTemplate { + t.Errorf("EmailTemplate was %s, not %s", n.EmailTemplate, expectedTemplate) + } } func TestSend(t *testing.T) { expectedUser := "test-user" expectedSubject := "test-subject" - n := NewNotification(expectedUser, expectedSubject, "", nil) + n := NewNotification(expectedUser, expectedSubject, "", "analysis_status_change", nil) srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { b, err := io.ReadAll(r.Body)