214 lines
4.8 KiB
Go
214 lines
4.8 KiB
Go
package factory
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
|
||
"git.toowon.com/jimmy/go-common/captcha"
|
||
"git.toowon.com/jimmy/go-common/email"
|
||
"git.toowon.com/jimmy/go-common/i18n"
|
||
"git.toowon.com/jimmy/go-common/logger"
|
||
"git.toowon.com/jimmy/go-common/mcp"
|
||
"git.toowon.com/jimmy/go-common/sms"
|
||
"git.toowon.com/jimmy/go-common/storage"
|
||
"github.com/redis/go-redis/v9"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// Module 可预热的模块标识(用于 Warmup)
|
||
type Module string
|
||
|
||
const (
|
||
ModuleLogger Module = "logger"
|
||
ModuleDatabase Module = "database"
|
||
ModuleRedis Module = "redis"
|
||
ModuleStorage Module = "storage"
|
||
ModuleEmail Module = "email"
|
||
ModuleSMS Module = "sms"
|
||
ModuleI18n Module = "i18n"
|
||
ModuleMCP Module = "mcp"
|
||
ModuleCaptcha Module = "captcha"
|
||
)
|
||
|
||
// MustInit 从配置文件初始化全局 Factory;失败则 panic(适合 main 启动)
|
||
func MustInit(filePath string, opts ...Option) *Factory {
|
||
if err := Init(filePath, opts...); err != nil {
|
||
panic(err)
|
||
}
|
||
return Default()
|
||
}
|
||
|
||
// Warmup 按需预热模块:配置缺失或连接失败时立即返回错误(适合启动期 fail-fast)
|
||
func (f *Factory) Warmup(modules ...Module) error {
|
||
if f == nil {
|
||
return fmt.Errorf("factory is nil")
|
||
}
|
||
for _, m := range modules {
|
||
var err error
|
||
switch m {
|
||
case ModuleLogger:
|
||
_, err = f.Logger()
|
||
case ModuleDatabase:
|
||
_, err = f.Database()
|
||
case ModuleRedis:
|
||
_, err = f.Redis()
|
||
case ModuleStorage:
|
||
_, err = f.Storage()
|
||
case ModuleEmail:
|
||
_, err = f.Email()
|
||
case ModuleSMS:
|
||
_, err = f.SMS()
|
||
case ModuleI18n:
|
||
_, err = f.I18n()
|
||
case ModuleMCP:
|
||
_, err = f.MCP()
|
||
case ModuleCaptcha:
|
||
_, err = f.Captcha()
|
||
default:
|
||
return fmt.Errorf("unknown module: %s", m)
|
||
}
|
||
if err != nil {
|
||
return fmt.Errorf("warmup %s: %w", m, err)
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// Close 关闭已创建的有状态模块(email / sms / redis / database / logger)
|
||
// 可重复调用;未初始化的模块会被跳过。
|
||
func (f *Factory) Close() error {
|
||
if f == nil {
|
||
return nil
|
||
}
|
||
|
||
f.mu.Lock()
|
||
defer f.mu.Unlock()
|
||
|
||
var errs []error
|
||
|
||
if f.email != nil {
|
||
if err := f.email.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("email: %w", err))
|
||
}
|
||
f.email = nil
|
||
}
|
||
if f.sms != nil {
|
||
if err := f.sms.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("sms: %w", err))
|
||
}
|
||
f.sms = nil
|
||
}
|
||
if f.redis != nil {
|
||
if err := f.redis.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("redis: %w", err))
|
||
}
|
||
f.redis = nil
|
||
}
|
||
if f.db != nil {
|
||
if sqlDB, err := f.db.DB(); err != nil {
|
||
errs = append(errs, fmt.Errorf("database: %w", err))
|
||
} else if err := sqlDB.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("database: %w", err))
|
||
}
|
||
f.db = nil
|
||
}
|
||
if f.mcp != nil {
|
||
if err := f.mcp.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("mcp: %w", err))
|
||
}
|
||
f.mcp = nil
|
||
}
|
||
if f.logger != nil {
|
||
if err := f.logger.Close(); err != nil {
|
||
errs = append(errs, fmt.Errorf("logger: %w", err))
|
||
}
|
||
f.logger = nil
|
||
}
|
||
|
||
// 中间件链依赖 logger/i18n,关闭后允许下次重新组装
|
||
f.chain = nil
|
||
|
||
return errors.Join(errs...)
|
||
}
|
||
|
||
// MustLogger 获取日志对象;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustLogger() *logger.Logger {
|
||
l, err := f.Logger()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return l
|
||
}
|
||
|
||
// MustDatabase 获取数据库连接;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustDatabase() *gorm.DB {
|
||
db, err := f.Database()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return db
|
||
}
|
||
|
||
// MustRedis 获取 Redis 客户端;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustRedis() *redis.Client {
|
||
c, err := f.Redis()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return c
|
||
}
|
||
|
||
// MustStorage 获取存储对象;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustStorage() storage.Storage {
|
||
s, err := f.Storage()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return s
|
||
}
|
||
|
||
// MustEmail 获取邮件客户端;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustEmail() *email.Email {
|
||
e, err := f.Email()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return e
|
||
}
|
||
|
||
// MustSMS 获取短信客户端;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustSMS() *sms.SMS {
|
||
s, err := f.SMS()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return s
|
||
}
|
||
|
||
// MustI18n 获取国际化对象;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustI18n() *i18n.I18n {
|
||
i, err := f.I18n()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return i
|
||
}
|
||
|
||
// MustMCP 获取 MCP 工具子系统对象;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustMCP() mcp.Manager {
|
||
m, err := f.MCP()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return m
|
||
}
|
||
|
||
// MustCaptcha 获取图形验证码子系统对象;失败则 panic(适合启动期注入)
|
||
func (f *Factory) MustCaptcha() captcha.Manager {
|
||
c, err := f.Captcha()
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return c
|
||
}
|