package main import ( "os" "os/signal" "syscall" "time" _ "time/tzdata" "git.fjla.uk/owlboard/timetable-mgr/background" "git.fjla.uk/owlboard/timetable-mgr/cif" "git.fjla.uk/owlboard/timetable-mgr/corpus" "git.fjla.uk/owlboard/timetable-mgr/dbAccess" "git.fjla.uk/owlboard/timetable-mgr/helpers" "git.fjla.uk/owlboard/timetable-mgr/log" "git.fjla.uk/owlboard/timetable-mgr/messaging" "git.fjla.uk/owlboard/timetable-mgr/vstp" "go.uber.org/zap" ) func main() { log.Info("Initialising OwlBoard timetable-mgr", zap.String("version", helpers.Version)) cfg, err := helpers.LoadConfig() if err != nil { log.Fatal("Unable to load configuration", zap.Error(err)) return } cfg.PrintConfig() dbAccess.InitDataAccess(cfg) dbAccess.PushVersionToDb() // Initialise a `stop` channel to signal goroutines to cleanup stop := make(chan struct{}) // Start CIF Task Ticker background.InitTicker(cfg, stop) // Handle signals from the OS go handleSignals(cfg, stop) // Manually call CIF and CORPUS checks to ensure that they are // not delayed until the first ticker event. go cif.CheckCif(cfg) go corpus.CheckCorpus(cfg) if cfg.VstpOn { messaging.StompInit(cfg) vstp.Subscribe() } <-stop } // Traps SIGINT and SIGTERM signals and ensures cleanup() is run func handleSignals(cfg *helpers.Configuration, stop chan<- struct{}) { sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) sig := <-sigChan log.Warn("Signal received: " + sig.String()) cleanup(cfg, stop) } // Cleans up open connections ready for a clean exit of the program func cleanup(cfg *helpers.Configuration, stop chan<- struct{}) { log.Debug("Cleaning up open connections") if cfg.VstpOn { if messaging.Client != nil { log.Info("Closing STOMP Client") messaging.Disconnect(messaging.Client) } } if dbAccess.MongoClient != nil { log.Info("Closing MongoDB Client") dbAccess.CloseMongoClient() } log.Info("Signalling to other goroutines") close(stop) log.Info("Program ready to exit") time.Sleep(500 * time.Millisecond) os.Exit(0) }