]> git.giacomolli.uk - onechat/blobdiff - schedule.go
Shorten the daemon log lines
[onechat] / schedule.go
index d27274bfe416f589b58ff5e0b047e3df129f1246..3b4a4eed213055457193bcc5295b7a3783e9d463 100644 (file)
@@ -6,6 +6,7 @@ import (
        "encoding/json"
        "errors"
        "fmt"
+       "log"
        "os"
        "slices"
        "strconv"
@@ -48,11 +49,13 @@ const (
 )
 
 // openSchedules reads the schedules of the file at path. A missing file holds
-// none. The clock gives the time and the time zone of the schedules.
-func openSchedules(path string, clock func() time.Time) (*Schedules, error) {
+// none. The clock gives the time and the time zone of the schedules, and logger
+// gets one line for each run.
+func openSchedules(path string, clock func() time.Time, logger *log.Logger) (*Schedules, error) {
        s := &Schedules{
                path:    path,
                clock:   clock,
+               logger:  logger,
                check:   scheduleCheck,
                changed: make(chan struct{}, 1),
        }
@@ -93,6 +96,7 @@ func openSchedules(path string, clock func() time.Time) (*Schedules, error) {
 type Schedules struct {
        path    string
        clock   func() time.Time
+       logger  *log.Logger
        check   time.Duration
        changed chan struct{}
 
@@ -209,6 +213,14 @@ func (s *Schedules) List() string {
        return strings.Join(lines, "\n")
 }
 
+// Len returns the number of schedules.
+func (s *Schedules) Len() int {
+       s.mutex.Lock()
+       defer s.mutex.Unlock()
+
+       return len(s.file.Schedules)
+}
+
 // Remove removes the schedule id and returns the answer of the tool.
 func (s *Schedules) Remove(id int) (string, error) {
        s.mutex.Lock()
@@ -236,7 +248,9 @@ func (s *Schedules) Remove(id int) (string, error) {
 // deliver logs the message of each due schedule in l, in due order, as a work
 // message of scheduleSource, and wakes the loop once with all of them. A
 // schedule ends its run with Done after its message is durable in the log. A
-// crash between the two makes the run repeat once.
+// crash between the two makes the run repeat once. Each run logs one line with
+// the ID of the schedule and, for a late run, how late it is. The line holds no
+// text of the schedule.
 func (s *Schedules) deliver(ctx context.Context, l *TurnLoop) error {
        now := s.clock()
        var turns []Message
@@ -262,6 +276,12 @@ func (s *Schedules) deliver(ctx context.Context, l *TurnLoop) error {
                        return err
                }
 
+               if schedule.late(now) {
+                       s.logger.Printf("schedule %d ran %s late", schedule.ID, durationText(now.Sub(schedule.Due)))
+               } else {
+                       s.logger.Printf("schedule %d ran", schedule.ID)
+               }
+
                turns = append(turns, message)
        }
 
@@ -394,13 +414,19 @@ func (s Schedule) Message(now time.Time) string {
                s.Text,
        }
 
-       if now.Sub(s.Due) > scheduleLate {
+       if s.late(now) {
                lines = append(lines, scheduleLateLine)
        }
 
        return strings.Join(append(lines, scheduleEmptyReply), "\n")
 }
 
+// late tells if a run at now is late: more than scheduleLate after the due
+// time.
+func (s Schedule) late(now time.Time) bool {
+       return now.Sub(s.Due) > scheduleLate
+}
+
 // repeats returns once for a one-time schedule, or else repeats and the cron
 // expression.
 func (s Schedule) repeats() string {