From 9d08217a6cc6712ba54c3f3298669f8bf87ecdcf Mon Sep 17 00:00:00 2001 From: Joshua Morris Date: Sat, 21 Nov 2015 21:04:43 +0000 Subject: [PATCH] Added a flag to turn on synchronous job running. If a job is already running, then don't run another one. By default this is turned off, so jobs will run in parallel if run time of a job is longer than the schedule period e.g. the job runs for 5 seconds, but the schedule is to run the job every 1 second --- main.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index f2afc22..6a1f770 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "os/exec" "os/signal" "strings" + "sync" "syscall" "time" @@ -14,6 +15,9 @@ import ( "github.com/robfig/cron" ) +var running bool +var mu = &sync.Mutex{} + func main() { app := cli.NewApp() app.Name = "docker-cron" @@ -84,6 +88,11 @@ SOFTWARE. Usage: "day of week: 0-6 or SUN-SAT", EnvVar: "DC_DOW", }, + cli.BoolFlag{ + Name: "sync-jobs", + Usage: "should the jobs be run one at a time (true), or whenever they are scheduled", + EnvVar: "DC_SYNC", + }, } app.Action = func(con *cli.Context) { // Vars @@ -118,21 +127,29 @@ SOFTWARE. }, " ") log.Printf("Setup cron to run on schedule: %s\n", schedule) c.AddFunc(schedule, func() { - log.Printf("Running cron on schedule: %s\n", schedule) + // Run one at a time, syncFlag=true, or whenever scheduled + syncFlag := con.Bool("sync-jobs") + if runJob(syncFlag) { + defer jobDone(syncFlag) - cmd := exec.Command("sh", "-c", command) + log.Printf("Running cron on schedule: %s\n", schedule) - setupStdout(cmd) - setupStderr(cmd) + cmd := exec.Command("sh", "-c", command) - err := cmd.Start() - if err != nil { - log.Fatal("Error running command", err) - } + setupStdout(cmd) + setupStderr(cmd) - err = cmd.Wait() - if err != nil { - log.Fatal("Error waiting for command", err) + err := cmd.Start() + if err != nil { + log.Fatal("Error running command", err) + } + + err = cmd.Wait() + if err != nil { + log.Fatal("Error waiting for command", err) + } + } else { + log.Println("A job is already running. The sync-jobs flag is true so we only run one at a time") } }) c.Start() @@ -172,5 +189,31 @@ func setupStderr(cmd *exec.Cmd) { log.Printf("ERR: %s\n", scanner.Text()) } }() +} +// Should we run a job. If syncFlag is false, then we always run a job even if +// there is already one running. If syncFlag is true, then we only run a job +// if one is not already running +func runJob(syncFlag bool) bool { + if syncFlag { + mu.Lock() + defer mu.Unlock() + if running { + return false + } else { + running = true + return true + } + } + // Always run, even if there is already one running + return true +} + +func jobDone(syncFlag bool) { + // We only need to change the running state if we have syncrhonous job runs + if syncFlag { + mu.Lock() + defer mu.Unlock() + running = false + } }