fix: resolve P1 backend consistency issues

This commit is contained in:
richjohnrambo
2026-09-08 16:23:21 +08:00
parent 06945a4050
commit 0b3c0b1c78
13 changed files with 587 additions and 57 deletions
+68 -24
View File
@@ -1760,6 +1760,16 @@ func GetCachedGroupMemberPage(tenantID types.TenantID, key string) (map[string]a
return nil, false
}
func invalidateGroupMemberPages(tenantID types.TenantID, topic string) {
topic = strings.TrimSpace(topic)
if topic == "" {
return
}
if err := DeleteCachedObjectsByPrefix(tenantID, cacheNamespaceGroupPage, topic+"|"); err != nil {
logs.Warn.Printf("cache group member pages[%s]: delete failed: %v", topic, err)
}
}
func (groupBusinessMapper) UpdateMember(tenantID types.TenantID, topic string, uid types.Uid, patch types.GroupMemberPatch) (*types.GroupMember, error) {
if strings.TrimSpace(topic) == "" || uid.IsZero() {
return nil, types.ErrMalformed
@@ -1775,6 +1785,7 @@ func (groupBusinessMapper) UpdateMember(tenantID types.TenantID, topic string, u
} else {
_ = DeleteCachedObject(tenantID, cacheNamespaceGroupMember, groupMemberCacheID(strings.TrimSpace(topic), uid))
}
invalidateGroupMemberPages(tenantID, topic)
}
return member, err
}
@@ -1798,7 +1809,11 @@ func (groupBusinessMapper) AcceptInvitation(tenantID types.TenantID, invitationI
if err != nil {
return nil, err
}
return tenantAdp.TenantGroupInvitationAccept(tenantID, strings.TrimSpace(invitationID), uid, memberPrivate, now)
invitation, err := tenantAdp.TenantGroupInvitationAccept(tenantID, strings.TrimSpace(invitationID), uid, memberPrivate, now)
if err == nil && invitation != nil {
invalidateGroupMemberPages(tenantID, invitation.Topic)
}
return invitation, err
}
func (groupBusinessMapper) CreateJoinRequest(tenantID types.TenantID, req *types.GroupJoinRequest) (*types.GroupJoinRequest, error) {
@@ -1834,7 +1849,11 @@ func (groupBusinessMapper) ResolveJoinRequest(tenantID types.TenantID, topic, re
if err != nil {
return nil, err
}
return tenantAdp.TenantGroupJoinRequestResolve(tenantID, strings.TrimSpace(topic), strings.TrimSpace(requestID), actor, strings.TrimSpace(action), strings.TrimSpace(rejectReason), version, memberPrivate, now)
resolved, err := tenantAdp.TenantGroupJoinRequestResolve(tenantID, strings.TrimSpace(topic), strings.TrimSpace(requestID), actor, strings.TrimSpace(action), strings.TrimSpace(rejectReason), version, memberPrivate, now)
if err == nil && resolved != nil && resolved.Status == types.GroupJoinRequestStatusAccepted {
invalidateGroupMemberPages(tenantID, topic)
}
return resolved, err
}
func (groupBusinessMapper) LatestAnnouncement(tenantID types.TenantID, topic string) (*types.GroupAnnouncement, error) {
@@ -1951,8 +1970,12 @@ func (groupBusinessMapper) InviteMember(tenantID types.TenantID, topic string, i
if err != nil {
return false, err
}
return tenantAdp.TenantGroupInviteMember(tenantID, strings.TrimSpace(topic), inviter, target,
created, err := tenantAdp.TenantGroupInviteMember(tenantID, strings.TrimSpace(topic), inviter, target,
strings.TrimSpace(message), strings.TrimSpace(idempotencyKey), private, now)
if err == nil {
invalidateGroupMemberPages(tenantID, topic)
}
return created, err
}
func (groupBusinessMapper) Leave(tenantID types.TenantID, topic string, uid types.Uid, now time.Time) error {
@@ -1969,6 +1992,7 @@ func (groupBusinessMapper) Leave(tenantID types.TenantID, topic string, uid type
_ = DeleteCachedObject(tenantID, cacheNamespaceGroupMember, groupMemberCacheID(strings.TrimSpace(topic), uid))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(strings.TrimSpace(topic), uid, false))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(strings.TrimSpace(topic), uid, true))
invalidateGroupMemberPages(tenantID, topic)
return nil
}
@@ -1987,6 +2011,7 @@ func (groupBusinessMapper) UpdateRole(tenantID types.TenantID, topic string, act
_ = DeleteCachedObject(tenantID, cacheNamespaceGroupMember, groupMemberCacheID(strings.TrimSpace(topic), target))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(strings.TrimSpace(topic), target, false))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(strings.TrimSpace(topic), target, true))
invalidateGroupMemberPages(tenantID, topic)
return nil
}
@@ -1999,7 +2024,17 @@ func (groupBusinessMapper) TransferOwner(tenantID types.TenantID, topic string,
if err != nil {
return err
}
return tenantAdp.TenantGroupOwnerTransfer(tenantID, strings.TrimSpace(topic), previousOwner, newOwner, version, now)
topic = strings.TrimSpace(topic)
if err = tenantAdp.TenantGroupOwnerTransfer(tenantID, topic, previousOwner, newOwner, version, now); err != nil {
return err
}
for _, uid := range []types.Uid{previousOwner, newOwner} {
_ = DeleteCachedObject(tenantID, cacheNamespaceGroupMember, groupMemberCacheID(topic, uid))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(topic, uid, false))
_ = DeleteCachedObject(tenantID, cacheNamespaceSub, subscriptionCacheID(topic, uid, true))
}
invalidateGroupMemberPages(tenantID, topic)
return nil
}
func (groupBusinessMapper) CanPost(tenantID types.TenantID, topic string, uid types.Uid, admin bool, now time.Time) (bool, error) {
@@ -2848,6 +2883,22 @@ func refreshUserProfileProjections(tenantID types.TenantID, uid types.Uid, profi
return
}
public := userProfilePublicProjection(profile)
if user, err := Users.Get(tenantID, uid); err != nil {
logs.Warn.Printf("profile %s: load native user projection failed: %v", uid, err)
} else if user != nil {
merged := make(map[string]any)
if encoded, marshalErr := json.Marshal(user.Public); marshalErr == nil {
_ = json.Unmarshal(encoded, &merged)
}
for key, value := range public {
merged[key] = value
}
if err = Users.Update(tenantID, uid, map[string]any{"Public": merged}); err != nil {
logs.Warn.Printf("profile %s: update native user projection failed: %v", uid, err)
} else {
public = merged
}
}
cursor := ""
for {
items, nextCursor, err := Relations.ListFriends(tenantID, uid, "", "", cursor, 100)
@@ -2871,27 +2922,17 @@ func refreshUserProfileProjections(tenantID types.TenantID, uid types.Uid, profi
}
func userProfilePublicProjection(profile *types.UserProfile) map[string]any {
public := make(map[string]any)
nickname := strings.TrimSpace(profile.Nickname)
if nickname != "" {
for _, key := range []string{"display_name", "nickname", "fn", "name"} {
public[key] = nickname
}
}
if value := strings.TrimSpace(profile.AvatarFileID); value != "" {
public["avatar_file_id"] = value
}
if value := strings.TrimSpace(profile.Signature); value != "" {
public["signature"] = value
}
if value := strings.TrimSpace(profile.Gender); value != "" {
public["gender"] = value
}
if value := strings.TrimSpace(profile.Region); value != "" {
public["region"] = value
}
if value := strings.TrimSpace(profile.PublicAccount); value != "" {
public["public_account"] = value
public := map[string]any{
"display_name": nickname,
"nickname": nickname,
"fn": nickname,
"name": nickname,
"avatar_file_id": strings.TrimSpace(profile.AvatarFileID),
"signature": strings.TrimSpace(profile.Signature),
"gender": strings.TrimSpace(profile.Gender),
"region": strings.TrimSpace(profile.Region),
"public_account": strings.TrimSpace(profile.PublicAccount),
}
return public
}
@@ -2959,6 +3000,9 @@ func validUserProfilePatch(patch types.UserProfilePatch) bool {
if patch.Email != nil && len([]rune(strings.TrimSpace(*patch.Email))) > 128 {
return false
}
if patch.Region != nil && len([]rune(strings.TrimSpace(*patch.Region))) > 128 {
return false
}
return true
}