mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 09:13:49 +08:00
120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"path/filepath"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/bddjr/hlfhr"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-gormigrate/gormigrate/v2"
|
|
"github.com/gookit/validate"
|
|
"github.com/robfig/cron/v3"
|
|
|
|
"github.com/acepanel/panel/pkg/config"
|
|
"github.com/acepanel/panel/pkg/queue"
|
|
)
|
|
|
|
type Ace struct {
|
|
conf *config.Config
|
|
router *chi.Mux
|
|
server *hlfhr.Server
|
|
migrator *gormigrate.Gormigrate
|
|
cron *cron.Cron
|
|
queue *queue.Queue
|
|
}
|
|
|
|
func NewAce(conf *config.Config, router *chi.Mux, server *hlfhr.Server, migrator *gormigrate.Gormigrate, cron *cron.Cron, queue *queue.Queue, _ *validate.Validation) *Ace {
|
|
return &Ace{
|
|
conf: conf,
|
|
router: router,
|
|
server: server,
|
|
migrator: migrator,
|
|
cron: cron,
|
|
queue: queue,
|
|
}
|
|
}
|
|
|
|
func (r *Ace) Run() error {
|
|
// migrate database
|
|
if err := r.migrator.Migrate(); err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("[DB] database migrated")
|
|
|
|
// start cron scheduler
|
|
r.cron.Start()
|
|
fmt.Println("[CRON] cron scheduler started")
|
|
|
|
// create context for queue
|
|
queueCtx, queueCancel := context.WithCancel(context.Background())
|
|
defer queueCancel()
|
|
|
|
// start queue
|
|
r.queue.Run(queueCtx)
|
|
|
|
// setup graceful shutdown
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
// run http server in goroutine
|
|
serverErr := make(chan error, 1)
|
|
go func() {
|
|
if r.conf.HTTP.TLS {
|
|
cert := filepath.Join(Root, "panel/storage/cert.pem")
|
|
key := filepath.Join(Root, "panel/storage/cert.key")
|
|
fmt.Println("[HTTP] listening and serving on port", r.conf.HTTP.Port, "with tls")
|
|
if err := r.server.ListenAndServeTLS(cert, key); !errors.Is(err, http.ErrServerClosed) {
|
|
serverErr <- err
|
|
}
|
|
} else {
|
|
fmt.Println("[HTTP] listening and serving on port", r.conf.HTTP.Port)
|
|
if err := r.server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
|
serverErr <- err
|
|
}
|
|
}
|
|
close(serverErr)
|
|
}()
|
|
|
|
// wait for shutdown signal or server error
|
|
select {
|
|
case err := <-serverErr:
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case sig := <-quit:
|
|
fmt.Println("\n[APP] received signal:", sig)
|
|
}
|
|
|
|
// graceful shutdown
|
|
fmt.Println("[APP] shutting down gracefully...")
|
|
|
|
// stop cron scheduler
|
|
ctx := r.cron.Stop()
|
|
<-ctx.Done()
|
|
fmt.Println("[CRON] cron scheduler stopped")
|
|
|
|
// stop queue
|
|
queueCancel()
|
|
fmt.Println("[QUEUE] queue stopped")
|
|
|
|
// shutdown http server
|
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer shutdownCancel()
|
|
|
|
if err := r.server.Shutdown(shutdownCtx); err != nil {
|
|
fmt.Println("[HTTP] server shutdown error:", err)
|
|
return err
|
|
}
|
|
fmt.Println("[HTTP] server stopped")
|
|
|
|
fmt.Println("[APP] shutdown complete")
|
|
return nil
|
|
}
|