MM-43145: channels loader (#19957)
Add channels dataloader https://mattermost.atlassian.net/browse/MM-43145 ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
4b354685e9
Коммит
d1de4857aa
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user