rework on logger + fix the program exit + rename file if errors in json parsing

This commit is contained in:
landrigun 2022-10-16 12:56:27 +00:00
parent 8b0af491c0
commit 4d5f685000
2 changed files with 32 additions and 13 deletions

View File

@ -77,8 +77,8 @@ func GetOutboxPath(iniFile *ini.File) (string, error) {
} }
func main() { func main() {
var logger log.Logger logger := log.NewLogfmtLogger(os.Stdout)
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) logger = level.NewFilter(logger, level.AllowInfo())
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "service", "mailsrv") logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "service", "mailsrv")
iniFile, err := LoadIni() iniFile, err := LoadIni()

View File

@ -1,6 +1,7 @@
package services package services
import ( import (
"fmt"
cfg "mailsrv/config" cfg "mailsrv/config"
"mailsrv/mail" "mailsrv/mail"
"mailsrv/runtime" "mailsrv/runtime"
@ -19,6 +20,7 @@ import (
const ( const (
TickerInterval time.Duration = 10 * time.Second TickerInterval time.Duration = 10 * time.Second
JSONSuffix string = ".json" JSONSuffix string = ".json"
ErrorSuffix string = ".err"
) )
type Sender struct { type Sender struct {
@ -41,23 +43,25 @@ func NewSender(logger log.Logger, config cfg.SMTPConfig, outboxPath string) Send
func (s Sender) SendMail(email mail.Email) error { func (s Sender) SendMail(email mail.Email) error {
auth := smtp.PlainAuth("", s.smtpConfig.User, s.smtpConfig.Password, s.smtpConfig.Url) auth := smtp.PlainAuth("", s.smtpConfig.User, s.smtpConfig.Password, s.smtpConfig.Url)
s.logger.Log("action", "authentication succeed") level.Debug(s.logger).Log("msg", "SMTP authentication succeed")
if err := smtp.SendMail(s.smtpConfig.GetFullUrl(), auth, email.Sender, email.Receivers, email.Generate()); err != nil { if err := smtp.SendMail(s.smtpConfig.GetFullUrl(), auth, email.Sender, email.Receivers, email.Generate()); err != nil {
level.Error(s.logger).Log("msg", "error while sending email", "err", err) level.Error(s.logger).Log("msg", "error while sending email", "err", err)
return err return err
} }
s.logger.Log("msg", "mail send successfully") level.Debug(s.logger).Log("msg", "mail send successfully")
return nil return nil
} }
// watchOutbox reads the `outbox` directory every `TickInterval` and put JSON format e-mail in the queue // watchOutbox reads the `outbox` directory every `TickInterval` and put JSON format e-mail in the queue
func (s Sender) watchOutbox() { func (s Sender) watchOutbox() {
s.logger.Log("msg", "start watching outbox directory", "outbox", s.outboxPath)
ticker := time.NewTicker(TickerInterval) ticker := time.NewTicker(TickerInterval)
go func() { go func() {
for _ = range ticker.C { for _ = range ticker.C {
s.logger.Log("action", "retrieving json e-mail format...", "path", s.outboxPath) level.Debug(s.logger).Log("action", "retrieving json e-mail format...", "path", s.outboxPath)
files, err := os.ReadDir(s.outboxPath) files, err := os.ReadDir(s.outboxPath)
if err != nil && !os.IsExist(err) { if err != nil && !os.IsExist(err) {
@ -71,7 +75,7 @@ func (s Sender) watchOutbox() {
s.queue.Add(path.Join(s.outboxPath, filename)) s.queue.Add(path.Join(s.outboxPath, filename))
continue continue
} }
level.Warn(s.logger).Log("msg", "incorrect suffix", "filename", filename) level.Debug(s.logger).Log("msg", "incorrect suffix", "filename", filename)
} }
} }
}() }()
@ -87,20 +91,31 @@ func (s Sender) processNextEmail() bool {
path, ok := item.(string) path, ok := item.(string)
if !ok { if !ok {
level.Error(s.logger).Log("msg", "unable to cast queue item into mail.Email") level.Error(s.logger).Log("msg", "unable to cast queue item into mail.Email", "item", item)
return true return true
} }
email, err := mail.FromJSON(path) email, err := mail.FromJSON(path)
if err != nil { if err != nil {
level.Error(s.logger).Log("msg", "unable to parse JSON email", "err", err) level.Error(s.logger).Log("msg", "unable to parse JSON email", "path", path, "err", err)
// if JSON parsing failed the `path` is renamed with an error suffix to avoid enqueued it again
newPath := fmt.Sprintf("%s%s", path, ErrorSuffix)
if err := os.Rename(path, newPath); err != nil {
level.Error(s.logger).Log("msg", "unable to rename bad JSON email path", "path", path, "newPath", newPath)
s.queue.Shutdown()
}
return true return true
} }
// whatever the return, the email will be not enqueued again
s.SendMail(email) s.SendMail(email)
if err := os.Remove(path); err != nil { if err := os.Remove(path); err != nil {
// this is a fatal error, can't send same e-mail indefinitely
if !os.IsExist(err) {
level.Error(s.logger).Log("msg", "unable to remove the JSON email", "path", path, "err", err) level.Error(s.logger).Log("msg", "unable to remove the JSON email", "path", path, "err", err)
s.queue.Shutdown()
}
} }
return true return true
@ -128,10 +143,14 @@ func (s Sender) Run() {
s.watchOutbox() s.watchOutbox()
queueCh := s.run() queueCh := s.run()
<-sigCh select {
case <-sigCh:
s.logger.Log("msg", "stop signal received, stopping e-mail queue...") s.logger.Log("msg", "stop signal received, stopping e-mail queue...")
s.queue.Shutdown() s.queue.Shutdown()
case <-queueCh:
s.logger.Log("msg", "e-mail queue stopped successfully")
}
<-queueCh
s.logger.Log("msg", "sender service stopped successfully") s.logger.Log("msg", "sender service stopped successfully")
} }