github.com/keys-pub/mattermost-server@v4.10.10+incompatible/jobs/schedulers.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package jobs 5 6 import ( 7 "fmt" 8 "sync" 9 "time" 10 11 "github.com/mattermost/mattermost-server/mlog" 12 "github.com/mattermost/mattermost-server/model" 13 ) 14 15 type Schedulers struct { 16 stop chan bool 17 stopped chan bool 18 configChanged chan *model.Config 19 listenerId string 20 startOnce sync.Once 21 jobs *JobServer 22 23 schedulers []model.Scheduler 24 nextRunTimes []*time.Time 25 } 26 27 func (srv *JobServer) InitSchedulers() *Schedulers { 28 mlog.Debug("Initialising schedulers.") 29 30 schedulers := &Schedulers{ 31 stop: make(chan bool), 32 stopped: make(chan bool), 33 configChanged: make(chan *model.Config), 34 jobs: srv, 35 } 36 37 if srv.DataRetentionJob != nil { 38 schedulers.schedulers = append(schedulers.schedulers, srv.DataRetentionJob.MakeScheduler()) 39 } 40 41 if srv.MessageExportJob != nil { 42 schedulers.schedulers = append(schedulers.schedulers, srv.MessageExportJob.MakeScheduler()) 43 } 44 45 if elasticsearchAggregatorInterface := srv.ElasticsearchAggregator; elasticsearchAggregatorInterface != nil { 46 schedulers.schedulers = append(schedulers.schedulers, elasticsearchAggregatorInterface.MakeScheduler()) 47 } 48 49 if ldapSyncInterface := srv.LdapSync; ldapSyncInterface != nil { 50 schedulers.schedulers = append(schedulers.schedulers, ldapSyncInterface.MakeScheduler()) 51 } 52 53 schedulers.nextRunTimes = make([]*time.Time, len(schedulers.schedulers)) 54 return schedulers 55 } 56 57 func (schedulers *Schedulers) Start() *Schedulers { 58 schedulers.listenerId = schedulers.jobs.ConfigService.AddConfigListener(schedulers.handleConfigChange) 59 60 go func() { 61 schedulers.startOnce.Do(func() { 62 mlog.Info("Starting schedulers.") 63 64 defer func() { 65 mlog.Info("Schedulers stopped.") 66 close(schedulers.stopped) 67 }() 68 69 now := time.Now() 70 for idx, scheduler := range schedulers.schedulers { 71 if !scheduler.Enabled(schedulers.jobs.Config()) { 72 schedulers.nextRunTimes[idx] = nil 73 } else { 74 schedulers.setNextRunTime(schedulers.jobs.Config(), idx, now, false) 75 } 76 } 77 78 for { 79 select { 80 case <-schedulers.stop: 81 mlog.Debug("Schedulers received stop signal.") 82 return 83 case now = <-time.After(1 * time.Minute): 84 cfg := schedulers.jobs.Config() 85 86 for idx, nextTime := range schedulers.nextRunTimes { 87 if nextTime == nil { 88 continue 89 } 90 91 if time.Now().After(*nextTime) { 92 scheduler := schedulers.schedulers[idx] 93 if scheduler != nil { 94 if scheduler.Enabled(cfg) { 95 if _, err := schedulers.scheduleJob(cfg, scheduler); err != nil { 96 mlog.Warn(fmt.Sprintf("Failed to schedule job with scheduler: %v", scheduler.Name())) 97 mlog.Error(fmt.Sprint(err)) 98 } else { 99 schedulers.setNextRunTime(cfg, idx, now, true) 100 } 101 } 102 } 103 } 104 } 105 case newCfg := <-schedulers.configChanged: 106 for idx, scheduler := range schedulers.schedulers { 107 if !scheduler.Enabled(newCfg) { 108 schedulers.nextRunTimes[idx] = nil 109 } else { 110 schedulers.setNextRunTime(newCfg, idx, now, false) 111 } 112 } 113 } 114 } 115 }) 116 }() 117 118 return schedulers 119 } 120 121 func (schedulers *Schedulers) Stop() *Schedulers { 122 mlog.Info("Stopping schedulers.") 123 close(schedulers.stop) 124 <-schedulers.stopped 125 return schedulers 126 } 127 128 func (schedulers *Schedulers) setNextRunTime(cfg *model.Config, idx int, now time.Time, pendingJobs bool) { 129 scheduler := schedulers.schedulers[idx] 130 131 if !pendingJobs { 132 if pj, err := schedulers.jobs.CheckForPendingJobsByType(scheduler.JobType()); err != nil { 133 mlog.Error("Failed to set next job run time: " + err.Error()) 134 schedulers.nextRunTimes[idx] = nil 135 return 136 } else { 137 pendingJobs = pj 138 } 139 } 140 141 lastSuccessfulJob, err := schedulers.jobs.GetLastSuccessfulJobByType(scheduler.JobType()) 142 if err != nil { 143 mlog.Error("Failed to set next job run time: " + err.Error()) 144 schedulers.nextRunTimes[idx] = nil 145 return 146 } 147 148 schedulers.nextRunTimes[idx] = scheduler.NextScheduleTime(cfg, now, pendingJobs, lastSuccessfulJob) 149 mlog.Debug(fmt.Sprintf("Next run time for scheduler %v: %v", scheduler.Name(), schedulers.nextRunTimes[idx])) 150 } 151 152 func (schedulers *Schedulers) scheduleJob(cfg *model.Config, scheduler model.Scheduler) (*model.Job, *model.AppError) { 153 pendingJobs, err := schedulers.jobs.CheckForPendingJobsByType(scheduler.JobType()) 154 if err != nil { 155 return nil, err 156 } 157 158 lastSuccessfulJob, err2 := schedulers.jobs.GetLastSuccessfulJobByType(scheduler.JobType()) 159 if err2 != nil { 160 return nil, err 161 } 162 163 return scheduler.ScheduleJob(cfg, pendingJobs, lastSuccessfulJob) 164 } 165 166 func (schedulers *Schedulers) handleConfigChange(oldConfig *model.Config, newConfig *model.Config) { 167 mlog.Debug("Schedulers received config change.") 168 schedulers.configChanged <- newConfig 169 }