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 }