chore: seed migration objects batch 5
This commit is contained in:
@@ -7,12 +7,12 @@ package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/library/hgorm/hook"
|
||||
"hotgo/internal/library/imkafka"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type sSysImTenant struct{}
|
||||
@@ -36,11 +35,11 @@ func init() {
|
||||
|
||||
// Model IM租户ORM模型
|
||||
func (s *sSysImTenant) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(imtenant.RegistryDB(ctx).Model(dao.ImTenant.Table()).Safe().Ctx(ctx), option...)
|
||||
return handler.Model(imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) configModel(ctx context.Context) *gdb.Model {
|
||||
return imtenant.RegistryDB(ctx).Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx)
|
||||
return imtenant.RegistryDB().Model(dao.ImTenantConfig.Table()).Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// List 获取IM租户列表
|
||||
@@ -145,7 +144,7 @@ func (s *sSysImTenant) Edit(ctx context.Context, in *sysin.ImTenantEditInp) (err
|
||||
return
|
||||
}
|
||||
|
||||
err = imtenant.RegistryDB(ctx).Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
return imtenant.RegistryDB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
if err = s.checkCodeUnique(ctx, in.Id, in.Code); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -170,12 +169,6 @@ func (s *sSysImTenant) Edit(ctx context.Context, in *sysin.ImTenantEditInp) (err
|
||||
}
|
||||
return s.saveConfig(ctx, id, in.MaxUsers, in.MaxGroups, in.MaxGroupMembers, userId)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.publishTenantConfigEvent(ctx, in.Code, in.Id, consts.ImConfigEventTenantUpdated, "tenant")
|
||||
s.publishTenantConfigEvent(ctx, in.Code, in.Id, consts.ImConfigEventTenantLimitsUpdated, "tenant_limits")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) checkCodeUnique(ctx context.Context, id int64, code string) (err error) {
|
||||
@@ -278,33 +271,139 @@ func (s *sSysImTenant) Status(ctx context.Context, in *sysin.ImTenantStatusInp)
|
||||
err = gerror.Wrap(err, "更新IM租户状态失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) Usage(ctx context.Context, in *sysin.ImTenantUsageInp) (res *sysin.ImTenantUsageModel, err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var tenant *entity.ImTenant
|
||||
if scanErr := s.Model(ctx).Fields(dao.ImTenant.Columns().Id, dao.ImTenant.Columns().Code).WherePri(in.Id).Scan(&tenant); scanErr == nil && tenant != nil {
|
||||
s.publishTenantConfigEvent(ctx, tenant.Code, tenant.Id, consts.ImConfigEventTenantStatusChanged, "tenant_status")
|
||||
if err = s.Model(ctx).WherePri(in.Id).Scan(&tenant); err != nil {
|
||||
return nil, gerror.Wrap(err, "获取IM租户信息失败,请稍后重试!")
|
||||
}
|
||||
if tenant == nil || tenant.Id <= 0 {
|
||||
return nil, gerror.New("IM租户不存在")
|
||||
}
|
||||
|
||||
res = &sysin.ImTenantUsageModel{
|
||||
Id: tenant.Id,
|
||||
Code: tenant.Code,
|
||||
Name: tenant.Name,
|
||||
DbName: tenant.DbName,
|
||||
DbDsnConfigured: tenant.DbDsn != "",
|
||||
Warnings: []string{},
|
||||
}
|
||||
|
||||
db, _, dbErr := imtenant.DB(ctx, tenant.Id)
|
||||
if dbErr != nil {
|
||||
res.DbReachable = false
|
||||
res.DbCheckError = dbErr.Error()
|
||||
return res, nil
|
||||
}
|
||||
if _, pingErr := db.GetValue(ctx, "SELECT 1"); pingErr != nil {
|
||||
res.DbReachable = false
|
||||
res.DbCheckError = pingErr.Error()
|
||||
return res, nil
|
||||
}
|
||||
res.DbReachable = true
|
||||
|
||||
res.SchemaVersion = s.queryScalarString(ctx, db, "kvmeta.version", "SELECT value FROM kvmeta WHERE key_='version' LIMIT 1", &res.Warnings)
|
||||
res.UserCount = s.queryScalarInt64(ctx, db, "im_users.total", "SELECT COUNT(*) FROM im_users", &res.Warnings)
|
||||
res.ActiveUserCount = s.queryScalarInt64(ctx, db, "im_users.active", "SELECT COUNT(*) FROM im_users WHERE state=0", &res.Warnings)
|
||||
res.GroupCount = s.queryScalarInt64(ctx, db, "im_group_settings", "SELECT COUNT(*) FROM im_group_settings WHERE group_status<>'dissolved'", &res.Warnings)
|
||||
res.DeviceCount = s.queryScalarInt64(ctx, db, "im_devices", "SELECT COUNT(*) FROM im_devices", &res.Warnings)
|
||||
res.PushTokenCount = s.queryScalarInt64(ctx, db, "im_device_push_tokens", "SELECT COUNT(*) FROM im_device_push_tokens", &res.Warnings)
|
||||
res.InviteUseCount = s.queryScalarInt64(ctx, db, "im_registration_invite_uses", "SELECT COUNT(*) FROM im_registration_invite_uses", &res.Warnings)
|
||||
res.OutboxPendingCount = s.queryScalarInt64(ctx, db, "im_business_events_outbox", "SELECT COUNT(*) FROM im_business_events_outbox WHERE status='pending'", &res.Warnings)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) queryScalarInt64(ctx context.Context, db gdb.DB, label, sql string, warnings *[]string) int64 {
|
||||
value, err := db.GetValue(ctx, sql)
|
||||
if err != nil {
|
||||
*warnings = append(*warnings, label+": "+err.Error())
|
||||
return 0
|
||||
}
|
||||
return value.Int64()
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) queryScalarString(ctx context.Context, db gdb.DB, label, sql string, warnings *[]string) string {
|
||||
value, err := db.GetValue(ctx, sql)
|
||||
if err != nil {
|
||||
*warnings = append(*warnings, label+": "+err.Error())
|
||||
return ""
|
||||
}
|
||||
return value.String()
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) DeletionCheck(ctx context.Context, in *sysin.ImTenantDeletionCheckInp) (res *sysin.ImTenantDeletionCheckModel, err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
usage, err := s.Usage(ctx, &sysin.ImTenantUsageInp{Id: in.Id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res = &sysin.ImTenantDeletionCheckModel{
|
||||
Id: usage.Id,
|
||||
Code: usage.Code,
|
||||
Name: usage.Name,
|
||||
Blockers: []string{},
|
||||
Warnings: usage.Warnings,
|
||||
UserCount: usage.UserCount,
|
||||
GroupCount: usage.GroupCount,
|
||||
PendingOutbox: usage.OutboxPendingCount,
|
||||
}
|
||||
if !usage.DbReachable {
|
||||
res.Blockers = append(res.Blockers, "租户业务库不可达:"+usage.DbCheckError)
|
||||
}
|
||||
if usage.UserCount > 0 {
|
||||
res.Blockers = append(res.Blockers, fmt.Sprintf("租户仍有 %d 个用户", usage.UserCount))
|
||||
}
|
||||
if usage.GroupCount > 0 {
|
||||
res.Blockers = append(res.Blockers, fmt.Sprintf("租户仍有 %d 个群", usage.GroupCount))
|
||||
}
|
||||
if usage.OutboxPendingCount > 0 {
|
||||
res.Blockers = append(res.Blockers, fmt.Sprintf("租户仍有 %d 条待处理 Outbox", usage.OutboxPendingCount))
|
||||
}
|
||||
res.CanEnterDeleting = len(res.Blockers) == 0
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) EnterDeleting(ctx context.Context, in *sysin.ImTenantLifecycleInp) (err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
check, err := s.DeletionCheck(ctx, &sysin.ImTenantDeletionCheckInp{Id: in.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !check.CanEnterDeleting {
|
||||
return gerror.New("租户未通过删除前检查,不能进入删除流程")
|
||||
}
|
||||
if _, err = s.Model(ctx).WherePri(in.Id).Data(g.Map{
|
||||
dao.ImTenant.Columns().State: consts.ImTenantStateDeleting,
|
||||
dao.ImTenant.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update(); err != nil {
|
||||
return gerror.Wrap(err, "设置IM租户删除流程失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysImTenant) publishTenantConfigEvent(ctx context.Context, tenantCode string, tenantId int64, eventType string, bizId string) {
|
||||
user := contexts.GetUser(ctx)
|
||||
actorName := ""
|
||||
if user != nil {
|
||||
actorName = user.RealName
|
||||
func (s *sSysImTenant) Restore(ctx context.Context, in *sysin.ImTenantLifecycleInp) (err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if err := imkafka.PublishConfigEvent(ctx, imkafka.ConfigEventInput{
|
||||
TenantID: tenantId,
|
||||
TenantCode: tenantCode,
|
||||
EventType: eventType,
|
||||
BizID: bizId,
|
||||
Group: "tenant",
|
||||
Keys: []string{"tenant", "limits", "features"},
|
||||
Actor: &imkafka.Actor{
|
||||
Type: "admin",
|
||||
ID: gconv.String(contexts.GetUserId(ctx)),
|
||||
DisplayName: actorName,
|
||||
},
|
||||
CreatedBy: contexts.GetUserId(ctx),
|
||||
}); err != nil {
|
||||
g.Log().Warningf(ctx, "发送IM租户配置Kafka事件失败 tenant:%s type:%s err:%+v", tenantCode, eventType, err)
|
||||
if _, err = s.Model(ctx).
|
||||
WherePri(in.Id).
|
||||
WhereIn(dao.ImTenant.Columns().State, []int{consts.ImTenantStateSuspended, consts.ImTenantStateDeleting}).
|
||||
Data(g.Map{
|
||||
dao.ImTenant.Columns().State: consts.ImTenantStateActive,
|
||||
dao.ImTenant.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update(); err != nil {
|
||||
return gerror.Wrap(err, "恢复IM租户失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user