From 35aea3e65da34c31053134c946fb87bb0144ae49 Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Thu, 26 Sep 2024 11:41:18 -1000 Subject: [PATCH] Add framework for scheduled jobs; convert auto-refresh This PR adds a framework for "scheduled jobs" and passes "TickMsg" messages to the Update() function based on an interval set in the root.go file (currently 1s per "tick"). This also converts the auto-refresh to a scheduled job, and sets a slice of initial `[]*scheduledJob`. Each scheduled job is made up of: ``` type scheduledJob struct { jobMsg tea.Cmd lastRun time.Time frequency time.Duration } ``` And the `jobMsg` `tea.Cmd` is run if the `lastRun` is further than `frequency` in the past. Each scheduled job is evalusted when a `TickMsg` is received. The auto refresh feature is implemented as: ``` { jobMsg: func() tea.Msg { return PollIncidentsMsg{} }, frequency: time.Second * 15, }, ``` This job is added to the list of initial secheduled jobs on startup. Currently, the job is run every 15 seconds, and if "auto-refresh" is enabled, then incidents are updated. In the future this will be converted to adding or removing the scheduled job from the job list, rather than parsing if "auto-refresh" is true or not, and `autoRefresh bool` removed from the model. Signed-off-by: Chris Collins --- cmd/root.go | 8 +++----- pkg/tui/commands.go | 18 ++++++++++++++---- pkg/tui/model.go | 12 ++++++++++++ pkg/tui/tui.go | 12 +++++++++--- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index fda63be..9be32c4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -39,7 +39,7 @@ import ( "github.com/spf13/viper" ) -const pollInterval = 15 +const tickInterval = 1 // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ @@ -86,10 +86,8 @@ but rather a simple tool to make on-call tasks easier.`, go func() { for { - time.Sleep(pollInterval * time.Second) - p.Send(tui.PollIncidentsMsg{ - PollInterval: pollInterval * time.Second, - }) + time.Sleep(tickInterval * time.Second) + p.Send(tui.TickMsg{}) } }() diff --git a/pkg/tui/commands.go b/pkg/tui/commands.go index efe09d6..3d50bfd 100644 --- a/pkg/tui/commands.go +++ b/pkg/tui/commands.go @@ -174,12 +174,10 @@ type waitForSelectedIncidentThenDoMsg struct { } type TickMsg struct { - Tick int -} -type PollIncidentsMsg struct { - PollInterval time.Duration } +type PollIncidentsMsg struct{} + type renderIncidentMsg string type renderedIncidentMsg struct { @@ -640,3 +638,15 @@ func doIfIncidentSelected(m *model, cmd tea.Cmd) tea.Cmd { cmd, ) } + +func runScheduledJobs(m *model) []tea.Cmd { + var cmds []tea.Cmd + for _, job := range m.scheduledJobs { + if time.Since(job.lastRun) > job.frequency && job.jobMsg != nil { + log.Debug("Update: TicketMsg", "scheduledJob", job.jobMsg, "frequency", job.frequency, "lastRun", job.lastRun, "running", true) + cmds = append(cmds, job.jobMsg) + job.lastRun = time.Now() + } + } + return cmds +} diff --git a/pkg/tui/model.go b/pkg/tui/model.go index dd0683e..c2ce8bb 100644 --- a/pkg/tui/model.go +++ b/pkg/tui/model.go @@ -1,6 +1,8 @@ package tui import ( + "time" + "github.com/PagerDuty/go-pagerduty" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/table" @@ -12,6 +14,13 @@ import ( "github.com/clcollins/srepd/pkg/pd" ) +var initialScheduledJobs = []*scheduledJob{ + { + jobMsg: func() tea.Msg { return PollIncidentsMsg{} }, + frequency: time.Second * 15, + }, +} + type model struct { err error @@ -33,6 +42,8 @@ type model struct { selectedIncidentNotes []pagerduty.IncidentNote selectedIncidentAlerts []pagerduty.IncidentAlert + scheduledJobs []*scheduledJob + autoAcknowledge bool autoRefresh bool teamMode bool @@ -60,6 +71,7 @@ func InitialModel( input: newTextInput(), incidentViewer: newIncidentViewer(), status: "", + scheduledJobs: append([]*scheduledJob{}, initialScheduledJobs...), } // This is an ugly way to handle this error diff --git a/pkg/tui/tui.go b/pkg/tui/tui.go index 83aeb78..42eb17d 100644 --- a/pkg/tui/tui.go +++ b/pkg/tui/tui.go @@ -45,6 +45,12 @@ type filteredMsg struct { truncated bool } +type scheduledJob struct { + jobMsg tea.Cmd + lastRun time.Time + frequency time.Duration +} + func filterMsgContent(msg tea.Msg) tea.Msg { var truncatedMsg string switch msg := msg.(type) { @@ -94,8 +100,8 @@ func filterMsgContent(msg tea.Msg) tea.Msg { // return m, func() tea.Msg { getIncident(m.config, msg.incident.ID) } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { msgType := reflect.TypeOf(msg) - // PollIncidentsMsgs are not helpful for logging - if msgType != reflect.TypeOf(PollIncidentsMsg{}) { + // TickMsg are not helpful for logging + if msgType != reflect.TypeOf(TickMsg{}) { log.Debug("Update", msgType, filterMsgContent(msg)) } @@ -107,7 +113,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m.errMsgHandler(msg) case TickMsg: - // Pass + return m, tea.Batch(runScheduledJobs(&m)...) case tea.WindowSizeMsg: return m.windowSizeMsgHandler(msg)