90 lines
1.8 KiB
Go
90 lines
1.8 KiB
Go
package scheduler
|
|
|
|
import (
|
|
"log"
|
|
"reflect"
|
|
"runtime"
|
|
"time"
|
|
)
|
|
|
|
type Job struct {
|
|
interval time.Duration
|
|
funcname string
|
|
function interface{}
|
|
params []interface{}
|
|
lastRun time.Time
|
|
nextRun time.Time
|
|
atTime time.Duration
|
|
}
|
|
|
|
type Scheduler struct {
|
|
}
|
|
|
|
func (j *Job) run() ([]reflect.Value, bool) {
|
|
f := reflect.ValueOf(j.function)
|
|
|
|
if len(j.params) != f.Type().NumIn() {
|
|
return nil, false
|
|
}
|
|
|
|
in := make([]reflect.Value, len(j.params))
|
|
for k, param := range j.params {
|
|
in[k] = reflect.ValueOf(param)
|
|
}
|
|
|
|
return f.Call(in), true
|
|
}
|
|
|
|
func (*Scheduler) Start(fn interface{}, params ...interface{}) {
|
|
ticker := time.NewTicker(time.Second)
|
|
defer ticker.Stop()
|
|
done := make(chan bool)
|
|
|
|
f := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
|
|
|
|
job := Job{
|
|
interval: time.Duration(1 * time.Hour * 24),
|
|
funcname: f,
|
|
function: fn,
|
|
params: params,
|
|
lastRun: time.Unix(0, 0),
|
|
nextRun: time.Unix(0, 0),
|
|
atTime: time.Duration(4)*time.Hour + time.Duration(0)*time.Minute + time.Duration(0)*time.Second,
|
|
}
|
|
|
|
log.Println(job)
|
|
if job.lastRun == time.Unix(0, 0) {
|
|
job.lastRun = time.Now()
|
|
}
|
|
|
|
go func() {
|
|
time.Sleep(60 * time.Second)
|
|
}()
|
|
|
|
for {
|
|
select {
|
|
case <-done:
|
|
log.Println("done !")
|
|
return
|
|
case <-ticker.C:
|
|
if time.Now().Unix() >= job.nextRun.Unix() {
|
|
j, ok := job.run()
|
|
if !ok {
|
|
log.Println("failed")
|
|
}
|
|
log.Println("job ran", j)
|
|
now := time.Now()
|
|
job.lastRun = now
|
|
job.nextRun = time.Date(job.lastRun.Year(), job.lastRun.Month(), job.lastRun.Day(), 0, 0, 0, 0, time.UTC)
|
|
job.nextRun = job.nextRun.Add(job.atTime)
|
|
for job.nextRun.Before(now) || job.nextRun.Before(job.lastRun) {
|
|
job.nextRun = job.nextRun.Add(job.interval)
|
|
}
|
|
|
|
log.Printf("next run at %s", job.nextRun)
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|