Add channels dataloader

https://mattermost.atlassian.net/browse/MM-43145

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2022-04-11 13:41:09 +05:30
коммит произвёл GitHub
родитель 4b354685e9
Коммит d1de4857aa
14 изменённых файлов: 277 добавлений и 90 удалений

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

@@ -62,10 +62,13 @@ func (api *API) InitGraphQL() error {
type ctxKey int
const (
webCtx ctxKey = 0
rolesLoaderCtx ctxKey = 1
webCtx ctxKey = 0
rolesLoaderCtx ctxKey = 1
channelsLoaderCtx ctxKey = 2
)
const loaderBatchCapacity = 200
func (api *API) graphQL(c *Context, w http.ResponseWriter, r *http.Request) {
var response *graphql.Response
defer func() {
@@ -98,9 +101,12 @@ func (api *API) graphQL(c *Context, w http.ResponseWriter, r *http.Request) {
reqCtx := r.Context()
reqCtx = context.WithValue(reqCtx, webCtx, c)
rolesLoader := dataloader.NewBatchedLoader(graphQLRolesLoader, dataloader.WithBatchCapacity(200))
rolesLoader := dataloader.NewBatchedLoader(graphQLRolesLoader, dataloader.WithBatchCapacity(loaderBatchCapacity))
reqCtx = context.WithValue(reqCtx, rolesLoaderCtx, rolesLoader)
channelsLoader := dataloader.NewBatchedLoader(graphQLChannelsLoader, dataloader.WithBatchCapacity(loaderBatchCapacity))
reqCtx = context.WithValue(reqCtx, channelsLoaderCtx, channelsLoader)
response = api.schema.Exec(reqCtx,
params.Query,
params.OperationName,

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

@@ -294,3 +294,12 @@ func getRolesLoader(ctx context.Context) (*dataloader.Loader, error) {
}
return l, nil
}
// getChannelsLoader returns the channels loader out of the context.
func getChannelsLoader(ctx context.Context) (*dataloader.Loader, error) {
l, ok := ctx.Value(channelsLoaderCtx).(*dataloader.Loader)
if !ok {
return nil, errors.New("no dataloader.Loader found in context")
}
return l, nil
}

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

@@ -31,11 +31,18 @@ func (cm *channelMember) Channel(ctx context.Context) (*channel, error) {
return nil, err
}
channel, appErr := c.App.GetChannel(cm.ChannelId)
if appErr != nil {
return nil, appErr
loader, err := getChannelsLoader(ctx)
if err != nil {
return nil, err
}
thunk := loader.Load(ctx, dataloader.StringKey(cm.ChannelId))
result, err := thunk()
if err != nil {
return nil, err
}
channel := result.(*model.Channel)
if channel.Type == model.ChannelTypeOpen {
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), channel.TeamId, model.PermissionReadPublicChannel) &&
!c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), cm.ChannelId, model.PermissionReadChannel) {
@@ -49,7 +56,7 @@ func (cm *channelMember) Channel(ctx context.Context) (*channel, error) {
}
}
appErr = c.App.FillInChannelProps(channel)
appErr := c.App.FillInChannelProps(channel)
if appErr != nil {
return nil, appErr
}
@@ -65,6 +72,56 @@ func (cm *channelMember) Channel(ctx context.Context) (*channel, error) {
return res[0], nil
}
func graphQLChannelsLoader(ctx context.Context, keys dataloader.Keys) []*dataloader.Result {
stringKeys := keys.Keys()
result := make([]*dataloader.Result, len(stringKeys))
c, err := getCtx(ctx)
if err != nil {
for i := range result {
result[i] = &dataloader.Result{Error: err}
}
return result
}
channels, err := getGraphQLChannels(c, stringKeys)
if err != nil {
for i := range result {
result[i] = &dataloader.Result{Error: err}
}
return result
}
for i, ch := range channels {
result[i] = &dataloader.Result{Data: ch}
}
return result
}
func getGraphQLChannels(c *web.Context, channelIDs []string) ([]*model.Channel, error) {
channels, appErr := c.App.GetChannels(channelIDs)
if appErr != nil {
return nil, appErr
}
if len(channels) != len(channelIDs) {
return nil, fmt.Errorf("all channels were not found. Requested %d; Found %d", len(channelIDs), len(channels))
}
// The channels need to be in the exact same order as the input slice.
tmp := make(map[string]*model.Channel)
for _, ch := range channels {
tmp[ch.Id] = ch
}
// We reuse the same slice and just rewrite the channels.
for i, id := range channelIDs {
channels[i] = tmp[id]
}
return channels, nil
}
func (cm *channelMember) Roles_(ctx context.Context) ([]*model.Role, error) {
loader, err := getRolesLoader(ctx)
if err != nil {
@@ -98,13 +155,17 @@ func graphQLRolesLoader(ctx context.Context, keys dataloader.Keys) []*dataloader
c, err := getCtx(ctx)
if err != nil {
result[0] = &dataloader.Result{Error: err}
for i := range result {
result[i] = &dataloader.Result{Error: err}
}
return result
}
roles, err := getGraphQLRoles(c, stringKeys)
if err != nil {
result[0] = &dataloader.Result{Error: err}
for i := range result {
result[i] = &dataloader.Result{Error: err}
}
return result
}