gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

timing.go (2072B)


      1 package sched
      2 
      3 import (
      4 	"time"
      5 )
      6 
      7 var (
      8 	// zerotime is zero time.Time (unix epoch).
      9 	zerotime = time.Time{}
     10 
     11 	// emptytiming is a global timingempty to check against.
     12 	emptytiming = timingempty{}
     13 )
     14 
     15 // Timing provides scheduling for a Job, determining the next time
     16 // for given current time that execution is required. Please note that
     17 // calls to .Next() may alter the results of the next call, and should
     18 // only be called by the Scheduler.
     19 type Timing interface {
     20 	Next(time.Time) time.Time
     21 }
     22 
     23 // timingempty is a 'zero' Timing implementation that always returns zero time.
     24 type timingempty struct{}
     25 
     26 func (timingempty) Next(time.Time) time.Time {
     27 	return zerotime
     28 }
     29 
     30 // Once implements Timing to provide a run-once Job execution.
     31 type Once time.Time
     32 
     33 func (o *Once) Next(time.Time) time.Time {
     34 	ret := *(*time.Time)(o)
     35 	*o = Once(zerotime) // reset
     36 	return ret
     37 }
     38 
     39 // Periodic implements Timing to provide a recurring Job execution.
     40 type Periodic time.Duration
     41 
     42 func (p Periodic) Next(now time.Time) time.Time {
     43 	return now.Add(time.Duration(p))
     44 }
     45 
     46 // PeriodicAt implements Timing to provide a recurring Job execution starting at 'Once' time.
     47 type PeriodicAt struct {
     48 	Once   Once
     49 	Period Periodic
     50 }
     51 
     52 func (p *PeriodicAt) Next(now time.Time) time.Time {
     53 	if next := p.Once.Next(now); !next.IsZero() {
     54 		return next
     55 	}
     56 	return p.Period.Next(now)
     57 }
     58 
     59 // TimingWrap allows combining two different Timing implementations.
     60 type TimingWrap struct {
     61 	Outer Timing
     62 	Inner Timing
     63 
     64 	// determined next times
     65 	outerNext time.Time
     66 	innerNext time.Time
     67 }
     68 
     69 func (t *TimingWrap) Next(now time.Time) time.Time {
     70 	if t.outerNext.IsZero() {
     71 		// Regenerate outermost next run time
     72 		t.outerNext = t.Outer.Next(now)
     73 	}
     74 
     75 	if t.innerNext.IsZero() {
     76 		// Regenerate innermost next run time
     77 		t.innerNext = t.Inner.Next(now)
     78 	}
     79 
     80 	// If outer comes before inner, return outer
     81 	if t.outerNext != zerotime &&
     82 		t.outerNext.Before(t.innerNext) {
     83 		next := t.outerNext
     84 		t.outerNext = zerotime
     85 		return next
     86 	}
     87 
     88 	// Else, return inner
     89 	next := t.innerNext
     90 	t.innerNext = zerotime
     91 	return next
     92 }