From 2d384046dd03b1830ae190422fe6d05cf9b286e9 Mon Sep 17 00:00:00 2001 From: jbergner Date: Fri, 14 Aug 2026 17:51:57 +0200 Subject: [PATCH] gitignore-fix --- .gitignore | 1 - cmd/pocketwatch/main.go | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 cmd/pocketwatch/main.go diff --git a/.gitignore b/.gitignore index 17b72cd..4a8ad5d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ *.db *.db-shm *.db-wal -pocketwatch .DS_Store diff --git a/cmd/pocketwatch/main.go b/cmd/pocketwatch/main.go new file mode 100644 index 0000000..ae1ec80 --- /dev/null +++ b/cmd/pocketwatch/main.go @@ -0,0 +1,74 @@ +package main + +import ( + "context" + "errors" + "log/slog" + "net/http" + "os" + "os/signal" + "path/filepath" + "syscall" + "time" + _ "time/tzdata" + + "pocketwatch-go/internal/app" +) + +func main() { + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})) + addr := env("APP_ADDR", ":8080") + dataDir := env("DATA_DIR", "/data") + if err := os.MkdirAll(dataDir, 0o750); err != nil { + logger.Error("create data directory", "error", err) + os.Exit(1) + } + + cfg := app.Config{ + DBPath: filepath.Join(dataDir, "pocketwatch.db"), + CookieSecure: env("COOKIE_SECURE", "false") == "true", + SessionTTL: 30 * 24 * time.Hour, + } + + a, err := app.New(cfg, logger) + if err != nil { + logger.Error("initialize app", "error", err) + os.Exit(1) + } + defer a.Close() + + srv := &http.Server{ + Addr: addr, + Handler: a.Handler(), + ReadHeaderTimeout: 10 * time.Second, + ReadTimeout: 20 * time.Second, + WriteTimeout: 60 * time.Second, + IdleTimeout: 120 * time.Second, + MaxHeaderBytes: 1 << 20, + } + + go func() { + logger.Info("pocketwatch listening", "addr", addr, "db", cfg.DBPath) + if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { + logger.Error("http server", "error", err) + os.Exit(1) + } + }() + + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt, syscall.SIGTERM) + <-stop + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + logger.Error("graceful shutdown", "error", err) + } +} + +func env(key, fallback string) string { + if v := os.Getenv(key); v != "" { + return v + } + return fallback +}