feat: support shared tenant database sharding

This commit is contained in:
richjohnrambo
2026-09-22 15:21:34 +08:00
parent 0596599db9
commit 851eca97ed
6 changed files with 265 additions and 76 deletions
+26 -21
View File
@@ -52,7 +52,7 @@ func (s *sSysImGroup) List(ctx context.Context, in *sysin.ImGroupListInp) (list
return
}
mod := s.groupModel(ctx, db)
mod := s.groupModel(ctx, db, tenant.Id)
mod = s.applyGroupWhere(mod, in)
mod = mod.Page(in.Page, in.PerPage).OrderDesc("t.touchedat").OrderDesc("t.id")
@@ -67,11 +67,11 @@ func (s *sSysImGroup) List(ctx context.Context, in *sysin.ImGroupListInp) (list
return
}
func (s *sSysImGroup) groupModel(ctx context.Context, db gdb.DB) *gdb.Model {
func (s *sSysImGroup) groupModel(ctx context.Context, db gdb.DB, tenantId int64) *gdb.Model {
return db.Model("im_topics t").Safe().Ctx(ctx).
LeftJoin("im_group_settings gs", "gs.topic = t.name").
LeftJoin("im_users owner", "owner.id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_user_profiles owner_profile", "owner_profile.user_id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_group_settings gs", "gs.tenant_id = t.tenant_id AND gs.topic = t.name").
LeftJoin("im_users owner", "owner.tenant_id = t.tenant_id AND owner.id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_user_profiles owner_profile", "owner_profile.tenant_id = t.tenant_id AND owner_profile.user_id = COALESCE(gs.owner_user_id, t.owner)").
Fields(
"t.name topic",
"t.state",
@@ -103,6 +103,7 @@ func (s *sSysImGroup) groupModel(ctx context.Context, db gdb.DB) *gdb.Model {
"COALESCE(gs.version, 0) settings_version",
"gs.updated_at settings_updated_at",
).
Where("t.tenant_id", tenantId).
WhereLike("t.name", "grp%")
}
@@ -140,9 +141,9 @@ func (s *sSysImGroup) View(ctx context.Context, in *sysin.ImGroupViewInp) (res *
}
err = db.Model("im_topics t").Safe().Ctx(ctx).
LeftJoin("im_group_settings gs", "gs.topic = t.name").
LeftJoin("im_users owner", "owner.id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_user_profiles owner_profile", "owner_profile.user_id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_group_settings gs", "gs.tenant_id = t.tenant_id AND gs.topic = t.name").
LeftJoin("im_users owner", "owner.tenant_id = t.tenant_id AND owner.id = COALESCE(gs.owner_user_id, t.owner)").
LeftJoin("im_user_profiles owner_profile", "owner_profile.tenant_id = t.tenant_id AND owner_profile.user_id = COALESCE(gs.owner_user_id, t.owner)").
Fields(
"t.name topic",
"t.state",
@@ -176,6 +177,7 @@ func (s *sSysImGroup) View(ctx context.Context, in *sysin.ImGroupViewInp) (res *
"COALESCE(gs.version, 0) settings_version",
"gs.updated_at settings_updated_at",
).
Where("t.tenant_id", tenant.Id).
Where("t.name", in.Topic).
WhereLike("t.name", "grp%").
Scan(&res)
@@ -196,27 +198,27 @@ func (s *sSysImGroup) MemberList(ctx context.Context, in *sysin.ImGroupMemberLis
return
}
db, _, err := resolveImTenantDB(ctx, in.TenantId)
db, tenant, err := resolveImTenantDB(ctx, in.TenantId)
if err != nil {
return
}
if s.hasGroupMemberTruth(ctx, db, in.Topic) {
return s.memberListFromBusiness(ctx, db, in)
if s.hasGroupMemberTruth(ctx, db, tenant.Id, in.Topic) {
return s.memberListFromBusiness(ctx, db, tenant.Id, in)
}
return s.memberListFromProjection(ctx, db, in)
return s.memberListFromProjection(ctx, db, tenant.Id, in)
}
func (s *sSysImGroup) hasGroupMemberTruth(ctx context.Context, db gdb.DB, topic string) bool {
count, err := db.Model("im_group_members").Safe().Ctx(ctx).Where("topic", topic).Count()
func (s *sSysImGroup) hasGroupMemberTruth(ctx context.Context, db gdb.DB, tenantId int64, topic string) bool {
count, err := db.Model("im_group_members").Safe().Ctx(ctx).Where("tenant_id", tenantId).Where("topic", topic).Count()
return err == nil && count > 0
}
func (s *sSysImGroup) memberListFromBusiness(ctx context.Context, db gdb.DB, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
func (s *sSysImGroup) memberListFromBusiness(ctx context.Context, db gdb.DB, tenantId int64, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
mod := db.Model("im_group_members gm").Safe().Ctx(ctx).
LeftJoin("im_users u", "u.id = gm.user_id").
LeftJoin("im_user_profiles up", "up.user_id = gm.user_id").
LeftJoin("im_subscriptions s", "s.topic = gm.topic AND s.userid = gm.user_id").
LeftJoin("im_users u", "u.tenant_id = gm.tenant_id AND u.id = gm.user_id").
LeftJoin("im_user_profiles up", "up.tenant_id = gm.tenant_id AND up.user_id = gm.user_id").
LeftJoin("im_subscriptions s", "s.tenant_id = gm.tenant_id AND s.topic = gm.topic AND s.userid = gm.user_id").
Fields(
"gm.user_id",
"up.nickname",
@@ -242,6 +244,7 @@ func (s *sSysImGroup) memberListFromBusiness(ctx context.Context, db gdb.DB, in
"gm.removed_by",
"gm.version",
).
Where("gm.tenant_id", tenantId).
Where("gm.topic", in.Topic)
if in.UserId > 0 {
mod = mod.Where("gm.user_id", in.UserId)
@@ -260,10 +263,10 @@ func (s *sSysImGroup) memberListFromBusiness(ctx context.Context, db gdb.DB, in
return
}
func (s *sSysImGroup) memberListFromProjection(ctx context.Context, db gdb.DB, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
func (s *sSysImGroup) memberListFromProjection(ctx context.Context, db gdb.DB, tenantId int64, in *sysin.ImGroupMemberListInp) (list []*sysin.ImGroupMemberListModel, totalCount int, err error) {
mod := db.Model("im_subscriptions s").Safe().Ctx(ctx).
LeftJoin("im_users u", "u.id = s.userid").
LeftJoin("im_user_profiles up", "up.user_id = s.userid").
LeftJoin("im_users u", "u.tenant_id = s.tenant_id AND u.id = s.userid").
LeftJoin("im_user_profiles up", "up.tenant_id = s.tenant_id AND up.user_id = s.userid").
Fields(
"s.userid user_id",
"up.nickname",
@@ -289,6 +292,7 @@ func (s *sSysImGroup) memberListFromProjection(ctx context.Context, db gdb.DB, i
"0 removed_by",
"0 version",
).
Where("s.tenant_id", tenantId).
Where("s.topic", in.Topic)
if in.UserId > 0 {
@@ -335,6 +339,7 @@ func (s *sSysImGroup) Governance(ctx context.Context, in *sysin.ImGroupTopicInp)
"created_at",
"updated_at",
).
Where("tenant_id", tenant.Id).
Where("topic", in.Topic).
Scan(&res)
if err != nil {