From aa1e1fd415c02089485847f0a1fe4e8c93c0a556 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Thu, 14 May 2026 19:26:57 +0200 Subject: [PATCH] feat(01-03): cmd/worker Phase 1 skeleton (D-03) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Opens pgxpool from DATABASE_URL, logs 'worker ready', blocks on SIGINT/SIGTERM, closes pool, exits 0 - Reuses web.NewSlogHandler — pure helper, no HTTP coupling - No job queue libraries (river/asynq/pg_notify) — Phase 6 replaces this file in full - 48 lines (under 80-line budget signals 'we did not implement Phase 6 by accident') --- backend/cmd/worker/main.go | 48 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 backend/cmd/worker/main.go diff --git a/backend/cmd/worker/main.go b/backend/cmd/worker/main.go new file mode 100644 index 0000000..ecaefd5 --- /dev/null +++ b/backend/cmd/worker/main.go @@ -0,0 +1,48 @@ +// Command worker is the Phase 1 worker skeleton (CONTEXT D-03). It boots, +// opens a pgxpool, logs "worker ready", and blocks on SIGINT/SIGTERM until +// shutdown. Phase 6 replaces this file with the real job runtime — keep it +// minimal until then. +package main + +import ( + "context" + "log/slog" + "os" + "os/signal" + "syscall" + + "backend/internal/db" + "backend/internal/web" +) + +func main() { + env := os.Getenv("ENV") + if env == "" { + env = "development" + } + dsn := os.Getenv("DATABASE_URL") + + slog.SetDefault(slog.New(web.NewSlogHandler(env, os.Stdout))) + + if dsn == "" { + slog.Error("DATABASE_URL is required but unset") + os.Exit(1) + } + + ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) + defer stop() + + pool, err := db.NewPool(ctx, dsn) + if err != nil { + slog.Error("db connect failed", "err", err) + os.Exit(1) + } + + // Load-bearing signal per D-03 — verification scripts grep for this. + slog.Info("worker ready") + + <-ctx.Done() + slog.Info("shutting down") + pool.Close() + slog.Info("shutdown complete") +}