package webserver import ( "context" "flag" "fmt" "github.com/go-co-op/gocron" "github.com/gofiber/fiber/v2" futils "github.com/gofiber/fiber/v2/utils" "github.com/rs/zerolog" "go.uber.org/fx" "os" "runtime" "strings" "time" "web-qudo-be/app/database" "web-qudo-be/app/database/seeds" md "web-qudo-be/app/middleware" articlesService "web-qudo-be/app/module/articles/service" "web-qudo-be/app/router" "web-qudo-be/config/config" "web-qudo-be/utils/response" ) // NewFiber : initialize the webserver func NewFiber(cfg *config.Config) *fiber.App { // setup app := fiber.New(fiber.Config{ ServerHeader: cfg.App.Name, AppName: cfg.App.Name, Prefork: cfg.App.Prefork, ErrorHandler: response.ErrorHandler, IdleTimeout: cfg.App.IdleTimeout * time.Second, EnablePrintRoutes: cfg.App.PrintRoutes, BodyLimit: cfg.App.BodyLimit, DisableStartupMessage: true, ReadBufferSize: 8192, }) // pass production config to check it response.IsProduction = cfg.App.Production return app } // Start : function to start webserver func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router *router.Router, middlewares *md.Middleware, db *database.Database, log zerolog.Logger) { lifecycle.Append( fx.Hook{ OnStart: func(ctx context.Context) error { // Connect database db.ConnectDatabase() // Register middlewares middlewares.Register(db) // Register routes router.Register() // Custom Startup Messages host, port := config.ParseAddress(cfg.App.Port) if host == "" { if fiber.Config().Network == "tcp6" { host = "[::1]" } else { host = "0.0.0.0" } } // ASCII Art ascii, err := os.ReadFile("./storage/ascii_art.txt") if err != nil { log.Debug().Err(err).Msg("An unknown error occurred when to print ASCII art!") } for _, line := range strings.Split(futils.UnsafeString(ascii), "\n") { log.Info().Msg(line) } // Information message log.Info().Msg(fiber.Config().AppName + " is running at the moment!") // Debug informations if !cfg.App.Production { prefork := "Enabled" procs := runtime.GOMAXPROCS(0) if !cfg.App.Prefork { procs = 1 prefork = "Disabled" } log.Debug().Msgf("Version: %s", "-") log.Debug().Msgf("Host: %s", host) log.Debug().Msgf("Port: %s", port) log.Debug().Msgf("Prefork: %s", prefork) log.Debug().Msgf("Handlers: %d", fiber.HandlersCount()) log.Debug().Msgf("Processes: %d", procs) log.Debug().Msgf("PID: %d", os.Getpid()) } // Listen the app (with TLS Support) //if cfg.App.TLS.Enable { // log.Debug().Msg("TLS support was enabled.") // // if err := fiber.ListenTLS(cfg.App.Port, cfg.App.TLS.CertFile, cfg.App.TLS.KeyFile); err != nil { // log.Error().Err(err).Msg("An unknown error occurred when to run server!") // } //} go func() { if err := fiber.Listen(cfg.App.Port); err != nil { log.Error().Err(err).Msg("An unknown error occurred when to run server!") } }() migrateFlag := flag.Bool("migrate", db.Cfg.DB.Postgres.Migrate, "migrate the database") seedFlag := flag.Bool("seed", db.Cfg.DB.Postgres.Seed, "seed the database") flag.Parse() // read flag -migrate to migrate the database if *migrateFlag { db.MigrateModels() } // read flag -seed to seed the database if *seedFlag { // init seed models masterStatusSeeder := seeds.MasterStatusesSeeder{} masterApprovalStatusSeeder := seeds.MasterApprovalStatusesSeeder{} activityLogsSeeder := seeds.ActivityLogsSeeder{} approvalWorkflowsSeeder := seeds.ApprovalWorkflowsSeeder{} allSeeders := []database.Seeder{masterStatusSeeder, masterApprovalStatusSeeder, activityLogsSeeder, approvalWorkflowsSeeder} db.SeedModels(allSeeders) } return nil }, OnStop: func(ctx context.Context) error { log.Info().Msg("Shutting down the app...") if err := fiber.Shutdown(); err != nil { log.Panic().Err(err).Msg("") } log.Info().Msg("Running cleanup tasks...") log.Info().Msg("1- Shutdown the database") db.ShutdownDatabase() log.Info().Msgf("%s was successful shutdown.", cfg.App.Name) log.Info().Msg("\u001b[96msee you again👋\u001b[0m") return nil }, }, ) } func RunScheduling(lifecycle fx.Lifecycle, articleService articlesService.ArticlesService) *gocron.Scheduler { scheduler := gocron.NewScheduler(time.UTC) // Tambahkan tugas yang berjalan setiap 10 detik scheduler.Every(1).Minutes().SingletonMode().Do(func() { fmt.Println("Run Scheduler", time.Now()) err := articleService.ExecuteScheduling() if err != nil { fmt.Println("Scheduler Got An Error", time.Now()) } }) // Menambahkan lifecycle hooks di Fx lifecycle.Append(fx.Hook{ OnStart: func(ctx context.Context) error { fmt.Println("Memulai scheduler...") scheduler.StartAsync() // Mulai scheduler saat aplikasi dimulai return nil }, OnStop: func(ctx context.Context) error { fmt.Println("Menghentikan scheduler...") scheduler.Stop() // Hentikan scheduler saat aplikasi dihentikan return nil }, }) return scheduler }