Skip to content

Commit

Permalink
Merge pull request #6 from krallin/fix-supercronic-skips-a-beat
Browse files Browse the repository at this point in the history
Fix: Supercronic skips a beat
  • Loading branch information
krallin authored Jul 11, 2017
2 parents 2486269 + 0e133a9 commit 4c8f5c9
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 14 deletions.
10 changes: 2 additions & 8 deletions cron/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,14 @@ func runJob(context *crontab.Context, command string, jobLogger *logrus.Entry) e
return nil
}

func StartJob(wg *sync.WaitGroup, context *crontab.Context, job *crontab.Job, exitChan chan interface{}) {
func StartJob(wg *sync.WaitGroup, context *crontab.Context, job *crontab.Job, exitChan chan interface{}, cronLogger *logrus.Entry) {
wg.Add(1)

go func() {
defer wg.Done()

cronLogger := logrus.WithFields(logrus.Fields{
"job.schedule": job.Schedule,
"job.command": job.Command,
"job.position": job.Position,
})

var cronIteration uint64 = 0
nextRun := job.Expression.Next(time.Now())
nextRun := time.Now()

// NOTE: this (intentionally) does not run multiple instances of the
// job concurrently
Expand Down
81 changes: 78 additions & 3 deletions cron/cron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"io/ioutil"
"regexp"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -35,6 +36,7 @@ func (hook *testHook) Levels() []logrus.Level {
func newTestLogger() (*logrus.Entry, chan *logrus.Entry) {
logger := logrus.New()
logger.Out = ioutil.Discard
logger.Level = logrus.DebugLevel

channel := make(chan *logrus.Entry, BUFFER_SIZE)
hook := newTestHook(channel)
Expand All @@ -44,10 +46,11 @@ func newTestLogger() (*logrus.Entry, chan *logrus.Entry) {
}

type testExpression struct {
delay time.Duration
}

func (expr *testExpression) Next(t time.Time) time.Time {
return t.Add(time.Minute)
return t.Add(expr.delay)
}

var (
Expand Down Expand Up @@ -161,7 +164,7 @@ func TestRunJob(t *testing.T) {
func TestStartJobExitsOnRequest(t *testing.T) {
job := crontab.Job{
CrontabLine: crontab.CrontabLine{
Expression: &testExpression{},
Expression: &testExpression{time.Minute},
Schedule: "always!",
Command: "true",
},
Expand All @@ -171,9 +174,81 @@ func TestStartJobExitsOnRequest(t *testing.T) {
exitChan := make(chan interface{}, 1)
exitChan <- nil

logger, _ := newTestLogger()

var wg sync.WaitGroup

StartJob(&wg, &basicContext, &job, exitChan)
StartJob(&wg, &basicContext, &job, exitChan, logger)

wg.Wait()
}

func TestStartJobRunsJob(t *testing.T) {
job := crontab.Job{
CrontabLine: crontab.CrontabLine{
Expression: &testExpression{2 * time.Second},
Schedule: "always!",
Command: "true",
},
Position: 1,
}

exitChan := make(chan interface{}, 1)

var wg sync.WaitGroup

logger, channel := newTestLogger()

StartJob(&wg, &basicContext, &job, exitChan, logger)

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("job will run next"), entry.Message)
case <-time.After(time.Second):
t.Fatalf("timed out waiting for schedule")
}

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("starting"), entry.Message)
case <-time.After(3 * time.Second):
t.Fatalf("timed out waiting for start")
}

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("job succeeded"), entry.Message)
case <-time.After(time.Second):
t.Fatalf("timed out waiting for success")
}

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("job will run next"), entry.Message)
case <-time.After(time.Second):
t.Fatalf("timed out waiting for second schedule")
}

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("starting"), entry.Message)
case <-time.After(3 * time.Second):
t.Fatalf("timed out waiting for second start")
}

select {
case entry := <-channel:
fmt.Printf("got %s\n", entry.Message)
assert.Regexp(t, regexp.MustCompile("job succeeded"), entry.Message)
case <-time.After(time.Second):
t.Fatalf("timed out waiting for second success")
}

exitChan <- nil
wg.Wait()
}
13 changes: 10 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,16 @@ func main() {
)

for _, job := range tab.Jobs {
c := make(chan interface{}, 1)
exitChans = append(exitChans, c)
cron.StartJob(&wg, tab.Context, job, c)
exitChan := make(chan interface{}, 1)
exitChans = append(exitChans, exitChan)

cronLogger := logrus.WithFields(logrus.Fields{
"job.schedule": job.Schedule,
"job.command": job.Command,
"job.position": job.Position,
})

cron.StartJob(&wg, tab.Context, job, exitChan, cronLogger)
}

termChan := make(chan os.Signal, 1)
Expand Down

0 comments on commit 4c8f5c9

Please sign in to comment.