118 lines
4.2 KiB
Go
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
|
|
}
|