MM-63923/MM-63924/MM-63925 Prevent deadlocks and constraint errors in UpdateSidebarCategories (#30965)

* MM-63925 Remove most nested transactions from channel_store_categories.go

There's one place which still has a nested transaction in
CreateInitialSidebarCategories, but that's because it's calling out to a
different part of the store. The only way to avoid that would be to
break the extraction like UpdateSidebarCategories does to update
preferences, but I chose not to follow that pattern here and leave it
as-is.

* MM-63923 Prevent deadlocks caused by updating multiple categories in a different order

* MM-63923 Prevent deadlocks while deleting from SidebarChannels

This could also have been resolved by sorting the categories, but
combining the queries seems a bit more elegant.

* MM-63924 Ensure adding SidebarChannels rows is idempotent

* Add additional test to cause deadlocks

* Prevent channels from appearing in a single category multiple times

* Other review feedback
Этот коммит содержится в:
Harrison Healey
2025-05-20 16:02:32 -04:00
коммит произвёл GitHub
родитель fa40a8c5d4
Коммит b70f1d859d
4 изменённых файлов: 356 добавлений и 70 удалений

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

@@ -257,6 +257,8 @@ func validateSidebarCategories(c *Context, teamId, userId string, categories []*
return nil
}
// validateSidebarCategoryChannels returns a normalized slice of channel IDs by removing duplicates from it and
// ensuring that it only contains IDs of channels in the given ChannelList.
func validateSidebarCategoryChannels(c *Context, userId string, channelIds []string, channels model.ChannelList) []string {
var filtered []string
@@ -276,6 +278,8 @@ func validateSidebarCategoryChannels(c *Context, userId string, channelIds []str
}
}
filtered = model.RemoveDuplicateStringsNonSort(filtered)
return filtered
}

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

@@ -1063,7 +1063,7 @@ func TestValidateSidebarCategoryChannels(t *testing.T) {
require.Empty(t, filtered)
})
t.Run("should preserve duplicate channel IDs", func(t *testing.T) {
t.Run("should prevent duplicate channel IDs", func(t *testing.T) {
channels := model.ChannelList{
th.BasicChannel,
}
@@ -1075,8 +1075,8 @@ func TestValidateSidebarCategoryChannels(t *testing.T) {
}
filtered := validateSidebarCategoryChannels(c, th.BasicUser.Id, channelIds, channels)
require.Len(t, filtered, 2) // Function preserves duplicates as per implementation
require.Equal(t, []string{th.BasicChannel.Id, th.BasicChannel.Id}, filtered)
require.Len(t, filtered, 1)
require.Equal(t, []string{th.BasicChannel.Id}, filtered)
})
}