复制项目
This commit is contained in:
152
internal/tools/cron/meeting.go
Normal file
152
internal/tools/cron/meeting.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/common/storage/model"
|
||||
"git.imall.cloud/openim/open-im-server-deploy/pkg/common/webhook"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/mcontext"
|
||||
)
|
||||
|
||||
// meetingPagination 简单的分页实现,供定时任务批量扫描使用
|
||||
type meetingPagination struct {
|
||||
pageNumber int32
|
||||
showNumber int32
|
||||
}
|
||||
|
||||
func (p *meetingPagination) GetPageNumber() int32 {
|
||||
if p.pageNumber <= 0 {
|
||||
return 1
|
||||
}
|
||||
return p.pageNumber
|
||||
}
|
||||
|
||||
func (p *meetingPagination) GetShowNumber() int32 {
|
||||
if p.showNumber <= 0 {
|
||||
return 200
|
||||
}
|
||||
return p.showNumber
|
||||
}
|
||||
|
||||
// dismissMeetingGroups 解散已结束超过10分钟的会议群聊
|
||||
func (c *cronServer) dismissMeetingGroups() {
|
||||
now := time.Now()
|
||||
// 计算10分钟前的时间
|
||||
beforeTime := now.Add(-10 * time.Minute)
|
||||
operationID := fmt.Sprintf("cron_dismiss_meeting_groups_%d_%d", os.Getpid(), now.UnixMilli())
|
||||
ctx := mcontext.SetOperationID(c.ctx, operationID)
|
||||
|
||||
log.ZDebug(ctx, "Start dismissing meeting groups", "beforeTime", beforeTime)
|
||||
|
||||
// 先将已过期但状态仍为已预约/进行中的会议标记为已结束
|
||||
c.finishExpiredMeetings(ctx, now)
|
||||
|
||||
// 查询已结束且结束时间在10分钟前的会议
|
||||
// 结束时间 = scheduledTime + duration(分钟)
|
||||
meetings, err := c.meetingDB.FindFinishedMeetingsBefore(ctx, beforeTime)
|
||||
if err != nil {
|
||||
log.ZError(ctx, "Failed to find finished meetings", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(meetings) == 0 {
|
||||
log.ZDebug(ctx, "No finished meetings to dismiss groups")
|
||||
return
|
||||
}
|
||||
|
||||
log.ZInfo(ctx, "Found finished meetings to dismiss groups", "count", len(meetings))
|
||||
|
||||
dismissedCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, meeting := range meetings {
|
||||
if meeting.GroupID == "" {
|
||||
log.ZWarn(ctx, "Meeting has no group ID, skip", nil, "meetingID", meeting.MeetingID)
|
||||
continue
|
||||
}
|
||||
|
||||
// 计算会议结束时间
|
||||
endTime := meeting.ScheduledTime.Add(time.Duration(meeting.Duration) * time.Minute)
|
||||
// 检查是否已经超过10分钟
|
||||
if now.Sub(endTime) < 10*time.Minute {
|
||||
log.ZDebug(ctx, "Meeting ended less than 10 minutes ago, skip", "meetingID", meeting.MeetingID, "endTime", endTime)
|
||||
continue
|
||||
}
|
||||
|
||||
// 解散群聊,deleteMember设为true表示删除所有成员
|
||||
ctx := mcontext.SetOperationID(c.ctx, fmt.Sprintf("%s_%s", operationID, meeting.MeetingID))
|
||||
err := c.groupClient.DismissGroup(ctx, meeting.GroupID, true)
|
||||
if err != nil {
|
||||
// 如果群不存在或找不到群主(RecordNotFoundError),说明群可能已经被解散或数据不一致
|
||||
if errs.ErrRecordNotFound.Is(err) {
|
||||
log.ZWarn(ctx, "Group not found or owner not found, may already be dismissed, clear groupID", nil, "meetingID", meeting.MeetingID, "groupID", meeting.GroupID)
|
||||
// 清空groupID,避免下次重复处理
|
||||
if updateErr := c.meetingDB.Update(ctx, meeting.MeetingID, map[string]any{"group_id": ""}); updateErr != nil {
|
||||
log.ZWarn(ctx, "Failed to clear groupID after group not found", updateErr, "meetingID", meeting.MeetingID)
|
||||
}
|
||||
// 不增加失败计数,因为这不是真正的失败
|
||||
continue
|
||||
}
|
||||
log.ZError(ctx, "Failed to dismiss meeting group", err, "meetingID", meeting.MeetingID, "groupID", meeting.GroupID)
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
// 从webhook配置的attentionIds中移除会议群ID
|
||||
if c.systemConfigDB != nil {
|
||||
if err := webhook.UpdateAttentionIds(ctx, c.systemConfigDB, meeting.GroupID, false); err != nil {
|
||||
log.ZWarn(ctx, "dismissMeetingGroups: failed to remove groupID from webhook attentionIds", err, "meetingID", meeting.MeetingID, "groupID", meeting.GroupID)
|
||||
}
|
||||
}
|
||||
|
||||
// 解散群成功后,清空会议的groupID,避免下次重复处理
|
||||
if updateErr := c.meetingDB.Update(ctx, meeting.MeetingID, map[string]any{"group_id": ""}); updateErr != nil {
|
||||
log.ZWarn(ctx, "Failed to clear groupID after dismissing group", updateErr, "meetingID", meeting.MeetingID, "groupID", meeting.GroupID)
|
||||
} else {
|
||||
log.ZInfo(ctx, "Successfully dismissed meeting group and cleared groupID", "meetingID", meeting.MeetingID, "groupID", meeting.GroupID, "endTime", endTime)
|
||||
}
|
||||
dismissedCount++
|
||||
}
|
||||
|
||||
log.ZInfo(ctx, "Finished dismissing meeting groups", "total", len(meetings), "dismissed", dismissedCount, "failed", failedCount, "duration", time.Since(now))
|
||||
}
|
||||
|
||||
// finishExpiredMeetings 将已过结束时间的会议状态更新为已结束
|
||||
func (c *cronServer) finishExpiredMeetings(ctx context.Context, now time.Time) {
|
||||
statuses := []int32{model.MeetingStatusScheduled, model.MeetingStatusOngoing}
|
||||
for _, status := range statuses {
|
||||
page := int32(1)
|
||||
for {
|
||||
total, meetings, err := c.meetingDB.FindByStatus(ctx, status, &meetingPagination{pageNumber: page, showNumber: 200})
|
||||
if err != nil {
|
||||
log.ZWarn(ctx, "finishExpiredMeetings: failed to list meetings", err, "status", status, "page", page)
|
||||
break
|
||||
}
|
||||
if len(meetings) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, meeting := range meetings {
|
||||
endTime := meeting.ScheduledTime.Add(time.Duration(meeting.Duration) * time.Minute)
|
||||
if now.After(endTime) {
|
||||
if err := c.meetingDB.UpdateStatus(ctx, meeting.MeetingID, model.MeetingStatusFinished); err != nil {
|
||||
log.ZWarn(ctx, "finishExpiredMeetings: failed to update status", err, "meetingID", meeting.MeetingID)
|
||||
continue
|
||||
}
|
||||
log.ZInfo(ctx, "finishExpiredMeetings: meeting marked finished", "meetingID", meeting.MeetingID, "endTime", endTime)
|
||||
}
|
||||
}
|
||||
|
||||
// 分页结束条件
|
||||
if int64(page*200) >= total {
|
||||
break
|
||||
}
|
||||
page++
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user