Some checks failed
CI / Build & Test (push) Failing after 40s
- kernel/plugin: 定义 Plugin 接口(Metadata/FxOption/SetupRoutes/Init) - kernel/plugin: 全局 Registry(Register/All/InitAll/Reset) - modules/example: 完整 4 层示例插件,实现 Plugin 接口 - config: 新增 PluginConfig(enabled 列表) - app.go: 集成插件系统 — fx.Invoke 注册 + plugin.All() 路由 + InitAll 生命周期
141 lines
3.8 KiB
Go
141 lines
3.8 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"mengstack/internal/app/cache"
|
|
"mengstack/internal/app/database"
|
|
"mengstack/internal/app/health"
|
|
"mengstack/internal/app/middleware"
|
|
"mengstack/internal/config"
|
|
"mengstack/internal/kernel/plugin"
|
|
"mengstack/internal/logger"
|
|
authinterfaces "mengstack/internal/modules/auth/interfaces"
|
|
rbacinterfaces "mengstack/internal/modules/rbac/interfaces"
|
|
orginterfaces "mengstack/internal/modules/org/interfaces"
|
|
auditinterfaces "mengstack/internal/modules/audit/interfaces"
|
|
settingsinterfaces "mengstack/internal/modules/settings/interfaces"
|
|
notificationinterfaces "mengstack/internal/modules/notification/interfaces"
|
|
exampleinterfaces "mengstack/internal/modules/example/interfaces"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/redis/go-redis/v9"
|
|
"go.uber.org/fx"
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
|
|
swaggerFiles "github.com/swaggo/files"
|
|
ginSwagger "github.com/swaggo/gin-swagger"
|
|
)
|
|
|
|
var Module = fx.Module("app",
|
|
fx.Provide(newEngine),
|
|
fx.Provide(newServer),
|
|
fx.Invoke(registerLifecycle),
|
|
)
|
|
|
|
func newEngine(
|
|
cfg *config.Config,
|
|
log *zap.Logger,
|
|
db *gorm.DB,
|
|
rdb *redis.Client,
|
|
authHandler *authinterfaces.Handler,
|
|
authMW gin.HandlerFunc,
|
|
rbacHandler *rbacinterfaces.Handler,
|
|
orgHandler *orginterfaces.Handler,
|
|
auditHandler *auditinterfaces.Handler,
|
|
settingsHandler *settingsinterfaces.Handler,
|
|
notificationHandler *notificationinterfaces.Handler,
|
|
) *gin.Engine {
|
|
ginMode := "release"
|
|
if cfg.Server.Mode == "debug" || cfg.Server.Mode == "dev" {
|
|
ginMode = "debug"
|
|
}
|
|
gin.SetMode(ginMode)
|
|
r := gin.New()
|
|
|
|
r.Use(middleware.RequestID())
|
|
r.Use(middleware.RequestLogger(log))
|
|
r.Use(middleware.SecurityHeaders())
|
|
r.Use(middleware.CORS())
|
|
r.Use(middleware.RateLimit(100, time.Minute))
|
|
r.Use(middleware.BodyLimit(10 << 20))
|
|
r.Use(middleware.Recovery(log))
|
|
|
|
healthHandler := health.NewHandler(db, rdb, log)
|
|
r.GET("/health", healthHandler.Handle)
|
|
|
|
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
|
|
|
authinterfaces.SetupRoutes(r, authHandler, authMW)
|
|
rbacinterfaces.SetupRoutes(r, rbacHandler, authMW)
|
|
orginterfaces.SetupRoutes(r, orgHandler, authMW)
|
|
auditinterfaces.SetupRoutes(r, auditHandler, authMW)
|
|
settingsinterfaces.SetupRoutes(r, settingsHandler, authMW)
|
|
notificationinterfaces.SetupRoutes(r, notificationHandler, authMW)
|
|
|
|
for _, p := range plugin.All() {
|
|
p.SetupRoutes(r, authMW)
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func newServer(cfg *config.Config, engine *gin.Engine) *http.Server {
|
|
return &http.Server{
|
|
Addr: fmt.Sprintf(":%d", cfg.Server.Port),
|
|
Handler: engine,
|
|
ReadTimeout: 15 * time.Second,
|
|
WriteTimeout: 15 * time.Second,
|
|
IdleTimeout: 60 * time.Second,
|
|
}
|
|
}
|
|
|
|
func registerLifecycle(lc fx.Lifecycle, srv *http.Server, log *zap.Logger) {
|
|
lc.Append(fx.Hook{
|
|
OnStart: func(ctx context.Context) error {
|
|
if err := plugin.InitAll(log); err != nil {
|
|
return err
|
|
}
|
|
log.Info("server starting", zap.String("addr", srv.Addr))
|
|
go func() {
|
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
log.Error("server error", zap.Error(err))
|
|
}
|
|
}()
|
|
return nil
|
|
},
|
|
OnStop: func(ctx context.Context) error {
|
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
log.Info("server shutting down")
|
|
return srv.Shutdown(shutdownCtx)
|
|
},
|
|
})
|
|
}
|
|
|
|
func NewApp() *fx.App {
|
|
return fx.New(
|
|
fx.Provide(
|
|
func() (*config.Config, error) { return config.Load() },
|
|
func(cfg *config.Config) (*zap.Logger, error) { return logger.New(cfg.Log) },
|
|
),
|
|
database.Module,
|
|
cache.Module,
|
|
authinterfaces.Module,
|
|
rbacinterfaces.Module,
|
|
orginterfaces.Module,
|
|
auditinterfaces.Module,
|
|
settingsinterfaces.Module,
|
|
notificationinterfaces.Module,
|
|
exampleinterfaces.Module,
|
|
fx.Invoke(func(p *exampleinterfaces.ExamplePlugin) {
|
|
plugin.Register(p)
|
|
}),
|
|
Module,
|
|
)
|
|
}
|