summaryrefslogtreecommitdiff
path: root/main.go
diff options
from:
to:
context:
space:
mode:
authorGravatar SayaAndy <montferrat@tuta.io> 2025-07-16 13:16:00 +0700
committerGravatar SayaAndy <montferrat@tuta.io> 2025-07-16 13:18:57 +0700
commit1a4df793e0228d4edbc1a87b1e9f53504a7a1189 (patch)
treea7982231335733dc6fa60bd49d1420b6f91670a5 /main.go
parent2f03ac5ac3a68ad26efc67f78b16dddf8c53b843 (diff)
downloadthumbnail-generator-1a4df793e0228d4edbc1a87b1e9f53504a7a1189.tar.gz
thumbnail-generator-1a4df793e0228d4edbc1a87b1e9f53504a7a1189.zip
feat: signal handling + log level setting
Diffstat (limited to 'main.go')
-rw-r--r--main.go87
1 files changed, 68 insertions, 19 deletions
diff --git a/main.go b/main.go
index 9d8b625..32ff634 100644
--- a/main.go
+++ b/main.go
@@ -3,7 +3,10 @@ package main
import (
"flag"
"log/slog"
+ "os"
+ "os/signal"
"sync"
+ "syscall"
"github.com/SayaAndy/saya-today-thumbnail-generator/config"
"github.com/SayaAndy/saya-today-thumbnail-generator/internal/client/input"
@@ -12,33 +15,47 @@ import (
)
var (
- configPath = flag.String("c", "config.json", "Path to the configuration file")
+ configPath = flag.String("c", "config.json", "Path to the configuration file")
+ sigTermChan = make(chan os.Signal, 1)
)
func main() {
- flag.Parse()
+ signal.Notify(sigTermChan, os.Interrupt, syscall.SIGTERM)
- slog.Info("starting thumbnail generator...")
- // slog.SetLogLoggerLevel(slog.LevelDebug)
+ flag.Parse()
cfg := &config.Config{}
if err := config.LoadConfig(*configPath, cfg); err != nil {
- panic(err)
+ slog.Error("fail to load configuration", slog.String("error", err.Error()))
+ os.Exit(1)
+ }
+
+ slog.SetLogLoggerLevel(cfg.LogLevel)
+ slog.Info("starting thumbnail generator...")
+
+ select {
+ case <-sigTermChan:
+ slog.Info("exiting due to termination signal")
+ os.Exit(130)
+ default:
}
inputClient, err := input.NewB2InputClient(&cfg.Input)
if err != nil {
- panic(err)
+ slog.Error("fail to initialize input client", slog.String("error", err.Error()))
+ os.Exit(1)
}
outputClient, err := output.NewB2OutputClient(&cfg.Output)
if err != nil {
- panic(err)
+ slog.Error("fail to initialize output client", slog.String("error", err.Error()))
+ os.Exit(1)
}
converter, err := processor.NewWebpProcessor(&cfg.Processor)
if err != nil {
- panic(err)
+ slog.Error("fail to initialize converter", slog.String("error", err.Error()))
+ os.Exit(1)
}
generalLogger := slog.With(
@@ -48,35 +65,59 @@ func main() {
)
generalLogger.Info("initialized clients and processor")
+ select {
+ case <-sigTermChan:
+ generalLogger.Info("exiting due to termination signal")
+ os.Exit(130)
+ default:
+ }
+
files, err := inputClient.Scan()
if err != nil {
- panic(err)
+ generalLogger.Error("fail to scan input files", slog.String("error", err.Error()))
+ os.Exit(1)
}
generalLogger.Info("scanned files", slog.Int("file_count", len(files)))
+ select {
+ case <-sigTermChan:
+ generalLogger.Info("exiting due to termination signal")
+ os.Exit(130)
+ default:
+ }
+
semaphore := make(chan struct{}, cfg.MaxConcurrentJobs)
var wg sync.WaitGroup
wg.Add(len(files))
for i, file := range files {
go func(index int, inputName string) {
- semaphore <- struct{}{}
- defer func() { <-semaphore }()
- defer wg.Done()
-
outputName := converter.DeductOutputPath(inputName)
fileLogger := generalLogger.With(slog.String("input_path", inputName), slog.String("output_path", outputName), slog.Int("file_index", index))
+ threadSigTermChannel := make(chan os.Signal, 1)
+ signal.Notify(threadSigTermChannel, os.Interrupt, syscall.SIGTERM)
+
+ defer func() { <-semaphore }()
+ defer wg.Done()
+ semaphore <- struct{}{}
+ select {
+ case <-threadSigTermChannel:
+ fileLogger.Info("exiting due to termination signal")
+ return
+ default:
+ }
+
inputMetadata, err := inputClient.ReadMetadata(inputName)
if err != nil {
- fileLogger.Error("fail to read metadata of (supposedly existing) input file", slog.String("error", err.Error()))
+ fileLogger.Warn("fail to read metadata of (supposedly existing) input file", slog.String("error", err.Error()))
return
}
if !cfg.ForceRewrite && !outputClient.IsMissing(outputName) {
outputMetadata, err := outputClient.ReadMetadata(outputName)
if err != nil {
- fileLogger.Error("fail to read metadata of (supposedly existing) output file", slog.String("error", err.Error()))
+ fileLogger.Warn("fail to read metadata of (supposedly existing) output file", slog.String("error", err.Error()))
return
}
if inputMetadata.Hash == outputMetadata.HashOriginal {
@@ -88,18 +129,18 @@ func main() {
fileLogger.Info("start to process file")
reader, err := inputClient.GetReader(inputName)
if err != nil {
- fileLogger.Error("fail to get reader for input file", slog.String("error", err.Error()))
+ fileLogger.Warn("fail to get reader for input file", slog.String("error", err.Error()))
return
}
writer, err := outputClient.GetWriter(outputName, inputMetadata)
if err != nil {
- fileLogger.Error("fail to get writer for output file", slog.String("error", err.Error()))
+ fileLogger.Warn("fail to get writer for output file", slog.String("error", err.Error()))
return
}
if err := converter.Process(inputMetadata.ContentType, reader, writer); err != nil {
- fileLogger.Error("fail to convert file", slog.String("error", err.Error()))
+ fileLogger.Warn("fail to convert file", slog.String("error", err.Error()))
return
}
@@ -108,5 +149,13 @@ func main() {
}
wg.Wait()
- generalLogger.Info("all files processed successfully, exiting")
+
+ select {
+ case <-sigTermChan:
+ generalLogger.Info("exiting due to termination signal")
+ os.Exit(130)
+ default:
+ generalLogger.Info("all files processed successfully, exiting")
+ os.Exit(0)
+ }
}