package scheduler import ( "sort" "time" ) type Scheduler interface { Len() int Swap(i, j int) Less(i, j int) bool NextRun() (Job, time.Time) Every(interval uint64) Job RunPending() RunAll() RunAllwithDelay(d int) Remove(j interface{}) Clear() Start() chan bool getRunnableJobs() (running_jobs [MAXJOBNUM]Job, n int) } // Create a new scheduler func NewScheduler() Scheduler { return &innerScheduler{[MAXJOBNUM]Job{}, 0} } type innerScheduler struct { // Array store jobs jobs [MAXJOBNUM]Job // Size of jobs which jobs holding. size int } func (s *innerScheduler) Len() int { return s.size } func (s *innerScheduler) Swap(i, j int) { s.jobs[i], s.jobs[j] = s.jobs[j], s.jobs[i] } func (s *innerScheduler) Less(i, j int) bool { return s.jobs[j].nextRun().After(s.jobs[i].nextRun()) } // Get the current runnable jobs, which shouldRun is True func (s *innerScheduler) getRunnableJobs() (running_jobs [MAXJOBNUM]Job, n int) { runnableJobs := [MAXJOBNUM]Job{} n = 0 sort.Sort(s) for i := 0; i < s.size; i++ { if s.jobs[i].shouldRun() { runnableJobs[n] = s.jobs[i] //fmt.Println(runnableJobs) n++ } else { break } } return runnableJobs, n } // Datetime when the next job should run. func (s *innerScheduler) NextRun() (Job, time.Time) { if s.size <= 0 { return nil, time.Now() } sort.Sort(s) return s.jobs[0], s.jobs[0].nextRun() } // Schedule a new periodic job func (s *innerScheduler) Every(interval uint64) Job { job := NewJob(interval) s.jobs[s.size] = job s.size++ return job } // Run all the jobs that are scheduled to run. func (s *innerScheduler) RunPending() { runnableJobs, n := s.getRunnableJobs() if n != 0 { for i := 0; i < n; i++ { runnableJobs[i].run() } } } // Run all jobs regardless if they are scheduled to run or not func (s *innerScheduler) RunAll() { for i := 0; i < s.size; i++ { s.jobs[i].run() } } // Run all jobs with delay seconds func (s *innerScheduler) RunAllwithDelay(d int) { for i := 0; i < s.size; i++ { s.jobs[i].run() time.Sleep(time.Duration(d)) } } // Remove specific job j func (s *innerScheduler) Remove(j interface{}) { i := 0 for ; i < s.size; i++ { if s.jobs[i].jobFunc() == getFunctionName(j) { break } } for j := (i + 1); j < s.size; j++ { s.jobs[i] = s.jobs[j] i++ } s.size = s.size - 1 } // Delete all scheduled jobs func (s *innerScheduler) Clear() { for i := 0; i < s.size; i++ { s.jobs[i] = nil } s.size = 0 } // Start all the pending jobs // Add seconds ticker func (s *innerScheduler) Start() chan bool { stopped := make(chan bool, 1) ticker := time.NewTicker(1 * time.Second) go func() { for { select { case <-ticker.C: s.RunPending() case <-stopped: return } } }() return stopped }