Skip to content

Commit

Permalink
UX touchups
Browse files Browse the repository at this point in the history
  • Loading branch information
dadgar committed Apr 26, 2018
1 parent 14d46f5 commit d4b4e6a
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 13 deletions.
2 changes: 1 addition & 1 deletion nomad/job_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,7 @@ func (j *Job) Plan(args *structs.JobPlanRequest, reply *structs.JobPlanResponse)
if args.Job.IsPeriodic() && args.Job.Periodic.Enabled {
reply.NextPeriodicLaunch, err = args.Job.Periodic.Next(time.Now().In(args.Job.Periodic.GetLocation()))
if err != nil {
return fmt.Errorf("Failed to parse cron time %v", err)
return fmt.Errorf("Failed to parse cron expression: %v", err)
}
}

Expand Down
3 changes: 2 additions & 1 deletion nomad/leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ func (s *Server) restorePeriodicDispatcher() error {
// nextLaunch is the next launch that should occur.
nextLaunch, err := job.Periodic.Next(launch.Launch.In(job.Periodic.GetLocation()))
if err != nil {
return fmt.Errorf("failed to parse periodic time: %v", err)
s.logger.Printf("[ERR] nomad.periodic: failed to determine next periodic launch for job %s: %v", job.NamespacedID(), err)
continue
}

// We skip force launching the job if there should be no next launch
Expand Down
9 changes: 4 additions & 5 deletions nomad/periodic.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (p *PeriodicDispatch) Add(job *structs.Job) error {
p.tracked[tuple] = job
next, err := job.Periodic.Next(time.Now().In(job.Periodic.GetLocation()))
if err != nil {
return fmt.Errorf("[ERR] nomad.periodic unable to parse cron expression: %v", err)
return fmt.Errorf("Failed adding job %s: %v", job.NamespacedID(), err)
}
if tracked {
if err := p.heap.Update(job, next); err != nil {
Expand Down Expand Up @@ -349,10 +349,9 @@ func (p *PeriodicDispatch) dispatch(job *structs.Job, launchTime time.Time) {

nextLaunch, err := job.Periodic.Next(launchTime)
if err != nil {
p.logger.Printf("[ERR] nomad.periodic: failed to parse periodic job %v", err)
}
if err := p.heap.Update(job, nextLaunch); err != nil {
p.logger.Printf("[ERR] nomad.periodic: failed to update next launch of periodic job %q (%s): %v", job.ID, job.Namespace, err)
p.logger.Printf("[ERR] nomad.periodic: failed to parse next periodic launch for job %s: %v", job.NamespacedID(), err)
} else if err := p.heap.Update(job, nextLaunch); err != nil {
p.logger.Printf("[ERR] nomad.periodic: failed to update next launch of periodic job %s: %v", job.NamespacedID(), err)
}

// If the job prohibits overlapping and there are running children, we skip
Expand Down
16 changes: 13 additions & 3 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1997,6 +1997,14 @@ type Job struct {
JobModifyIndex uint64
}

// NamespacedID returns the namespaced id useful for logging
func (j *Job) NamespacedID() *NamespacedID {
return &NamespacedID{
ID: j.ID,
Namespace: j.Namespace,
}
}

// Canonicalize is used to canonicalize fields in the Job. This should be called
// when registering a Job. A set of warnings are returned if the job was changed
// in anyway that the user should be made aware of.
Expand Down Expand Up @@ -2649,11 +2657,13 @@ func (p *PeriodicConfig) Canonicalize() {
p.location = l
}

func cronParseNext(e *cronexpr.Expression, fromTime time.Time) (t time.Time, err error) {
// cronParseNext is a helper that parses the next time for the given expression
// but captures any panic that may occur in the underlying library.
func cronParseNext(e *cronexpr.Expression, fromTime time.Time, spec string) (t time.Time, err error) {
defer func() {
if recover() != nil {
t = time.Time{}
err = fmt.Errorf("Unable to parse cron expression from time")
err = fmt.Errorf("failed parsing cron expression: %q", spec)
}
}()

Expand All @@ -2668,7 +2678,7 @@ func (p *PeriodicConfig) Next(fromTime time.Time) (time.Time, error) {
switch p.SpecType {
case PeriodicSpecCron:
if e, err := cronexpr.Parse(p.Spec); err == nil {
return cronParseNext(e, fromTime)
return cronParseNext(e, fromTime, p.Spec)
}
case PeriodicSpecTest:
split := strings.Split(p.Spec, ",")
Expand Down
15 changes: 12 additions & 3 deletions nomad/structs/structs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2015,7 +2015,10 @@ func TestPeriodicConfig_NextCron(t *testing.T) {
for i, spec := range specs {
p := &PeriodicConfig{Enabled: true, SpecType: PeriodicSpecCron, Spec: spec}
p.Canonicalize()
n := p.Next(from)
n, err := p.Next(from)
if err != nil {
t.Fatalf("Next returned error: %v", err)
}
if expected[i] != n {
t.Fatalf("Next(%v) returned %v; want %v", from, n, expected[i])
}
Expand Down Expand Up @@ -2050,8 +2053,14 @@ func TestPeriodicConfig_DST(t *testing.T) {
e1 := time.Date(2017, time.March, 11, 10, 0, 0, 0, time.UTC)
e2 := time.Date(2017, time.March, 12, 9, 0, 0, 0, time.UTC)

n1 := p.Next(t1).UTC()
n2 := p.Next(t2).UTC()
n1, err1 := p.Next(t1)
n2, err2 := p.Next(t2)
if err1 != nil || err2 != nil {
t.Fatalf("bad: %v %v", err1, err2)
}

n1 = n1.UTC()
n2 = n2.UTC()

if !reflect.DeepEqual(e1, n1) {
t.Fatalf("Got %v; want %v", n1, e1)
Expand Down

0 comments on commit d4b4e6a

Please sign in to comment.