Skip to content

Commit 502cce2

Browse files
committed
PLUTON-19231 | Fewer database calls in VcLTagBuilder.prepare_redirects
Previously, related domains and domain mappings for a given cluster were fetched in a loop, performing many small selects In this change, two types of of data fetching procedures (acquiring all domain mappings, and static domain mappings for each cluster) have been moved to VclRendererInput, and the smaller chunks needed for rendering steps are obtained locally from simple data structures. In local testing, this resulted in roughly halving the time of the prepare_redirects rendering phase (from around 2 to around 0.9 seconds)
1 parent 6090dab commit 502cce2

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

vaas/vaas/vcl/renderer.py

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import time
77
import functools
88
from typing import Dict, List
9+
from urllib.parse import urlsplit
910

1011
from django.conf import settings
1112
from django.db.models import Prefetch
@@ -186,23 +187,50 @@ def __init__(self, varnish, input_data):
186187
'mesh_routing': varnish.cluster.service_mesh_routing
187188
}
188189

190+
def filter_cluster_domain_mappings(
191+
self, cluster: LogicalCluster
192+
) -> dict[str, list[str]]:
193+
"""Returns a dictionary where keys are domains, and values are mapped to by the key"""
194+
# we can PROBABLY assume that each domain has only one mapping
195+
# in an experiment trying to add a new mapping for a source domain removed the old one
196+
destination_dict = {}
197+
for domain_mapping in self.input.domain_mappings:
198+
domain = domain_mapping.domain
199+
destination_dict[domain] = domain_mapping.mapped_domains(cluster)
200+
return destination_dict
201+
202+
def provide_related_domains(self, cluster: LogicalCluster) -> list[str]:
203+
"""Returns a list of all domains related to a cluster - for static mappings,
204+
the list is specified within the mapping, for dynamic - clusters are associated using
205+
labels (mapping targets can contain labels, and each cluster can have multiple labels, but
206+
each label belongs to exactly one cluster)"""
207+
result = {m.domain for m in self.input.static_domain_mappings_by_cluster[cluster.name]}
208+
for m in self.input.mapping_provider.mappings["dynamic"]:
209+
if m.is_cluster_related_by_labels(cluster):
210+
result.add(m.domain)
211+
return sorted(list(result))
212+
189213
@collect_processing
190214
def prepare_redirects(self) -> Dict[str, List[VclRedirect]]:
191215
redirects = {}
192-
related_domains = MappingProvider(DomainMapping.objects.all()).provide_related_domains(self.varnish.cluster) # tutaj juz mamy dwa zapytania do bazy
216+
related_domains = self.provide_related_domains(self.varnish.cluster)
217+
destinations_dict = self.filter_cluster_domain_mappings(self.varnish.cluster)
193218
for redirect in self.input.redirects:
194-
destination_domain, destination_mappings = redirect.fetch_all_destinations_mappings(self.varnish.cluster) # tutaj znów sięgamy do bazy po redirecty i liste mappingow
195-
if str(redirect.src_domain) in related_domains:
196-
for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster):
197-
destination = str(redirect.destination)
198-
if destination_domain == redirect.src_domain.domain:
199-
destination = destination.replace(destination_domain, mapped_domain)
200-
elif all((destination_domain, len(destination_mappings) == 1)):
201-
destination = destination.replace(destination_domain, destination_mappings[0])
202-
if entries := redirects.get(mapped_domain, []):
203-
entries.append(VclRedirect(redirect, mapped_domain, destination))
204-
else:
205-
redirects[mapped_domain] = [VclRedirect(redirect, mapped_domain, destination)]
219+
if str(redirect.src_domain) not in related_domains:
220+
continue
221+
destination_domain = urlsplit(redirect.destination).netloc
222+
destination_mappings = destinations_dict.get(destination_domain)
223+
for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster):
224+
destination = str(redirect.destination)
225+
if destination_domain == redirect.src_domain.domain:
226+
destination = destination.replace(destination_domain, mapped_domain)
227+
elif destination_domain and len(destination_mappings) == 1:
228+
destination = destination.replace(destination_domain, destination_mappings[0])
229+
230+
if entries := redirects.get(mapped_domain, []):
231+
entries.append(VclRedirect(redirect, mapped_domain, destination))
232+
else:
233+
redirects[mapped_domain] = [VclRedirect(redirect, mapped_domain, destination)]
206234
return redirects
207235

208236
@collect_processing
@@ -392,6 +420,18 @@ def fetch_render_data(self):
392420
)
393421
self.distributed_backends = self.distribute_backends(backends)
394422
self.distributed_canary_backends = self.prepare_canary_backends(canary_backend_ids, backends)
423+
self.domain_mappings = DomainMapping.objects.all()
424+
self.mapping_provider = MappingProvider(self.domain_mappings)
425+
self.static_domain_mappings_by_cluster = self.cluster_static_domain_mappings()
426+
427+
def cluster_static_domain_mappings(self) -> dict[str, list[DomainMapping]]:
428+
"""Returns a dict cluster.name: [associated domain mappings]"""
429+
# NTH: get the same output with only one database query, perhaps with prefetch_related()
430+
result_dict = dict()
431+
all_clusters = LogicalCluster.objects.all()
432+
for cluster in all_clusters:
433+
result_dict[cluster.name] = cluster.domainmapping_set.filter(type="static")
434+
return result_dict
395435

396436
@collect_processing
397437
def distribute_backends(self, backends):

0 commit comments

Comments
 (0)