126 lines
4.0 KiB
Go
126 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"jiggablend/internal/api"
|
|
"jiggablend/internal/auth"
|
|
"jiggablend/internal/database"
|
|
"jiggablend/internal/logger"
|
|
"jiggablend/internal/storage"
|
|
)
|
|
|
|
func main() {
|
|
var (
|
|
port = flag.String("port", getEnv("PORT", "8080"), "Server port")
|
|
dbPath = flag.String("db", getEnv("DB_PATH", "jiggablend.db"), "Database path")
|
|
storagePath = flag.String("storage", getEnv("STORAGE_PATH", "./jiggablend-storage"), "Storage path")
|
|
logDir = flag.String("log-dir", getEnv("LOG_DIR", "./logs"), "Log directory")
|
|
logMaxSize = flag.Int("log-max-size", getEnvInt("LOG_MAX_SIZE", 100), "Maximum log file size in MB before rotation")
|
|
logMaxBackups = flag.Int("log-max-backups", getEnvInt("LOG_MAX_BACKUPS", 5), "Maximum number of rotated log files to keep")
|
|
logMaxAge = flag.Int("log-max-age", getEnvInt("LOG_MAX_AGE", 30), "Maximum age in days for rotated log files")
|
|
)
|
|
flag.Parse()
|
|
|
|
// Initialize logger (writes to both stdout and log file with rotation)
|
|
logDirPath := *logDir
|
|
if err := logger.Init(logDirPath, "manager.log", *logMaxSize, *logMaxBackups, *logMaxAge); err != nil {
|
|
log.Fatalf("Failed to initialize logger: %v", err)
|
|
}
|
|
defer func() {
|
|
if l := logger.GetDefault(); l != nil {
|
|
l.Close()
|
|
}
|
|
}()
|
|
log.Printf("Log rotation configured: max_size=%dMB, max_backups=%d, max_age=%d days", *logMaxSize, *logMaxBackups, *logMaxAge)
|
|
|
|
// Initialize database
|
|
db, err := database.NewDB(*dbPath)
|
|
if err != nil {
|
|
log.Fatalf("Failed to initialize database: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Initialize auth
|
|
authHandler, err := auth.NewAuth(db.DB)
|
|
if err != nil {
|
|
log.Fatalf("Failed to initialize auth: %v", err)
|
|
}
|
|
|
|
// Initialize storage
|
|
storageHandler, err := storage.NewStorage(*storagePath)
|
|
if err != nil {
|
|
log.Fatalf("Failed to initialize storage: %v", err)
|
|
}
|
|
|
|
// Check if Blender is available (required for metadata extraction)
|
|
if err := checkBlenderAvailable(); err != nil {
|
|
log.Fatalf("Blender is not available: %v\n"+
|
|
"The manager requires Blender to be installed and in PATH for metadata extraction.\n"+
|
|
"Please install Blender and ensure it's accessible via the 'blender' command.", err)
|
|
}
|
|
log.Printf("Blender is available")
|
|
|
|
// Create API server
|
|
server, err := api.NewServer(db, authHandler, storageHandler)
|
|
if err != nil {
|
|
log.Fatalf("Failed to create server: %v", err)
|
|
}
|
|
|
|
// Start server with increased request body size limit for large file uploads
|
|
addr := fmt.Sprintf(":%s", *port)
|
|
log.Printf("Starting manager server on %s", addr)
|
|
log.Printf("Database: %s", *dbPath)
|
|
log.Printf("Storage: %s", *storagePath)
|
|
|
|
httpServer := &http.Server{
|
|
Addr: addr,
|
|
Handler: server,
|
|
MaxHeaderBytes: 1 << 20, // 1 MB for headers
|
|
ReadTimeout: 0, // No read timeout (for large uploads)
|
|
WriteTimeout: 0, // No write timeout (for large uploads)
|
|
}
|
|
|
|
// Note: MaxRequestBodySize is not directly configurable in http.Server
|
|
// It's handled by ParseMultipartForm in handlers, which we've already configured
|
|
// But we need to ensure the server can handle large requests
|
|
// The default limit is 10MB, but we bypass it by using ParseMultipartForm with larger limit
|
|
|
|
if err := httpServer.ListenAndServe(); err != nil {
|
|
log.Fatalf("Server failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvInt(key string, defaultValue int) int {
|
|
if value := os.Getenv(key); value != "" {
|
|
var result int
|
|
if _, err := fmt.Sscanf(value, "%d", &result); err == nil {
|
|
return result
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// checkBlenderAvailable checks if Blender is available by running `blender --version`
|
|
func checkBlenderAvailable() error {
|
|
cmd := exec.Command("blender", "--version")
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to run 'blender --version': %w (output: %s)", err, string(output))
|
|
}
|
|
// If we got here, Blender is available
|
|
return nil
|
|
}
|