PLT-7444: If there is activity in Mattermost before the email batch is sent, do not send the email (#7342)
* Changed email batching short-circuit logic to look at last viewed at timestamp in channel member struct instead of in user's status struct, since the latter is only updated if the user's status is set to online * Fixed unit tests * Reduced right-hand drift * Reduced total number of store calls by loading all channel member objects for user exactly once per team that the user received notifications for
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
2977b31a39
Коммит
016b5daa1c
@@ -122,24 +122,42 @@ func (job *EmailBatchingJob) handleNewNotifications() {
|
||||
}
|
||||
|
||||
func (job *EmailBatchingJob) checkPendingNotifications(now time.Time, handler func(string, []*batchedNotification)) {
|
||||
// look for users who've acted since pending posts were received
|
||||
for userId, notifications := range job.pendingNotifications {
|
||||
schan := Srv.Store.Status().Get(userId)
|
||||
pchan := Srv.Store.Preference().Get(userId, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL)
|
||||
batchStartTime := notifications[0].post.CreateAt
|
||||
inspectedTeamNames := make(map[string]string)
|
||||
for _, notification := range notifications {
|
||||
// at most, we'll do one check for each team that notifications were sent for
|
||||
if inspectedTeamNames[notification.teamName] != "" {
|
||||
continue
|
||||
}
|
||||
tchan := Srv.Store.Team().GetByName(notifications[0].teamName)
|
||||
if result := <-tchan; result.Err != nil {
|
||||
l4g.Error("Unable to find Team id for notification", result.Err)
|
||||
continue
|
||||
} else if team, ok := result.Data.(*model.Team); ok {
|
||||
inspectedTeamNames[notification.teamName] = team.Id
|
||||
}
|
||||
|
||||
// check if the user has been active and would've seen any new posts
|
||||
if result := <-schan; result.Err != nil {
|
||||
l4g.Error(utils.T("api.email_batching.check_pending_emails.status.app_error"), result.Err)
|
||||
delete(job.pendingNotifications, userId)
|
||||
continue
|
||||
} else if status := result.Data.(*model.Status); status.LastActivityAt >= batchStartTime {
|
||||
delete(job.pendingNotifications, userId)
|
||||
continue
|
||||
// if the user has viewed any channels in this team since the notification was queued, delete
|
||||
// all queued notifications
|
||||
mchan := Srv.Store.Channel().GetMembersForUser(inspectedTeamNames[notification.teamName], userId)
|
||||
if result := <-mchan; result.Err != nil {
|
||||
l4g.Error("Unable to find ChannelMembers for user", result.Err)
|
||||
continue
|
||||
} else if channelMembers, ok := result.Data.(*model.ChannelMembers); ok {
|
||||
for _, channelMember := range *channelMembers {
|
||||
if channelMember.LastViewedAt >= batchStartTime {
|
||||
l4g.Info("Deleted notifications for user %s", userId)
|
||||
delete(job.pendingNotifications, userId)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get how long we need to wait to send notifications to the user
|
||||
var interval int64
|
||||
pchan := Srv.Store.Preference().Get(userId, model.PREFERENCE_CATEGORY_NOTIFICATIONS, model.PREFERENCE_NAME_EMAIL_INTERVAL)
|
||||
if result := <-pchan; result.Err != nil {
|
||||
// use the default batching interval if an error ocurrs while fetching user preferences
|
||||
interval, _ = strconv.ParseInt(model.PREFERENCE_EMAIL_INTERVAL_BATCHING_SECONDS, 10, 64)
|
||||
|
||||
Ссылка в новой задаче
Block a user