rework on logger + fix the program exit + rename file if errors in json parsing
This commit is contained in:
		
							parent
							
								
									8b0af491c0
								
							
						
					
					
						commit
						4d5f685000
					
				
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							| @ -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() | ||||||
|  | |||||||
| @ -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 { | ||||||
| 		level.Error(s.logger).Log("msg", "unable to remove the JSON email", "path", path, "err", err) | 		// 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) | ||||||
|  | 			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 { | ||||||
| 	s.logger.Log("msg", "stop signal received, stopping e-mail queue...") | 	case <-sigCh: | ||||||
| 	s.queue.Shutdown() | 		s.logger.Log("msg", "stop signal received, stopping e-mail queue...") | ||||||
|  | 		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") | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user