mirror of https://git.envs.net/envs/getwtxt.git
119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
/*
|
|
Copyright (c) 2019 Ben Morrison (gbmor)
|
|
|
|
This file is part of Getwtxt.
|
|
|
|
Getwtxt is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Getwtxt is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Getwtxt. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package svc // import "git.sr.ht/~gbmor/getwtxt/svc"
|
|
|
|
import (
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
)
|
|
|
|
// Functions and types in this file pertain
|
|
// to periodic, regular actions.
|
|
|
|
// This is a wrapper for a *time.Ticker
|
|
// that adds another channel. It's used
|
|
// to signal to the ticker goroutines
|
|
// that they should stop the tickers
|
|
// and exit.
|
|
type tick struct {
|
|
isDB bool
|
|
t *time.Ticker
|
|
exit chan struct{}
|
|
}
|
|
|
|
// Creates a new instance of a tick
|
|
func initTicker(db bool, interval time.Duration) *tick {
|
|
return &tick{
|
|
isDB: db,
|
|
t: time.NewTicker(interval),
|
|
exit: make(chan struct{}, 1),
|
|
}
|
|
}
|
|
|
|
// Sends the signal to stop the tickers
|
|
// and for their respective goroutines
|
|
// to exit.
|
|
func killTickers() {
|
|
ct := <-cTickC
|
|
dt := <-dbTickC
|
|
ct.exit <- struct{}{}
|
|
dt.exit <- struct{}{}
|
|
}
|
|
|
|
// Waits for a signal from the database
|
|
// *tick. Either stops the ticker and
|
|
// kills the goroutine or it will
|
|
// update cache / push the DB to disk
|
|
func dataTimer(tkr *tick) {
|
|
for {
|
|
select {
|
|
case signal := <-tkr.t.C:
|
|
if tkr.isDB {
|
|
errLog("", pushDB())
|
|
log.Printf("Database push took: %v\n", time.Since(signal))
|
|
continue
|
|
}
|
|
cacheUpdate()
|
|
log.Printf("Cache update took: %v\n", time.Since(signal))
|
|
case <-tkr.exit:
|
|
tkr.t.Stop()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// Called when a change is detected in the
|
|
// configuration file. Closes log file,
|
|
// closes database connection, stops all
|
|
// tickers, then binds new configuration
|
|
// values, opens new log file, connects to
|
|
// new database, and starts new cache and
|
|
// database tickers.
|
|
func reInit(e fsnotify.Event) {
|
|
log.Printf("%v. Reloading...\n", e.String())
|
|
|
|
if !confObj.StdoutLogging {
|
|
closeLog <- struct{}{}
|
|
}
|
|
|
|
killTickers()
|
|
bindConfig()
|
|
initLogging()
|
|
initPersistence()
|
|
}
|
|
|
|
// Starts the tickers that periodically:
|
|
// - pull new user statuses into cache
|
|
// - push cached data to disk
|
|
func initPersistence() {
|
|
confObj.Mu.RLock()
|
|
cacheTkr := initTicker(false, confObj.CacheInterval)
|
|
dbTkr := initTicker(true, confObj.DBInterval)
|
|
confObj.Mu.RUnlock()
|
|
|
|
go dataTimer(cacheTkr)
|
|
go dataTimer(dbTkr)
|
|
|
|
dbTickC <- dbTkr
|
|
cTickC <- cacheTkr
|
|
}
|