Repository: OpenIMSDK/Open-IM-Server
File: internal/rpc/msg/as_read.go (Go)

Code before:
	if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
		m.conversationAndGetRecvID(conversation, req.UserID), req.Seqs, hasReadSeq); err != nil {
		return
	}
	return &msg.MarkMsgsAsReadResp{}, nil
}

func (m *msgServer) MarkConversationAsRead(
	ctx context.Context,
	req *msg.MarkConversationAsReadReq,
) (resp *msg.MarkConversationAsReadResp, err error) {
	conversation, err := m.Conversation.GetConversation(ctx, req.UserID, req.ConversationID)
	if err != nil {
		return nil, err
	}
	hasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID)
	if err != nil && errs.Unwrap(err) != redis.Nil {
		return nil, err
	}
	var seqs []int64

	log.ZDebug(ctx, "MarkConversationAsRead", "hasReadSeq", hasReadSeq,
		"req.HasReadSeq", req.HasReadSeq)
	if conversation.ConversationType == constant.SingleChatType {
		for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ {
			seqs = append(seqs, i)
		}
		//avoid client missed call MarkConversationMessageAsRead by order
		for _, val := range req.Seqs {
			if !utils2.Contain(val, seqs...) {
				seqs = append(seqs, val)
			}
		}
		if len(seqs) > 0 {
			log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID)
			if err = m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil {
				return nil, err
			}
		}
		if req.HasReadSeq > hasReadSeq {
			err = m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq)
			if err != nil {
				return nil, err
			}
			hasReadSeq = req.HasReadSeq
		}
		if err = m.sendMarkAsReadNotification(ctx, req.ConversationID, conversation.ConversationType, req.UserID,
			m.conversationAndGetRecvID(conversation, req.UserID), seqs, hasReadSeq); err != nil {
			return nil, err
		}
	} else if conversation.ConversationType == constant.SuperGroupChatType ||

Review comment (refactor):
simplify code

```go
		for i := hasReadSeq + 1; i <= req.HasReadSeq; i++ {
			//avoid client missed call MarkConversationMessageAsRead by order
			if !utils2.Contain(val, seqs...) {
				seqs = append(seqs, val)
			}
		}

```

Code after:
		m.conversationAndGetRecvID(conversation, req.UserID), req.Seqs, hasReadSeq); err != nil {
		return
	}
	return &msg.MarkMsgsAsReadResp{}, nil
}

func (m *msgServer) MarkConversationAsRead(ctx context.Context, req *msg.MarkConversationAsReadReq) (resp *msg.MarkConversationAsReadResp, err error) {
	conversation, err := m.Conversation.GetConversation(ctx, req.UserID, req.ConversationID)
	if err != nil {
		return nil, err
	}
	hasReadSeq, err := m.MsgDatabase.GetHasReadSeq(ctx, req.UserID, req.ConversationID)
	if err != nil && errs.Unwrap(err) != redis.Nil {
		return nil, err
	}
	seqs := generateSeqs(hasReadSeq, req)

	if len(seqs) > 0 || req.HasReadSeq > hasReadSeq {
		err = m.updateReadStatus(ctx, req, conversation, seqs, hasReadSeq)
		if err != nil {
			return nil, err
		}
	}
	return &msg.MarkConversationAsReadResp{}, nil
}

func generateSeqs(hasReadSeq int64, req *msg.MarkConversationAsReadReq) []int64 {
	var seqs []int64
	for _, val := range req.Seqs {
		if val > hasReadSeq && !utils2.Contain(val, seqs...) {
			seqs = append(seqs, val)
		}
	}
	return seqs
}

func (m *msgServer) updateReadStatus(ctx context.Context, req *msg.MarkConversationAsReadReq, conversation *conversation.Conversation, seqs []int64, hasReadSeq int64) error {
	if conversation.ConversationType == constant.SingleChatType && len(seqs) > 0 {
		log.ZDebug(ctx, "MarkConversationAsRead", "seqs", seqs, "conversationID", req.ConversationID)
		if err := m.MsgDatabase.MarkSingleChatMsgsAsRead(ctx, req.UserID, req.ConversationID, seqs); err != nil {
			return err
		}
	}

	if req.HasReadSeq > hasReadSeq {
		if err := m.MsgDatabase.SetHasReadSeq(ctx, req.UserID, req.ConversationID, req.HasReadSeq); err != nil {
			return err
		}
	}

	recvID := m.conversationAndGetRecvID(conversation, req.UserID)