Files
im_manager/server/internal/logic/sys/im_task_dashboard.go
T

118 lines
4.2 KiB
Go

package sys
import (
"context"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/imtenant"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
)
type sSysImTaskDashboard struct{}
func NewSysImTaskDashboard() *sSysImTaskDashboard { return &sSysImTaskDashboard{} }
func init() {
service.RegisterSysImTaskDashboard(NewSysImTaskDashboard())
}
func (s *sSysImTaskDashboard) List(ctx context.Context, in *sysin.ImTaskDashboardListInp) (list []*sysin.ImTaskDashboardListModel, totalCount int, err error) {
if err = in.Filter(ctx); err != nil {
return
}
scope, err := resolveImAdminScopeWithAll(ctx, in.TenantId, true)
if err != nil {
return
}
mod := imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx)
if scope.TenantId > 0 {
mod = mod.WherePri(scope.TenantId)
}
if in.TenantId > 0 {
mod = mod.WherePri(in.TenantId)
}
mod = mod.Page(in.Page, in.PerPage).OrderAsc(dao.ImTenant.Columns().Id)
var tenants []*entity.ImTenant
if err = mod.ScanAndCount(&tenants, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取IM任务看板租户失败,请稍后重试!")
return
}
list = make([]*sysin.ImTaskDashboardListModel, 0, len(tenants))
for _, tenant := range tenants {
item := s.buildTenantSummary(ctx, tenant)
if in.Status != "" && item.Status != in.Status {
continue
}
list = append(list, item)
}
if in.Status != "" {
totalCount = len(list)
}
return
}
func (s *sSysImTaskDashboard) buildTenantSummary(ctx context.Context, tenant *entity.ImTenant) *sysin.ImTaskDashboardListModel {
item := &sysin.ImTaskDashboardListModel{
TenantId: tenant.Id,
TenantName: tenant.Name,
TenantCode: tenant.Code,
TenantState: tenant.State,
DbStatus: "ok",
Status: consts.ImTaskDashboardStatusHealthy,
RecommendedNextAction: "无需处理",
}
db, _, err := imtenant.DB(ctx, tenant.Id)
if err != nil {
item.DbStatus = "error"
item.Status = consts.ImTaskDashboardStatusError
item.RecommendedNextAction = "检查租户数据库连接"
return item
}
item.OutboxPendingCount, _ = s.count(ctx, db, "im_business_events_outbox", "status='pending'")
item.OutboxFailedCount, _ = s.count(ctx, db, "im_business_events_outbox", "status='failed'")
item.GroupOutboxPending, _ = s.count(ctx, db, "im_group_events_outbox", "status='pending'")
item.GroupOutboxFailed, _ = s.count(ctx, db, "im_group_events_outbox", "status='failed'")
item.OrphanFileCount, _ = s.countOrphanFiles(ctx, db)
item.DeletedFileCount, _ = s.count(ctx, db, "im_fileuploads", "status=3")
item.LastOutboxCreatedAt, _ = s.maxTime(ctx, db, "im_business_events_outbox", "created_at")
item.LastGroupEventAt, _ = s.maxTime(ctx, db, "im_group_events_outbox", "created_at")
item.LastFileUpdatedAt, _ = s.maxTime(ctx, db, "im_fileuploads", "updatedat")
if item.OutboxFailedCount > 0 || item.GroupOutboxFailed > 0 {
item.Status = consts.ImTaskDashboardStatusError
item.RecommendedNextAction = "处理失败Outbox事件"
} else if item.OutboxPendingCount > 0 || item.GroupOutboxPending > 0 || item.OrphanFileCount > 0 || item.DeletedFileCount > 0 {
item.Status = consts.ImTaskDashboardStatusWarning
item.RecommendedNextAction = "检查待处理任务和文件清理"
}
return item
}
func (s *sSysImTaskDashboard) count(ctx context.Context, db gdb.DB, table string, where string) (int, error) {
return db.Model(table).Safe().Ctx(ctx).Where(where).Count()
}
func (s *sSysImTaskDashboard) countOrphanFiles(ctx context.Context, db gdb.DB) (int, error) {
return db.Model("im_fileuploads fu").Safe().Ctx(ctx).
LeftJoin("im_filemsglinks fml", "fml.fileid=fu.id").
Where("fml.id IS NULL").
WhereNotIn("fu.status", []int{consts.ImFileStatusDeleted, consts.ImFileStatusQuarantined}).
Count()
}
func (s *sSysImTaskDashboard) maxTime(ctx context.Context, db gdb.DB, table string, field string) (res *gtime.Time, err error) {
var row struct {
Value *gtime.Time `orm:"value"`
}
if err = db.Model(table).Safe().Ctx(ctx).Fields("MAX(" + field + ") value").Scan(&row); err != nil {
return nil, err
}
return row.Value, nil
}