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) } } } }