feat: improve group member events and push delivery

This commit is contained in:
richjohnrambo
2026-09-18 01:00:41 +08:00
parent 0e2f4e73d1
commit c6e7f6b923
13 changed files with 521 additions and 19 deletions
+56
View File
@@ -339,6 +339,9 @@ func (s *testGroupBusinessStore) UpsertMember(_ types.TenantID, member *types.Gr
}
func (s *testGroupBusinessStore) GetMember(_ types.TenantID, topic string, uid types.Uid) (*types.GroupMember, error) {
if s.member != nil {
return s.member, nil
}
return &types.GroupMember{Topic: topic, UserID: uid, Role: types.GroupMemberRoleMember, MemberStatus: types.GroupMemberStatusActive, Version: 1}, nil
}
@@ -3034,6 +3037,59 @@ func TestServeIMGroupMembers(t *testing.T) {
}
}
func TestServeIMGroupMemberReturnsSingleSnapshot(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
expectIMBearer(t, ctrl, "token-1", 7, 42)
oldSubs := store.Subs
oldUsers := store.Users
oldGroupBusiness := store.GroupBusiness
oldRelations := store.Relations
subs := mock_store.NewMockSubsPersistenceInterface(ctrl)
users := mock_store.NewMockUsersPersistenceInterface(ctrl)
store.Subs = subs
store.Users = users
memberID := types.Uid(101)
joinedAt := time.Date(2026, 9, 18, 0, 0, 0, 0, time.UTC)
store.GroupBusiness = &testGroupBusinessStore{member: &types.GroupMember{
ID: 101, Topic: "grpMention", UserID: memberID, Role: types.GroupMemberRoleMember,
MemberStatus: types.GroupMemberStatusActive, Nickname: "群里小王", Version: 3,
JoinedAt: joinedAt, UpdatedAt: joinedAt.Add(time.Minute),
}}
store.Relations = &testRelationsStore{context: &types.RelationshipContext{
TenantID: 7, UserID: 42, PeerID: memberID, Relationship: types.RelationshipNone,
}}
t.Cleanup(func() {
store.Subs = oldSubs
store.Users = oldUsers
store.GroupBusiness = oldGroupBusiness
store.Relations = oldRelations
})
fullSub := func(uid types.Uid) *types.Subscription {
return &types.Subscription{TenantID: 7, User: uid.String(), Topic: "grpMention", ModeWant: types.ModeCFull, ModeGiven: types.ModeCFull}
}
subs.EXPECT().Get(types.TenantID(7), "grpMention", types.Uid(42), false).Return(fullSub(42), nil)
subs.EXPECT().Get(types.TenantID(7), "grpMention", memberID, false).Return(fullSub(memberID), nil)
users.EXPECT().Get(types.TenantID(7), memberID).Return(&types.User{
ObjHeader: types.ObjHeader{Id: memberID.String()}, Public: map[string]any{"nickname": "Alice", "avatar_file_id": "alice.jpg"},
}, nil)
req := httptest.NewRequest(http.MethodGet, "/v1/im/groups/grpMention/members/"+memberID.UserId(), nil)
req.Header.Set("Authorization", "Bearer token-1")
rec := httptest.NewRecorder()
serveIMGroupResource(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status: got %d, want %d; body=%s", rec.Code, http.StatusOK, rec.Body.String())
}
data := decodeIMHTTPResponse(t, rec).Data.(map[string]any)
if data["user_id"] != memberID.UserId() || data["sync_mode"] != "single" || data["version"].(float64) != 3 ||
data["group_nickname"] != "群里小王" || data["nickname"] != "Alice" {
t.Fatalf("unexpected single member response: %#v", data)
}
}
func TestGroupMemberPayloadUserIDFormats(t *testing.T) {
raw := types.Uid(101)
fromRaw := groupMemberPayload(types.Subscription{