Skip to content

Fix EnvironmentSerializer preloads unrelated pipelines/builds

What does this MR do?

Reported at !58748 (comment 562639919) by @ahegyi . Currently, accessing https://gitlab.com/gitlab-org/gitlab-docs/-/environments causes timeout by a massive preloading on unrelated pipelines/builds records.

The culprit

It seems we're preloading all deployments (and pipelines/builds) of each environment, where only the lastest/upcoming deployment is necessary. For example, currently the AR relationship looks like the following:

class Environment < ApplicationRecord
  has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment', inverse_of: :environment
  has_one :upcoming_deployment, -> { running.order('deployments.id DESC') }, class_name: 'Deployment', inverse_of: :environment

and when we execute environments.preload(:last_deployment), it generates the following query:

SELECT "deployments".*
FROM "deployments"
WHERE "deployments"."status" = $1
  AND "deployments"."environment_id" IN ($2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
ORDER BY deployments.id DESC

So the preloader doesn't have idea which deployment the latest per environment, so that loading associated pipelines/builds of all deployments. We need a grouping clause here.

Fortunately, we have Deployment.distinct_on_environment scope that was introduced for a similar problem in environment dashboard context. With it, the AR relationship should be:

class Environment < ApplicationRecord
  has_one :last_deployment, -> { success.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
  has_one :upcoming_deployment, -> { running.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment

which generates the following query:

SELECT DISTINCT ON (environment_id) deployments.*
FROM "deployments"
WHERE "deployments"."status" = $1
  AND "deployments"."environment_id" IN ($2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
ORDER BY environment_id, deployments.id DESC 

This correctly fetches the latest/upcoming deployment per environment. We have confirmed that only relevant pipelines/builds are preloaded for them.

SELECT "ci_pipelines".* FROM "ci_pipelines" WHERE "ci_pipelines"."id" IN ($1, $2) 

Related !58748 (merged)

Screenshots (strongly suggested)

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by Shinya Maeda

Merge request reports