MM-14357: Remove store call that can provoke dead locks (#10393)

* MM-14357: Remove store call that can provoke dead locks

* Simplify query

* Adding unit test
Этот коммит содержится в:
Jesús Espino
2019-03-04 17:52:26 +01:00
коммит произвёл GitHub
родитель 46a035df79
Коммит 43e6e261d6
6 изменённых файлов: 18 добавлений и 64 удалений

Просмотреть файл

@@ -2449,45 +2449,6 @@ func (s SqlChannelStore) ClearAllCustomRoleAssignments() store.StoreChannel {
})
}
func (s SqlChannelStore) ResetLastPostAt() store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
transaction, err := s.GetMaster().Begin()
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
defer finalizeTransaction(transaction)
*result = s.resetLastPostAtT(transaction)
if result.Err != nil {
return
}
if err := transaction.Commit(); err != nil {
result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
})
}
func (s SqlChannelStore) resetLastPostAtT(transaction *gorp.Transaction) store.StoreResult {
result := store.StoreResult{}
var query string
if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
query = "UPDATE Channels SET LastPostAt = COALESCE((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);"
} else {
query = "UPDATE Channels SET LastPostAt = IFNULL((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);"
}
if _, err := transaction.Exec(query); err != nil {
result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.app_error", nil, err.Error(), http.StatusInternalServerError)
return result
}
return result
}
func (s SqlChannelStore) GetAllChannelsForExportAfter(limit int, afterId string) store.StoreChannel {
return store.Do(func(result *store.StoreResult) {
var data []*model.ChannelForExport

Просмотреть файл

@@ -119,10 +119,10 @@ func (s *SqlPostStore) Save(post *model.Post) store.StoreChannel {
post.Type != model.POST_JOIN_TEAM && post.Type != model.POST_LEAVE_TEAM &&
post.Type != model.POST_ADD_TO_CHANNEL && post.Type != model.POST_REMOVE_FROM_CHANNEL &&
post.Type != model.POST_ADD_TO_TEAM && post.Type != model.POST_REMOVE_FROM_TEAM {
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = :LastPostAt, TotalMsgCount = TotalMsgCount + 1 WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": time, "ChannelId": post.ChannelId})
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = GREATEST(:LastPostAt, LastPostAt), TotalMsgCount = TotalMsgCount + 1 WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": time, "ChannelId": post.ChannelId})
} else {
// don't update TotalMsgCount for unimportant messages so that the channel isn't marked as unread
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = :LastPostAt WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": time, "ChannelId": post.ChannelId})
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = :LastPostAt WHERE Id = :ChannelId AND LastPostAt < :LastPostAt", map[string]interface{}{"LastPostAt": time, "ChannelId": post.ChannelId})
}
if len(post.RootId) > 0 {
@@ -161,10 +161,10 @@ func (s *SqlPostStore) Update(newPost *model.Post, oldPost *model.Post) store.St
result.Err = model.NewAppError("SqlPostStore.Update", "store.sql_post.update.app_error", nil, "id="+newPost.Id+", "+err.Error(), http.StatusInternalServerError)
} else {
time := model.GetMillis()
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = :LastPostAt WHERE Id = :ChannelId", map[string]interface{}{"LastPostAt": time, "ChannelId": newPost.ChannelId})
s.GetMaster().Exec("UPDATE Channels SET LastPostAt = :LastPostAt WHERE Id = :ChannelId AND LastPostAt < :LastPostAt", map[string]interface{}{"LastPostAt": time, "ChannelId": newPost.ChannelId})
if len(newPost.RootId) > 0 {
s.GetMaster().Exec("UPDATE Posts SET UpdateAt = :UpdateAt WHERE Id = :RootId", map[string]interface{}{"UpdateAt": time, "RootId": newPost.RootId})
s.GetMaster().Exec("UPDATE Posts SET UpdateAt = :UpdateAt WHERE Id = :RootId AND UpdateAt < :UpdateAt", map[string]interface{}{"UpdateAt": time, "RootId": newPost.RootId})
}
// mark the old post as deleted