feat: 完善IM后台Kafka与组织架构管理
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/library/queue"
|
||||
"time"
|
||||
|
||||
@@ -60,7 +61,7 @@ func PublishAdminCommand(ctx context.Context, in AdminCommandInput) (res *AdminC
|
||||
return nil, gerror.Wrap(err, "序列化IM命令Envelope失败")
|
||||
}
|
||||
|
||||
db := g.DB()
|
||||
db := adminDB()
|
||||
err = db.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
nowTime := gtime.Now()
|
||||
if _, err := tx.Exec(`INSERT INTO im_admin_commands
|
||||
@@ -101,7 +102,7 @@ func PublishAdminCommand(ctx context.Context, in AdminCommandInput) (res *AdminC
|
||||
}
|
||||
|
||||
func DispatchOutboxByEvent(ctx context.Context, eventID string) error {
|
||||
row, err := g.DB().GetOne(ctx, `SELECT * FROM im_admin_outbox WHERE event_id=? AND status=? LIMIT 1`,
|
||||
row, err := adminDB().GetOne(ctx, `SELECT * FROM im_admin_outbox WHERE event_id=? AND status=? LIMIT 1`,
|
||||
eventID, consts.ImAdminOutboxStatusPending)
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "读取IM命令Outbox失败")
|
||||
@@ -146,7 +147,7 @@ func PublishConfigEvent(ctx context.Context, in ConfigEventInput) error {
|
||||
return gerror.Wrap(err, "序列化IM配置事件Envelope失败")
|
||||
}
|
||||
nowTime := gtime.Now()
|
||||
_, err = g.DB().Exec(ctx, `INSERT INTO im_admin_outbox
|
||||
_, err = adminDB().Exec(ctx, `INSERT INTO im_admin_outbox
|
||||
(event_id,command_id,topic,event_type,biz_type,biz_id,key_value,envelope,status,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,CAST(? AS JSON),?,?,?)`,
|
||||
eventID, "", consts.QueueImConfigEventTopic, in.EventType, "config", in.BizID, in.TenantCode,
|
||||
@@ -198,7 +199,7 @@ func PublishEvent(ctx context.Context, in EventInput) (eventID string, err error
|
||||
return "", gerror.Wrap(err, "序列化IM Kafka事件Envelope失败")
|
||||
}
|
||||
nowTime := gtime.Now()
|
||||
_, err = g.DB().Exec(ctx, `INSERT INTO im_admin_outbox
|
||||
_, err = adminDB().Exec(ctx, `INSERT INTO im_admin_outbox
|
||||
(event_id,command_id,topic,event_type,biz_type,biz_id,key_value,envelope,status,created_at,updated_at)
|
||||
VALUES(?,?,?,?,?,?,?,CAST(? AS JSON),?,?,?)`,
|
||||
eventID, "", in.Topic, in.EventType, in.BizType, in.BizID, in.BizID,
|
||||
@@ -216,7 +217,7 @@ func DispatchPendingOutbox(ctx context.Context, limit int) (sent int, err error)
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
rows, err := g.DB().GetAll(ctx, `SELECT * FROM im_admin_outbox
|
||||
rows, err := adminDB().GetAll(ctx, `SELECT * FROM im_admin_outbox
|
||||
WHERE status IN (?,?) AND (next_retry_at IS NULL OR next_retry_at <= NOW())
|
||||
ORDER BY id ASC LIMIT ?`, consts.ImAdminOutboxStatusPending, consts.ImAdminOutboxStatusFailed, limit)
|
||||
if err != nil {
|
||||
@@ -250,14 +251,14 @@ func dispatchOutboxRecord(ctx context.Context, row gdb.Record) error {
|
||||
return err
|
||||
}
|
||||
now := gtime.Now()
|
||||
_, err := g.DB().Exec(ctx, `UPDATE im_admin_outbox
|
||||
_, err := adminDB().Exec(ctx, `UPDATE im_admin_outbox
|
||||
SET status=?,attempts=attempts+1,sent_at=?,last_reason='',last_error='',updated_at=?
|
||||
WHERE event_id=?`, consts.ImAdminOutboxStatusSent, now, now, eventID)
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "更新IM命令Outbox投递状态失败")
|
||||
}
|
||||
if commandID != "" {
|
||||
_, err = g.DB().Exec(ctx, `UPDATE im_admin_commands
|
||||
_, err = adminDB().Exec(ctx, `UPDATE im_admin_commands
|
||||
SET status=?,sent_at=?,updated_at=? WHERE command_id=?`,
|
||||
consts.ImAdminCommandStatusRunning, now, now, commandID)
|
||||
if err != nil {
|
||||
@@ -269,7 +270,7 @@ func dispatchOutboxRecord(ctx context.Context, row gdb.Record) error {
|
||||
|
||||
func markOutboxFailed(ctx context.Context, eventID string, reason string, message string) error {
|
||||
now := gtime.Now()
|
||||
_, err := g.DB().Exec(ctx, `UPDATE im_admin_outbox
|
||||
_, err := adminDB().Exec(ctx, `UPDATE im_admin_outbox
|
||||
SET status=?,attempts=attempts+1,next_retry_at=?,last_reason=?,last_error=?,updated_at=?
|
||||
WHERE event_id=?`, consts.ImAdminOutboxStatusFailed, now.Add(30*time.Second), reason, message, now, eventID)
|
||||
if err != nil {
|
||||
@@ -316,9 +317,13 @@ func ApplyCommandResult(ctx context.Context, result CommandResult) error {
|
||||
}
|
||||
sql += ` WHERE ` + whereColumn + `=?`
|
||||
args = append(args, whereValue)
|
||||
_, err := g.DB().Exec(ctx, sql, args...)
|
||||
_, err := adminDB().Exec(ctx, sql, args...)
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "更新IM后台命令结果失败")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func adminDB() gdb.DB {
|
||||
return imtenant.RegistryDB()
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
type sSysImKafkaAudit struct{}
|
||||
@@ -25,7 +25,8 @@ func (s *sSysImKafkaAudit) List(ctx context.Context, in *sysin.ImKafkaAuditListI
|
||||
return
|
||||
}
|
||||
where, args := buildImKafkaAuditWhere(in)
|
||||
totalValue, err := g.DB().GetValue(ctx, "SELECT COUNT(*) FROM im_audit_events "+where, args...)
|
||||
db := imtenant.RegistryDB()
|
||||
totalValue, err := db.GetValue(ctx, "SELECT COUNT(*) FROM im_audit_events "+where, args...)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取IM Kafka审计事件总数失败,请稍后重试!")
|
||||
return
|
||||
@@ -45,7 +46,7 @@ func (s *sSysImKafkaAudit) List(ctx context.Context, in *sysin.ImKafkaAuditListI
|
||||
action,resource,resource_id,result,reason,occurred_at,received_at
|
||||
FROM im_audit_events ` + where + ` ORDER BY id DESC LIMIT ? OFFSET ?`
|
||||
queryArgs := append(append([]any{}, args...), perPage, offset)
|
||||
rows, err := g.DB().GetAll(ctx, query, queryArgs...)
|
||||
rows, err := db.GetAll(ctx, query, queryArgs...)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取IM Kafka审计事件列表失败,请稍后重试!")
|
||||
return
|
||||
@@ -126,7 +127,7 @@ func (s *sSysImKafkaAudit) View(ctx context.Context, in *sysin.ImKafkaAuditViewI
|
||||
args = append(args, in.EventId)
|
||||
}
|
||||
query += " LIMIT 1"
|
||||
row, err := g.DB().GetOne(ctx, query, args...)
|
||||
row, err := imtenant.RegistryDB().GetOne(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "获取IM Kafka审计事件详情失败,请稍后重试!")
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/imkafka"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
@@ -34,7 +34,8 @@ func (s *sSysImKafkaCommand) List(ctx context.Context, in *sysin.ImKafkaCommandL
|
||||
return
|
||||
}
|
||||
where, args := buildImKafkaCommandWhere(in)
|
||||
totalValue, err := g.DB().GetValue(ctx, "SELECT COUNT(*) FROM im_admin_commands "+where, args...)
|
||||
db := imtenant.RegistryDB()
|
||||
totalValue, err := db.GetValue(ctx, "SELECT COUNT(*) FROM im_admin_commands "+where, args...)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取IM后台命令总数失败,请稍后重试!")
|
||||
return
|
||||
@@ -53,7 +54,7 @@ func (s *sSysImKafkaCommand) List(ctx context.Context, in *sysin.ImKafkaCommandL
|
||||
status,reason,message,sent_at,completed_at,created_by,created_at,updated_at
|
||||
FROM im_admin_commands ` + where + ` ORDER BY id DESC LIMIT ? OFFSET ?`
|
||||
queryArgs := append(append([]any{}, args...), perPage, offset)
|
||||
rows, err := g.DB().GetAll(ctx, query, queryArgs...)
|
||||
rows, err := db.GetAll(ctx, query, queryArgs...)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取IM后台命令列表失败,请稍后重试!")
|
||||
return
|
||||
@@ -80,7 +81,7 @@ func (s *sSysImKafkaCommand) View(ctx context.Context, in *sysin.ImKafkaCommandV
|
||||
args = append(args, in.CommandId)
|
||||
}
|
||||
query += " LIMIT 1"
|
||||
row, err := g.DB().GetOne(ctx, query, args...)
|
||||
row, err := imtenant.RegistryDB().GetOne(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, "获取IM后台命令详情失败,请稍后重试!")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/excel"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
@@ -34,33 +35,28 @@ func (s *sSysImOrg) DepartmentList(ctx context.Context, in *sysin.ImOrgDepartmen
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
db, tenant, err := resolveImTenantDB(ctx, in.TenantId)
|
||||
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mod := s.departmentModel(ctx, db)
|
||||
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
|
||||
if in.DepartmentId != "" {
|
||||
mod = mod.Where("d.department_id", strings.TrimSpace(in.DepartmentId))
|
||||
values.Set("department_id", strings.TrimSpace(in.DepartmentId))
|
||||
}
|
||||
if in.ParentId != "" {
|
||||
mod = mod.Where("d.parent_id", strings.TrimSpace(in.ParentId))
|
||||
values.Set("parent_id", strings.TrimSpace(in.ParentId))
|
||||
}
|
||||
if in.Name != "" {
|
||||
mod = mod.WhereLike("d.name", "%"+strings.TrimSpace(in.Name)+"%")
|
||||
values.Set("name", strings.TrimSpace(in.Name))
|
||||
}
|
||||
if in.State != "" {
|
||||
mod = mod.Where("d.state", strings.TrimSpace(in.State))
|
||||
values.Set("state", strings.TrimSpace(in.State))
|
||||
}
|
||||
mod = mod.Page(in.Page, in.PerPage).OrderAsc("d.sort_order").OrderAsc("d.id")
|
||||
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
|
||||
err = gerror.Wrap(err, "获取IM组织部门失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
for _, item := range list {
|
||||
item.TenantId = tenant.Id
|
||||
item.TenantName = tenant.Name
|
||||
}
|
||||
return
|
||||
return imAdminQueryList[sysin.ImOrgDepartmentModel](ctx, tenant,
|
||||
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/org/departments",
|
||||
values,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *sSysImOrg) DepartmentExport(ctx context.Context, in *sysin.ImOrgDepartmentListInp) (err error) {
|
||||
@@ -195,34 +191,28 @@ func (s *sSysImOrg) MemberList(ctx context.Context, in *sysin.ImOrgMemberListInp
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
db, tenant, err := resolveImTenantDB(ctx, in.TenantId)
|
||||
tenant, err := resolveImAdminTenant(ctx, in.TenantId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mod := s.memberModel(ctx, db)
|
||||
values := addPageQuery(url.Values{}, in.Page, in.PerPage)
|
||||
if in.DepartmentId != "" {
|
||||
mod = mod.Where("m.department_id", strings.TrimSpace(in.DepartmentId))
|
||||
values.Set("department_id", strings.TrimSpace(in.DepartmentId))
|
||||
}
|
||||
if in.UserId > 0 {
|
||||
mod = mod.Where("m.user_id", in.UserId)
|
||||
values.Set("user_id", int64ToString(in.UserId))
|
||||
}
|
||||
if in.EmploymentState != "" {
|
||||
mod = mod.Where("m.employment_state", strings.TrimSpace(in.EmploymentState))
|
||||
values.Set("employment_state", strings.TrimSpace(in.EmploymentState))
|
||||
}
|
||||
if q := strings.TrimSpace(in.Query); q != "" {
|
||||
like := "%" + q + "%"
|
||||
mod = mod.Where("(m.display_name LIKE ? OR m.mobile LIKE ? OR m.email LIKE ? OR CAST(m.user_id AS CHAR) LIKE ?)", like, like, like, like)
|
||||
if in.Query != "" {
|
||||
values.Set("q", strings.TrimSpace(in.Query))
|
||||
}
|
||||
mod = mod.Page(in.Page, in.PerPage).OrderAsc("m.sort_order").OrderAsc("m.id")
|
||||
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
|
||||
err = gerror.Wrap(err, "获取IM组织成员失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
for _, item := range list {
|
||||
item.TenantId = tenant.Id
|
||||
item.TenantName = tenant.Name
|
||||
}
|
||||
return
|
||||
return imAdminQueryList[sysin.ImOrgMemberModel](ctx, tenant,
|
||||
"/internal/admin-query/tenants/"+url.PathEscape(tenant.Code)+"/org/members",
|
||||
values,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
func (s *sSysImOrg) MemberExport(ctx context.Context, in *sysin.ImOrgMemberListInp) (err error) {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"encoding/json"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/imkafka"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/library/queue"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ func (q *qImAuditEvent) Handle(ctx context.Context, mqMsg queue.MqMsg) (err erro
|
||||
if len(envelope.Payload) > 0 {
|
||||
_ = json.Unmarshal(envelope.Payload, &payload)
|
||||
}
|
||||
_, err = g.DB().Exec(ctx, `INSERT IGNORE INTO im_audit_events
|
||||
_, err = imtenant.RegistryDB().Exec(ctx, `INSERT IGNORE INTO im_audit_events
|
||||
(event_id,tenant_code,event_type,biz_type,biz_id,actor_type,actor_id,action,resource,resource_id,result,reason,payload,envelope,occurred_at,received_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,CAST(NULLIF(?, '') AS JSON),CAST(? AS JSON),?,?)`,
|
||||
envelope.EventID, envelope.TenantCode, envelope.EventType, envelope.BizType, envelope.BizID,
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"encoding/json"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/imkafka"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/library/queue"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ func (q *qImDeadLetter) Handle(ctx context.Context, mqMsg queue.MqMsg) (err erro
|
||||
if len(envelope.Payload) > 0 {
|
||||
_ = json.Unmarshal(envelope.Payload, &payload)
|
||||
}
|
||||
_, err = g.DB().Exec(ctx, `INSERT IGNORE INTO im_kafka_dead_letter_events
|
||||
_, err = imtenant.RegistryDB().Exec(ctx, `INSERT IGNORE INTO im_kafka_dead_letter_events
|
||||
(event_id,parent_event_id,tenant_code,event_type,biz_type,biz_id,source_service,target_service,dead_id,reason,message,payload,envelope,received_at)
|
||||
VALUES(?,?,?,?,?,?,?,?,?,?,?,CAST(NULLIF(?, '') AS JSON),CAST(? AS JSON),?)`,
|
||||
envelope.EventID, envelope.ParentEventID, envelope.TenantCode, envelope.EventType, envelope.BizType, envelope.BizID,
|
||||
|
||||
Reference in New Issue
Block a user