diff options
Diffstat (limited to 'doc/development/api_graphql_styleguide.md')
-rw-r--r-- | doc/development/api_graphql_styleguide.md | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index d73c3a8d6f6..85098689392 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -10,7 +10,10 @@ This document outlines the style guide for the GitLab [GraphQL API](../api/graph ## How GitLab implements GraphQL +<!-- vale gitlab.Spelling = NO --> We use the [GraphQL Ruby gem](https://graphql-ruby.org/) written by [Robert Mosolgo](https://github.com/rmosolgo/). +<!-- vale gitlab.Spelling = YES --> +In addition, we have a subscription to [GraphQL Pro](https://www.graphql.pro). For details see [GraphQL Pro subscription](graphql_guide/graphql_pro.md). All GraphQL queries are directed to a single endpoint ([`app/controllers/graphql_controller.rb#execute`](https://gitlab.com/gitlab-org/gitlab/blob/master/app%2Fcontrollers%2Fgraphql_controller.rb)), @@ -21,6 +24,7 @@ which is exposed as an API endpoint at `/api/graphql`. In March 2019, Nick Thomas hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on the GitLab [GraphQL API](../api/graphql/index.md) to share his domain specific knowledge with anyone who may work in this part of the codebase in the future. You can find the +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> [recording on YouTube](https://www.youtube.com/watch?v=-9L_1MWrjkg), and the slides on [Google Slides](https://docs.google.com/presentation/d/1qOTxpkTdHIp1CRjuTvO-aXg0_rUtzE3ETfLUdnBB5uQ/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/8e78ea7f326b2ef649e7d7d569c26d56/GraphQL_Deep_Dive__Create_.pdf). @@ -42,6 +46,36 @@ can be shared. It's also possible to add a `private_token` to the query string, or add a `HTTP_PRIVATE_TOKEN` header. +## Limits + +Several limits apply to the GraphQL API and some of these can be overridden +by developers. + +### Max page size + +By default, [connections](#connection-types) can only return +at most a maximum number of records defined in +[`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb) +per page. + +Developers can [specify a custom max page size](#page-size-limit) when defining +a connection. + +### Max complexity + +Complexity is explained [on our client-facing API page](../api/graphql/index.md#max-query-complexity). + +Fields default to adding `1` to a query's complexity score, but developers can +[specify a custom complexity](#field-complexity) when defining a field. + +To estimate the complexity of a query, you can run the +[`gitlab:graphql:analyze`](rake_tasks.md#analyze-graphql-queries) +Rake task. + +### Request timeout + +Requests time out at 30 seconds. + ## Global IDs The GitLab GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`) @@ -281,6 +315,61 @@ Use the functionality the framework provides unless there is a compelling reason For example, instead of `latest_pipeline`, use `pipelines(last: 1)`. +#### Page size limit + +By default, the API returns at most a maximum number of records defined in +[`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb) +per page within a connection and this will also be the default number of records +returned per page if no limiting arguments (`first:` or `last:`) are provided by a client. + +The `max_page_size` argument can be used to specify a different page size limit +for a connection. + +WARNING: +It's better to change the frontend client, or product requirements, to not need large amounts of +records per page than it is to raise the `max_page_size`, as the default is set to ensure +the GraphQL API remains performant. + +For example: + +```ruby +field :tags, + Types::ContainerRepositoryTagType.connection_type, + null: true, + description: 'Tags of the container repository', + max_page_size: 20 +``` + +### Field complexity + +The GitLab GraphQL API uses a _complexity_ score to limit performing overly complex queries. +Complexity is described in [our client documentation](../api/graphql/index.md#max-query-complexity) on the topic. + +Complexity limits are defined in [`app/graphql/gitlab_schema.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/gitlab_schema.rb). + +By default, fields will add `1` to a query's complexity score. This can be overridden by +[providing a custom `complexity`](https://graphql-ruby.org/queries/complexity_and_depth.html) value for a field. + +Developers should specify higher complexity for fields that cause more _work_ to be performed +by the server in order to return data. Fields that represent data that can be returned +with little-to-no _work_, for example in most cases; `id` or `title`, can be given a complexity of `0`. + +### `calls_gitaly` + +Fields that have the potential to perform a [Gitaly](../administration/gitaly/index.md) call when resolving _must_ be marked as +such by passing `calls_gitaly: true` to `field` when defining it. + +For example: + +```ruby +field :blob, type: Types::Snippets::BlobType, + description: 'Snippet blob', + null: false, + calls_gitaly: true +``` + +This will increment the [`complexity` score](#field-complexity) of the field by `1`. + ### Exposing permissions for a type To expose permissions the current user has on a resource, you can call @@ -1599,7 +1688,7 @@ full stack: - An argument or scalar's [`prepare`](#validating-arguments) applies correctly. - Logic in a resolver or mutation's [`#ready?` method](#correct-use-of-resolverready) applies correctly. - An [argument's `default_value`](https://graphql-ruby.org/fields/arguments.html) applies correctly. -- Objects resolve performantly and there are no N+1 issues. +- Objects resolve successfully, and there are no N+1 issues. When adding a query, you can use the `a working graphql query` shared example to test if the query renders valid results. |