From fca0a5baf9b87f65b7b6a24d5da6e5c0ba39cd3d Mon Sep 17 00:00:00 2001 From: richjohnrambo Date: Mon, 14 Sep 2026 23:29:33 +0800 Subject: [PATCH] fix: keep friend request success when event publish fails --- server/im_http.go | 4 ++-- server/im_http_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/server/im_http.go b/server/im_http.go index 9a37297..5042e93 100644 --- a/server/im_http.go +++ b/server/im_http.go @@ -4696,8 +4696,8 @@ func serveIMFriendRequestCreate(wrt http.ResponseWriter, req *http.Request) { if imReliableHTTPEventsEnabled(req) { if err = publishIMRelationEvent(principal.TenantID, principal.Uid, target, created.RequestID, "friend.request.created", "新的好友申请", message); err != nil { - writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil) - return + logs.Warn.Printf("im friend request create: relation event failed request_id=%s friend_request_id=%s target=%s: %v", + req.Header.Get("X-Request-ID"), created.RequestID, target.UserId(), err) } } writeIMSuccess(wrt, req, friendRequestPayload(created)) diff --git a/server/im_http_test.go b/server/im_http_test.go index 9b12084..3f38cd5 100644 --- a/server/im_http_test.go +++ b/server/im_http_test.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/json" + "errors" "fmt" "io" "mime/multipart" @@ -299,6 +300,7 @@ type testMailboxStore struct { type testUserSecurityStore struct { unreadByPrefix map[string]int notifications []types.SystemNotification + err error } type testProfilesStore struct { @@ -1017,6 +1019,9 @@ func (s *testUserSecurityStore) SetYouthMode(_ types.TenantID, uid types.Uid, en } func (s *testUserSecurityStore) CreateSystemNotification(_ types.TenantID, notification *types.SystemNotification) error { + if s.err != nil { + return s.err + } if notification != nil { s.notifications = append(s.notifications, *notification) } @@ -8015,6 +8020,42 @@ func TestServeIMFriendRequestCreate(t *testing.T) { } } +func TestServeIMFriendRequestCreateIgnoresRelationEventFailure(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mockStore := expectIMBearer(t, ctrl, "token-1", 7, 1) + mockStore.EXPECT().GetUidString().Return("request-1") + oldRelations := store.Relations + oldProfiles := store.Profiles + oldSecurity := store.Security + relations := &testRelationsStore{context: &types.RelationshipContext{Relationship: types.RelationshipNone}} + store.Relations = relations + store.Profiles = &testProfilesStore{} + store.Security = &testUserSecurityStore{err: errors.New("notification unavailable")} + defer func() { + store.Relations = oldRelations + store.Profiles = oldProfiles + store.Security = oldSecurity + }() + + req := httptest.NewRequest(http.MethodPost, "/v1/im/friend-requests", + bytes.NewBufferString(`{"target_user_id":"`+types.Uid(2).UserId()+`","message":"你好","source":"search"}`)) + req = req.WithContext(context.WithValue(req.Context(), imHTTPProtocolValidated, true)) + req.Header.Set("Authorization", "Bearer token-1") + req.Header.Set("Idempotency-Key", "fr-1") + req.Header.Set("X-Request-ID", "req-event-fail") + rec := httptest.NewRecorder() + + serveIMFriendRequests(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("status: got %d, want %d; body=%s", rec.Code, http.StatusOK, rec.Body.String()) + } + if relations.created == nil || relations.created.RequestID == "" { + t.Fatalf("friend request was not created: %#v", relations.created) + } +} + func TestPublishIMConversationSystemNoticeDeliversToOnlineP2PSessions(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish()