newdrive/cmd/drive/main.go
Elijah 077cf7601a
Some checks failed
CI / Backend (push) Failing after 4s
CI / Frontend (push) Successful in 11s
CI / Contracts and repository policy (push) Failing after 5s
CI / Container (push) Has been skipped
Initial phase 1 baseline implementation
2026-07-16 19:14:01 -07:00

91 lines
2 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"log/slog"
"os"
"os/signal"
"syscall"
"time"
"drive.local/drivev2/internal/adapters/postgres"
"drive.local/drivev2/internal/adapters/webassets"
"drive.local/drivev2/internal/application"
"drive.local/drivev2/internal/config"
"drive.local/drivev2/internal/transport/httpapi"
)
var version = "dev"
func main() {
if err := run(); err != nil {
slog.Error("drive stopped", "error", err)
os.Exit(1)
}
}
func run() error {
command := "serve"
if len(os.Args) > 1 {
command = os.Args[1]
}
switch command {
case "serve":
return serve()
case "version":
fmt.Println(version)
return nil
default:
return fmt.Errorf("unknown command %q", command)
}
}
func serve() error {
cfg, err := config.FromEnvironment()
if err != nil {
return err
}
if cfg.DatabaseURL == "" {
return errors.New("DRIVE_DATABASE_URL is required for serve")
}
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: cfg.LogLevel}))
slog.SetDefault(logger)
startupCtx, startupCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer startupCancel()
if err := postgres.Migrate(cfg.DatabaseURL); err != nil {
return err
}
store, err := postgres.Open(startupCtx, cfg.DatabaseURL)
if err != nil {
return err
}
defer store.Close()
systemService := application.NewSystemService(store, version)
server := httpapi.NewServer(cfg, logger, systemService, webassets.New(cfg.WebRoot))
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
errCh := make(chan error, 1)
go func() {
logger.Info("starting drive", "address", cfg.HTTPAddress, "version", version)
errCh <- server.ListenAndServe()
}()
select {
case err := <-errCh:
if errors.Is(err, httpapi.ErrServerClosed) {
return nil
}
return err
case <-ctx.Done():
shutdownCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
return server.Shutdown(shutdownCtx)
}
}