From 5c11c9eeae8dd7e2807b9ba2ed7b0352793ce793 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 22 Oct 2025 23:54:27 -0700 Subject: [PATCH] Reduce cached SQL queries in `/api/v4/internal/pages` endpoint Previously `VirtualDomain#pages_access_control_trie` dominated the CPU profile because the memoization was not working properly. It was being memoized with the value of `self_and_descendants`, which is a different object ID each time the method is called. Fix this by memoizing `pages_access_control_trie` directly. Changelog: performance --- app/models/namespace.rb | 6 ++---- app/models/pages/virtual_domain.rb | 9 ++++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 2cefcb8fc7da90..162cd600734c44 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -801,11 +801,9 @@ def allow_runner_registration_token? end def pages_access_control_trie(namespaces = self_and_descendants) - strong_memoize_with(:pages_access_control_trie, namespaces) do - traversal_ids = namespaces.joins(:namespace_settings).where(namespace_settings: { force_pages_access_control: true }).map(&:traversal_ids) + traversal_ids = namespaces.joins(:namespace_settings).where(namespace_settings: { force_pages_access_control: true }).map(&:traversal_ids) - Namespaces::Traversal::TrieNode.build(traversal_ids) - end + Namespaces::Traversal::TrieNode.build(traversal_ids) end def pages_access_control_forced_by_self_or_ancestor? diff --git a/app/models/pages/virtual_domain.rb b/app/models/pages/virtual_domain.rb index b6f259dba7932d..f9d751e71d92d2 100644 --- a/app/models/pages/virtual_domain.rb +++ b/app/models/pages/virtual_domain.rb @@ -2,6 +2,8 @@ module Pages class VirtualDomain + include Gitlab::Utils::StrongMemoize + def initialize(projects:, trim_prefix: nil, domain: nil, namespace: nil) @projects = projects @trim_prefix = trim_prefix @@ -34,8 +36,13 @@ def access_control_for(project) return true if ::Gitlab::Pages.access_control_is_forced? return true if project.project_feature&.private_pages? - @namespace&.pages_access_control_trie&.covered?(project.namespace.traversal_ids) + pages_access_control_trie&.covered?(project.namespace.traversal_ids) + end + + def pages_access_control_trie + @namespace&.pages_access_control_trie end + strong_memoize_attr :pages_access_control_trie def lookup_paths_for(project, root_namespace_id) deployments_for(project).map do |deployment| -- GitLab