87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/syonad/clonepack/config"
|
|
"github.com/syonad/clonepack/internal/api"
|
|
"github.com/syonad/clonepack/internal/core"
|
|
"github.com/syonad/clonepack/internal/store"
|
|
)
|
|
|
|
var serveCmd = &cobra.Command{
|
|
Use: "serve",
|
|
Short: "Start the ClonePack HTTP server",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
cfg, err := config.Load(cfgFile)
|
|
if err != nil {
|
|
return fmt.Errorf("load config: %w", err)
|
|
}
|
|
|
|
setupLogger(cfg.Log)
|
|
|
|
db, err := store.Open(cfg.DB)
|
|
if err != nil {
|
|
return fmt.Errorf("open store: %w", err)
|
|
}
|
|
|
|
repoStore := store.NewRepoStore(db)
|
|
jobStore := store.NewCloneJobStore(db)
|
|
pendingStore := store.NewPendingPackageStore(db)
|
|
blockedStore := store.NewBlockedPackageStore(db)
|
|
snapshotStore := store.NewSnapshotStore(db)
|
|
|
|
repoSvc := core.NewRepoService(repoStore, cfg.DataDir)
|
|
cloneSvc := core.NewCloneService(repoStore, jobStore, cfg.DataDir)
|
|
snapshotSvc := core.NewSnapshotService(snapshotStore, repoStore, cfg.DataDir)
|
|
syncSvc := core.NewSyncService(repoStore, pendingStore, blockedStore, cloneSvc, snapshotSvc, cfg.DataDir)
|
|
|
|
repoH := api.NewRepoHandler(repoSvc)
|
|
cloneH := api.NewCloneHandler(cloneSvc)
|
|
syncH := api.NewSyncHandler(syncSvc)
|
|
snapshotH := api.NewSnapshotHandler(snapshotSvc)
|
|
proxyH := api.NewProxyHandler(repoSvc, cfg.DataDir)
|
|
router := api.NewRouter(repoH, cloneH, syncH, snapshotH, proxyH)
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer cancel()
|
|
|
|
syncSvc.StartScheduler(ctx, cfg.Sync.IntervalDuration())
|
|
|
|
addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
|
|
srv := &http.Server{Addr: addr, Handler: router}
|
|
|
|
go func() {
|
|
slog.Info("ClonePack listening", "addr", addr)
|
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
slog.Error("server error", "error", err)
|
|
}
|
|
}()
|
|
|
|
<-ctx.Done()
|
|
slog.Info("shutting down...")
|
|
|
|
shutdownCtx, cancel2 := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel2()
|
|
return srv.Shutdown(shutdownCtx)
|
|
},
|
|
}
|
|
|
|
func setupLogger(cfg config.LogConfig) {
|
|
opts := &slog.HandlerOptions{Level: cfg.SlogLevel()}
|
|
var handler slog.Handler
|
|
if cfg.Format == "json" {
|
|
handler = slog.NewJSONHandler(os.Stderr, opts)
|
|
} else {
|
|
handler = slog.NewTextHandler(os.Stderr, opts)
|
|
}
|
|
slog.SetDefault(slog.New(handler))
|
|
}
|