Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

178 lines
5.1 KiB
Go

package main
import (
"91porn-server/common/cachev2"
"91porn-server/common/dataReport"
"91porn-server/common/services"
"context"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"91porn-server/app/api/updownctrl"
"91porn-server/app/appg"
"91porn-server/app/router"
"91porn-server/app/service/activityclient"
"91porn-server/app/service/imser"
"91porn-server/common"
"91porn-server/common/conf"
"91porn-server/common/constant"
_ "91porn-server/common/daichong"
"91porn-server/common/db"
"91porn-server/common/email"
"91porn-server/common/filter"
"91porn-server/common/httputil"
"91porn-server/common/laosiji_app"
"91porn-server/common/log"
recommendqueue "91porn-server/common/shortrecommend"
"91porn-server/common/sms"
"91porn-server/common/tg"
"91porn-server/models"
"91porn-server/models/Init"
_ "91porn-server/models/commod"
_ "91porn-server/models/v/moduleconfmod" // swagger依赖
_ "91porn-server/models/v/productmod"
_ "91porn-server/models/v/rchgamtmod" // swagger依赖
_ "91porn-server/models/v/recommod" // swagger依赖
_ "91porn-server/models/v/sourcemod"
_ "91porn-server/models/v/systemmod"
_ "91porn-server/models/v/txnmod" // swagger
_ "91porn-server/models/v/usermod" // swagger依赖
_ "91porn-server/models/v/versionmod"
_ "91porn-server/models/v/videocoupon" // swagger依赖
_ "91porn-server/models/v/vidmod" // swagger
_ "91porn-server/models/v/walletmod"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
var httpServer *http.Server
// @title app文档
// @version 1.0
// @description 短视频服务后端API接口文档
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
func init() {
cfg := appg.GlobalConfig{}
if err := conf.LoadJSON("config/app.json", &cfg); err != nil {
fmt.Printf("startUp get config error: %v\n", err)
os.Exit(1)
}
fmt.Println("use local config successfully")
//加载配置
appg.Conf = &cfg
log.Init(log.Options{Level: appg.Conf.Log.Level, DisableStack: appg.Conf.Log.DisableStacktrace})
sms.Init(appg.Conf.SMS)
laosiji_app.Init(appg.Conf.LaoSiJiAiMate)
common.InitGinSecret(appg.Conf.Base.ResKey, appg.Conf.Base.ResKey360, appg.Conf.Base.Env)
if cfg.Base.Env == constant.ProdEnv {
appg.Bot = tg.New(tg.TianTian_Bot, fmt.Sprintf("短视频[env:%s]", appg.Conf.Base.Env))
common.SetPanicHandler(func(s string) { _ = appg.Bot.Send(tg.Msg{ChatId: tg.ChatIdServerTeam, Text: "[App-Server]" + s}) })
}
}
// @host 127.0.0.1:9009
// @BasePath
func main() {
time.Local, _ = time.LoadLocation("Asia/Shanghai")
common.Go(startUp)
waitQuit()
}
func startUp() {
//初始化数据库
ds := db.InitDS(appg.InitMongodbParam(models.RegisterPool))
if len(ds) > 0 {
for k, v := range ds {
switch k {
case models.VideoDb:
appg.VideoDB = v
case models.LogDb:
appg.LogDB = v
case models.StatDb:
appg.StatDB = v
}
}
}
appg.ProxyCfg = &httputil.ProxyCfg{
Host: appg.Conf.URL.HttpProxy,
IsActive: false,
}
dataReport.Init(dataReport.Config{
ApiUrl: appg.Conf.DataReport.Url,
})
//初始化静态配置
appg.InitStatic()
// 初始化Redis
appg.InitRedis()
if err := recommendqueue.SetKeyTTLHours(appg.Conf.ShortRecommendKeyTTL()); err != nil {
log.Error("short recommend key TTL config invalid, use default",
log.E(err), log.Any("configuredHours", appg.Conf.ShortRecommendKeyTTL()))
_ = recommendqueue.SetKeyTTLHours(72)
}
services.Init(appg.Redis)
// 初始化缓存操作中间件
cachev2.Init(appg.Redis, log.ZapLog)
// 初始化ElasticSearch
appg.InitElastic()
Init.InitMongo()
Init.ESInit()
Init.InitCache()
// init email service
_ = email.MustInit(context.TODO(), appg.Conf.AWS.SES)
// 初始化文本过滤器
filter.Start()
// 启动时异步取一次 IM appToken + 每小时刷新(不阻断启动)
imser.InitAppToken()
// 启动活动服定时同步
activityclient.Start()
//开始http
ginRouter := router.SetupGin()
ginRouter.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
port := appg.Conf.Base.Port
httpServer = &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: ginRouter,
}
log.Info("Start Listen ...", log.Any("port", port))
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal("server listen err", log.E(err))
}
// Block Here
log.Info("httpServer quit...")
}
func waitQuit() {
//graceful exit
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
<-ch
log.Info("Recv Signal, Shutdown Server Start...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if httpServer != nil {
if err := httpServer.Shutdown(ctx); err != nil {
log.Error("Server Shutdown error", log.E(err))
}
}
db.CloseDS()
updownctrl.FlushM3u8RefererStats() // 退出前把进程内聚合的来源计数刷回 Redis,减少丢失
if err := appg.RedisClose(); err != nil {
log.Error("redis close error", log.E(err))
return
}
log.Warn("Shutdown Server OK...")
}