More notification metrics fixes (#26889)
* Explicitly have the client tell the server when it should expect an ACK * Don't count missing profile errors for your own posts, added comment * Fix test * Make postedAck a parameter in WebSocketClient * Snapshot fixes --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
5f1a357845
Коммит
60c15c821f
@@ -17,6 +17,7 @@ import (
|
||||
const (
|
||||
connectionIDParam = "connection_id"
|
||||
sequenceNumberParam = "sequence_number"
|
||||
postedAckParam = "posted_ack"
|
||||
)
|
||||
|
||||
func (api *API) InitWebSocket() {
|
||||
@@ -48,6 +49,7 @@ func connectWebSocket(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
TFunc: c.AppContext.T,
|
||||
Locale: "",
|
||||
Active: true,
|
||||
PostedAck: r.URL.Query().Get(postedAckParam) == "true",
|
||||
}
|
||||
// The WebSocket upgrade request coming from mobile is missing the
|
||||
// user agent so we need to fallback on the session's metadata.
|
||||
|
||||
@@ -740,15 +740,19 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
|
||||
// A user following a thread but had left the channel won't get a notification
|
||||
// https://mattermost.atlassian.net/browse/MM-36769
|
||||
if profileMap[uid] == nil {
|
||||
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonMissingProfile)
|
||||
a.NotificationsLog().Error("Missing profile",
|
||||
mlog.String("type", model.NotificationTypeWebsocket),
|
||||
mlog.String("post_id", post.Id),
|
||||
mlog.String("status", model.NotificationStatusError),
|
||||
mlog.String("reason", model.NotificationReasonMissingProfile),
|
||||
mlog.String("sender_id", sender.Id),
|
||||
mlog.String("receiver_id", uid),
|
||||
)
|
||||
// This also sometimes happens when bots, which will never show up in the map, reply to threads
|
||||
// Their own post goes through this and they get "notified", which we don't need to count as an error if they can't
|
||||
if uid != post.UserId {
|
||||
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonMissingProfile)
|
||||
a.NotificationsLog().Error("Missing profile",
|
||||
mlog.String("type", model.NotificationTypeWebsocket),
|
||||
mlog.String("post_id", post.Id),
|
||||
mlog.String("status", model.NotificationStatusError),
|
||||
mlog.String("reason", model.NotificationReasonMissingProfile),
|
||||
mlog.String("sender_id", sender.Id),
|
||||
mlog.String("receiver_id", uid),
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if a.IsCRTEnabledForUser(c, uid) {
|
||||
|
||||
@@ -68,6 +68,7 @@ type WebConnConfig struct {
|
||||
Active bool
|
||||
ReuseCount int
|
||||
OriginClient string
|
||||
PostedAck bool
|
||||
|
||||
// These aren't necessary to be exported to api layer.
|
||||
sequence int
|
||||
@@ -89,6 +90,7 @@ type WebConn struct {
|
||||
Locale string
|
||||
Sequence int64
|
||||
UserId string
|
||||
PostedAck bool
|
||||
|
||||
allChannelMembers map[string]string
|
||||
lastAllChannelMembersTime int64
|
||||
@@ -234,6 +236,7 @@ func (ps *PlatformService) NewWebConn(cfg *WebConnConfig, suite SuiteIFace, runn
|
||||
UserId: cfg.Session.UserId,
|
||||
T: cfg.TFunc,
|
||||
Locale: cfg.Locale,
|
||||
PostedAck: cfg.PostedAck,
|
||||
reuseCount: cfg.ReuseCount,
|
||||
endWritePump: make(chan struct{}),
|
||||
pumpFinished: make(chan struct{}),
|
||||
|
||||
@@ -82,11 +82,9 @@ func usePostedAckHook(message *model.WebSocketEvent, postedUserId string, channe
|
||||
}
|
||||
|
||||
func (h *postedAckBroadcastHook) Process(msg *platform.HookedWebSocketEvent, webConn *platform.WebConn, args map[string]any) error {
|
||||
// Don't ACK mobile app websocket events at this time, we may revisit this when we can add this to mobile app
|
||||
if session := webConn.GetSession(); session != nil {
|
||||
if session.IsMobile() {
|
||||
return nil
|
||||
}
|
||||
// Don't ACK unless we say to explicitly
|
||||
if !webConn.PostedAck {
|
||||
return nil
|
||||
}
|
||||
|
||||
postedUserId, err := getTypedArg[string](args, "posted_user_id")
|
||||
|
||||
@@ -87,8 +87,9 @@ func TestPostedAckHook_Process(t *testing.T) {
|
||||
hook := &postedAckBroadcastHook{}
|
||||
userID := model.NewId()
|
||||
webConn := &platform.WebConn{
|
||||
UserId: userID,
|
||||
Platform: &platform.PlatformService{},
|
||||
UserId: userID,
|
||||
Platform: &platform.PlatformService{},
|
||||
PostedAck: true,
|
||||
}
|
||||
webConn.SetSession(&model.Session{})
|
||||
|
||||
@@ -140,12 +141,12 @@ func TestPostedAckHook_Process(t *testing.T) {
|
||||
assert.True(t, msg.Event().GetData()["should_ack"].(bool))
|
||||
})
|
||||
|
||||
t.Run("should not ack for mobile app", func(t *testing.T) {
|
||||
t.Run("should not ack if posted ack is false", func(t *testing.T) {
|
||||
mobileWebConn := &platform.WebConn{
|
||||
UserId: userID,
|
||||
Platform: &platform.PlatformService{},
|
||||
UserId: userID,
|
||||
Platform: &platform.PlatformService{},
|
||||
PostedAck: false,
|
||||
}
|
||||
mobileWebConn.SetSession(&model.Session{Props: map[string]string{"isMobile": "true"}})
|
||||
msg := platform.MakeHookedWebSocketEvent(model.NewWebSocketEvent(model.WebsocketEventPosted, "", "", "", nil, ""))
|
||||
|
||||
hook.Process(msg, mobileWebConn, map[string]any{
|
||||
|
||||
Ссылка в новой задаче
Block a user