复制项目
This commit is contained in:
307
internal/tools/cron/cron_task.go
Normal file
307
internal/tools/cron/cron_task.go
Normal file
@@ -0,0 +1,307 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/common/config"
|
||||
disetcd "git.imall.cloud/openim/open-im-server-deploy/pkg/common/discovery/etcd"
|
||||
mcache "git.imall.cloud/openim/open-im-server-deploy/pkg/common/storage/cache/mcache"
|
||||
redisCache "git.imall.cloud/openim/open-im-server-deploy/pkg/common/storage/cache/redis"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/common/storage/database"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/common/storage/database/mgo"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/dbbuild"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/notification"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/rpcli"
|
||||
pbconversation "git.imall.cloud/openim/protocol/conversation"
|
||||
"git.imall.cloud/openim/protocol/msg"
|
||||
"git.imall.cloud/openim/protocol/third"
|
||||
"github.com/openimsdk/tools/discovery"
|
||||
"github.com/openimsdk/tools/discovery/etcd"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
"github.com/openimsdk/tools/s3"
|
||||
"github.com/openimsdk/tools/s3/cont"
|
||||
"github.com/openimsdk/tools/s3/disable"
|
||||
"github.com/openimsdk/tools/s3/minio"
|
||||
"github.com/openimsdk/tools/utils/runtimeenv"
|
||||
"github.com/robfig/cron/v3"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
CronTask config.CronTask
|
||||
Share config.Share
|
||||
Discovery config.Discovery
|
||||
Mongo config.Mongo
|
||||
Redis config.Redis
|
||||
Minio config.Minio
|
||||
Third config.Third
|
||||
Notification config.Notification
|
||||
}
|
||||
|
||||
func Start(ctx context.Context, conf *Config, client discovery.SvcDiscoveryRegistry, service grpc.ServiceRegistrar) error {
|
||||
log.CInfo(ctx, "CRON-TASK server is initializing", "runTimeEnv", runtimeenv.RuntimeEnvironment(), "chatRecordsClearTime", conf.CronTask.CronExecuteTime, "msgDestructTime", conf.CronTask.RetainChatRecords)
|
||||
if conf.CronTask.RetainChatRecords < 1 {
|
||||
log.ZInfo(ctx, "disable cron")
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
ctx = mcontext.SetOpUserID(ctx, conf.Share.IMAdminUser.UserIDs[0])
|
||||
|
||||
msgConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
thirdConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Third)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conversationConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Conversation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
groupConn, err := client.GetConn(ctx, conf.Discovery.RpcService.Group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化数据库连接(用于会议群聊解散)
|
||||
dbb := dbbuild.NewBuilder(&conf.Mongo, &conf.Redis)
|
||||
mgocli, err := dbb.Mongo(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
meetingDB, err := mgo.NewMeetingMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
systemConfigDB, err := mgo.NewSystemConfigMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msgDocDB, err := mgo.NewMsgMongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objectDB, err := mgo.NewS3Mongo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 初始化S3客户端和缓存(用于删除S3文件)
|
||||
rdb, err := dbb.Redis(ctx)
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Redis连接失败,S3文件删除功能可能受限", err)
|
||||
rdb = nil
|
||||
}
|
||||
var s3Client s3.Interface
|
||||
var s3Cache cont.S3Cache
|
||||
switch enable := conf.Third.Object.Enable; enable {
|
||||
case "minio":
|
||||
var minioCache minio.Cache
|
||||
if rdb == nil {
|
||||
mc, err := mgo.NewCacheMgo(mgocli.GetDB())
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "Mongo缓存初始化失败,S3文件删除功能可能受限", err)
|
||||
s3Client = disable.NewDisable()
|
||||
s3Cache = nil
|
||||
} else {
|
||||
minioCache = mcache.NewMinioCache(mc)
|
||||
s3Client, err = minio.NewMinio(ctx, minioCache, *conf.Minio.Build())
|
||||
if err != nil {
|
||||
log.ZError(ctx, "Minio初始化失败", err)
|
||||
return err
|
||||
}
|
||||
s3Cache = nil // MongoDB缓存模式下,S3Cache为nil
|
||||
}
|
||||
} else {
|
||||
minioCache = redisCache.NewMinioCache(rdb)
|
||||
s3Client, err = minio.NewMinio(ctx, minioCache, *conf.Minio.Build())
|
||||
if err != nil {
|
||||
log.ZError(ctx, "Minio初始化失败", err)
|
||||
return err
|
||||
}
|
||||
s3Cache = redisCache.NewS3Cache(rdb, s3Client)
|
||||
}
|
||||
case "":
|
||||
s3Client = disable.NewDisable()
|
||||
s3Cache = nil
|
||||
default:
|
||||
// 其他S3类型暂不支持,使用disable模式
|
||||
log.ZWarn(ctx, "S3类型不支持,使用disable模式", nil, "enable", enable)
|
||||
s3Client = disable.NewDisable()
|
||||
s3Cache = nil
|
||||
}
|
||||
|
||||
var locker Locker
|
||||
if conf.Discovery.Enable == config.ETCD {
|
||||
cm := disetcd.NewConfigManager(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient(), []string{
|
||||
conf.CronTask.GetConfigFileName(),
|
||||
conf.Share.GetConfigFileName(),
|
||||
conf.Discovery.GetConfigFileName(),
|
||||
})
|
||||
cm.Watch(ctx)
|
||||
locker, err = NewEtcdLocker(client.(*etcd.SvcDiscoveryRegistryImpl).GetClient())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if locker == nil {
|
||||
locker = emptyLocker{}
|
||||
}
|
||||
|
||||
// 初始化NotificationSender(用于发送删除消息通知)
|
||||
notificationSender := notification.NewNotificationSender(&conf.Notification,
|
||||
notification.WithRpcClient(func(ctx context.Context, req *msg.SendMsgReq) (*msg.SendMsgResp, error) {
|
||||
return msg.NewMsgClient(msgConn).SendMsg(ctx, req)
|
||||
}),
|
||||
)
|
||||
|
||||
srv := &cronServer{
|
||||
ctx: ctx,
|
||||
config: conf,
|
||||
cron: cron.New(),
|
||||
msgClient: msg.NewMsgClient(msgConn),
|
||||
conversationClient: pbconversation.NewConversationClient(conversationConn),
|
||||
thirdClient: third.NewThirdClient(thirdConn),
|
||||
groupClient: rpcli.NewGroupClient(groupConn),
|
||||
meetingDB: meetingDB,
|
||||
systemConfigDB: systemConfigDB,
|
||||
msgDocDB: msgDocDB,
|
||||
objectDB: objectDB,
|
||||
s3Client: s3Client,
|
||||
s3Cache: s3Cache,
|
||||
notificationSender: notificationSender,
|
||||
locker: locker,
|
||||
}
|
||||
|
||||
if err := srv.registerClearS3(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerDeleteMsg(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerClearUserMsg(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerDismissMeetingGroups(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerClearGroupMsgByConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.registerClearUserMsgByConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZDebug(ctx, "start cron task", "CronExecuteTime", conf.CronTask.CronExecuteTime)
|
||||
srv.cron.Start()
|
||||
log.ZDebug(ctx, "cron task server is running")
|
||||
<-ctx.Done()
|
||||
log.ZDebug(ctx, "cron task server is shutting down")
|
||||
srv.cron.Stop()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type Locker interface {
|
||||
ExecuteWithLock(ctx context.Context, taskName string, task func())
|
||||
}
|
||||
|
||||
type emptyLocker struct{}
|
||||
|
||||
func (emptyLocker) ExecuteWithLock(ctx context.Context, taskName string, task func()) {
|
||||
task()
|
||||
}
|
||||
|
||||
type cronServer struct {
|
||||
ctx context.Context
|
||||
config *Config
|
||||
cron *cron.Cron
|
||||
msgClient msg.MsgClient
|
||||
conversationClient pbconversation.ConversationClient
|
||||
thirdClient third.ThirdClient
|
||||
groupClient *rpcli.GroupClient
|
||||
meetingDB database.Meeting
|
||||
systemConfigDB database.SystemConfig
|
||||
msgDocDB database.Msg
|
||||
objectDB database.ObjectInfo
|
||||
s3Client s3.Interface
|
||||
s3Cache cont.S3Cache
|
||||
notificationSender *notification.NotificationSender
|
||||
locker Locker
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearS3() error {
|
||||
if c.config.CronTask.FileExpireTime <= 0 || len(c.config.CronTask.DeleteObjectType) == 0 {
|
||||
log.ZInfo(c.ctx, "disable scheduled cleanup of s3", "fileExpireTime", c.config.CronTask.FileExpireTime, "deleteObjectType", c.config.CronTask.DeleteObjectType)
|
||||
return nil
|
||||
}
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "clearS3", c.clearS3)
|
||||
})
|
||||
return errs.WrapMsg(err, "failed to register clear s3 cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerDeleteMsg() error {
|
||||
if c.config.CronTask.RetainChatRecords <= 0 {
|
||||
log.ZInfo(c.ctx, "disable scheduled cleanup of chat records", "retainChatRecords", c.config.CronTask.RetainChatRecords)
|
||||
return nil
|
||||
}
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "deleteMsg", c.deleteMsg)
|
||||
})
|
||||
return errs.WrapMsg(err, "failed to register delete msg cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearUserMsg() error {
|
||||
_, err := c.cron.AddFunc(c.config.CronTask.CronExecuteTime, func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "clearUserMsg", c.clearUserMsg)
|
||||
})
|
||||
return errs.WrapMsg(err, "failed to register clear user msg cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerDismissMeetingGroups() error {
|
||||
// 每分钟执行一次,检查已结束超过10分钟的会议并解散群聊
|
||||
_, err := c.cron.AddFunc("*/1 * * * *", func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "dismissMeetingGroups", c.dismissMeetingGroups)
|
||||
})
|
||||
return errs.WrapMsg(err, "failed to register dismiss meeting groups cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearGroupMsgByConfig() error {
|
||||
// 使用配置文件中的执行时间,清理群聊消息(根据系统配置)
|
||||
cronExpr := c.config.CronTask.CronExecuteTime
|
||||
log.ZInfo(c.ctx, "[CLEAR_MSG] 注册清理群聊消息定时任务", "cron", cronExpr)
|
||||
_, err := c.cron.AddFunc(cronExpr, func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "clearGroupMsgByConfig", c.clearGroupMsg)
|
||||
})
|
||||
if err != nil {
|
||||
log.ZError(c.ctx, "[CLEAR_MSG] 注册清理群聊消息定时任务失败", err)
|
||||
} else {
|
||||
log.ZInfo(c.ctx, "[CLEAR_MSG] 清理群聊消息定时任务注册成功", "cron", cronExpr)
|
||||
}
|
||||
return errs.WrapMsg(err, "failed to register clear group msg by config cron task")
|
||||
}
|
||||
|
||||
func (c *cronServer) registerClearUserMsgByConfig() error {
|
||||
// 使用配置文件中的执行时间,清理个人聊天消息(根据系统配置)
|
||||
cronExpr := c.config.CronTask.CronExecuteTime
|
||||
log.ZInfo(c.ctx, "[CLEAR_MSG] 注册清理个人聊天消息定时任务", "cron", cronExpr)
|
||||
_, err := c.cron.AddFunc(cronExpr, func() {
|
||||
c.locker.ExecuteWithLock(c.ctx, "clearUserMsgByConfig", c.clearUserMsg)
|
||||
})
|
||||
if err != nil {
|
||||
log.ZError(c.ctx, "[CLEAR_MSG] 注册清理个人聊天消息定时任务失败", err)
|
||||
} else {
|
||||
log.ZInfo(c.ctx, "[CLEAR_MSG] 清理个人聊天消息定时任务注册成功", "cron", cronExpr)
|
||||
}
|
||||
return errs.WrapMsg(err, "failed to register clear user msg by config cron task")
|
||||
}
|
||||
Reference in New Issue
Block a user