Files
2025-12-13 15:31:52 +00:00

96 lines
2.5 KiB
Go

package main
import (
"context"
"database/sql"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/example/storage-appliance/internal/audit"
httpin "github.com/example/storage-appliance/internal/http"
"github.com/example/storage-appliance/internal/infra/osexec"
"github.com/example/storage-appliance/internal/infra/sqlite/db"
"github.com/example/storage-appliance/internal/infra/zfs"
"github.com/example/storage-appliance/internal/service/mock"
"github.com/example/storage-appliance/internal/service/storage"
_ "github.com/glebarez/sqlite"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
)
func main() {
ctx := context.Background()
// Connect simple sqlite DB (file)
dsn := "file:appliance.db?_foreign_keys=on"
sqldb, err := sql.Open("sqlite", dsn)
if err != nil {
log.Fatalf("open db: %v", err)
}
defer sqldb.Close()
// Run migrations and seed admin
if err := db.MigrateAndSeed(ctx, sqldb); err != nil {
log.Fatalf("migrate: %v", err)
}
r := chi.NewRouter()
uuidMiddleware := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rid := uuid.New().String()
rw := w
r = r.WithContext(context.WithValue(r.Context(), httpin.ContextKeyRequestID, rid))
rw.Header().Set("X-Request-Id", rid)
next.ServeHTTP(rw, r)
})
}
// Attach router and app dependencies
// wire mocks for now; replace with real adapters in infra
diskSvc := &mock.MockDiskService{}
zfsSvc := &mock.MockZFSService{}
jobRunner := &mock.MockJobRunner{}
auditLogger := audit.NewSQLAuditLogger(sqldb)
zfsAdapter := zfs.NewAdapter(osexec.Default)
// storage service wiring: use zfsAdapter and jobRunner and audit logger
storageSvc := storage.NewStorageService(zfsAdapter, jobRunner, auditLogger)
app := &httpin.App{
DB: sqldb,
DiskSvc: diskSvc,
ZFSSvc: zfsSvc,
JobRunner: jobRunner,
HTTPClient: &http.Client{},
StorageSvc: storageSvc,
}
r.Use(uuidMiddleware)
httpin.RegisterRoutes(r, app)
srv := &http.Server{
Addr: ":8080",
Handler: r,
}
// graceful shutdown
go func() {
log.Printf("Starting server on %s", srv.Addr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server error: %v", err)
}
}()
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
ctxShut, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctxShut); err != nil {
log.Fatalf("server shutdown failed: %v", err)
}
log.Println("server stopped")
}