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
-
📋 Does this MR need a changelog?-
I have included a changelog entry. -
I have not included a changelog entry because _____.
-
-
Documentation (if required) -
Code review guidelines -
Merge request performance guidelines -
Style guides -
Database guides -
Separation of EE specific content
Availability and Testing
-
Review and add/update tests for this feature/bug. Consider all test levels. See the Test Planning Process. -
Tested in all supported browsers -
Informed Infrastructure department of a default or new setting change, if applicable per definition of done
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