github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+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  	"sync"
     8  	"time"
     9  
    10  	l4g "github.com/alecthomas/log4go"
    11  
    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  	l4g.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  			l4g.Info("Starting schedulers.")
    63  
    64  			defer func() {
    65  				l4g.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  					l4g.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  										l4g.Warn("Failed to schedule job with scheduler: %v", scheduler.Name())
    97  										l4g.Error(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  	l4g.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  			l4g.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  		l4g.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  	l4g.Debug("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  	l4g.Debug("Schedulers received config change.")
   168  	schedulers.configChanged <- newConfig
   169  }