You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

134 lines
4.6 KiB

package main
import (
"context"
"yunyan/comm"
"yunyan/lego"
"yunyan/modules/api"
"yunyan/modules/svccfg"
"yunyan/services"
"yunyan/sys/email"
"yunyan/sys/microsoft/translate"
"yunyan/sys/tencentyun/cos"
"flag"
"fmt"
"os"
"yunyan/lego/base/rpcx"
"yunyan/lego/core"
"yunyan/lego/sys/log"
"yunyan/lego/sys/mysql"
"yunyan/lego/sys/pools"
"yunyan/lego/sys/postgres"
redissys "yunyan/lego/sys/redis"
)
/*
服务类型:ai服务
*/
var (
conf = flag.String("conf", "./conf/api.yaml", "获取需要启动的服务配置文件") //启动服务的Id
)
func main() {
flag.Parse()
s := NewService(
rpcx.SetConfPath(*conf),
rpcx.SetVersion("1.0.0.0"),
)
s.OnInstallComp( //装备组件
services.NewHttpRouteComp(),
)
lego.Run(s, //运行模块
api.NewModule(),
svccfg.NewModule(), //服务配置管理:接收配置下发,重载本服务持有的 email 客户端
)
}
func NewService(ops ...rpcx.Option) core.IService {
s := new(Service)
s.Configure(ops...)
return s
}
// worker 的服务对象定义
type Service struct {
services.ServiceBase
}
// 初始化worker需要的一些系统工具
func (this *Service) InitSys() {
this.ServiceBase.InitSys()
pools.Add(comm.Pool_UserSession, func() comm.IUserSession { return comm.NewUserSession() })
//公共库(PostgreSQL/Supabase,含只读副本)——先连,它是「服务配置托管」的 bootstrap(要先连它才能读库配置)。
if err := postgres.OnInit(this.GetSettings().Sys["postgres"]); err != nil {
panic(fmt.Sprintf("init sys.postgres err: %s", err.Error()))
} else {
log.Infof("init sys.postgres success!")
}
// 服务配置托管:库优先、无则读文件回写(seed)。应用标识由部署 .env 注入(APP_NAME/APP_REGION),
// FIELD_ENCRYPT_KEY 需与 console 一致。未配 APP_NAME 则跳过、保持纯文件配置(不产生孤儿数据)。
// 命中库配置时就地覆盖 Sys(mysql/redis/cos…),随后各 OnInit 使用被覆盖后的值。
appName, region, encKey := os.Getenv("APP_NAME"), os.Getenv("APP_REGION"), os.Getenv("FIELD_ENCRYPT_KEY")
if seeded, err := comm.LoadOrSeedServiceConfig(encKey, appName, region, "api", this.GetSettings().Sys); err != nil {
log.Warnf("init service config 托管失败(降级为纯文件配置): %s", err.Error())
} else if appName != "" {
if seeded {
log.Infof("init service config: 首次 seed 文件配置 → console 共享库 (app=%s region=%s)", appName, region)
} else {
log.Infof("init service config: 已从 console 共享库加载并覆盖文件配置 (app=%s region=%s)", appName, region)
}
}
//业务库(MySQL)
if err := mysql.OnInit(this.GetSettings().Sys["mysql"]); err != nil {
panic(fmt.Sprintf("init sys.mysql err: %s", err.Error()))
} else {
log.Infof("init sys.mysql success!")
}
// 业务功能配置:**只读覆盖、不 seed**(yaml 属主是 home,见 comm.ModuleConfigOwner)。
// 必须早于下面的 email.OnInit——api 自己也发邮件,若用 api.yaml 的旧值就会与 home 用的库值不一致。
// 失败则降级用 yaml 默认、不阻断启动。
if err := comm.LoadModuleConfig(mysql.GetSys(), os.Getenv("FIELD_ENCRYPT_KEY"), this.GetSettings().Sys); err != nil {
log.Errorf("load module config err (回退 yaml 默认): %s", err.Error())
} else {
log.Infof("load module config success!")
}
//Redis
if err := redissys.OnInit(this.GetSettings().Sys["redis"]); err != nil {
panic(fmt.Sprintf("init sys.redis err: %s", err.Error()))
} else {
log.Infof("init sys.redis success!")
}
if err := cos.OnInit(this.GetSettings().Sys["cos"]); err != nil {
panic(fmt.Sprintf("init sys.cos err: %s", err.Error()))
} else {
log.Infof("init sys.cos success!")
}
if err := email.OnInit(this.GetSettings().Sys["email"]); err != nil {
panic(fmt.Sprintf("init sys.email err: %s", err.Error()))
} else {
log.Infof("init sys.email success!")
}
if err := translate.OnInit(this.GetSettings().Sys["translate"]); err != nil {
log.Warnf("init sys.translate err: %s (翻译服务未配置,翻译功能不可用)", err.Error())
} else {
log.Infof("init sys.translate success!")
}
// 业务功能配置热重载:登记本服务可热更的 sys 与重载上下文(须在各 sys OnInit 之后)。见 configreload.go。
this.setupModuleReload()
}
func (this *Service) GetUserSession(ctx context.Context, meta map[string]string) (session comm.IUserSession) {
session = pools.Get[comm.IUserSession](comm.Pool_UserSession)
session.SetSession(ctx, meta)
return
}
func (this *Service) PutUserSession(session comm.IUserSession) {
session.Reset()
pools.Put(comm.Pool_UserSession, session)
}