Skip to content

Commit 5b5a967

Browse files
committed
PLUTON-19231 | Implement @awmackowiak's changes
Draft pull request: #519 This changes the iteration order during prepare_redirects (changing the loop from: ```for redirect in self.input.redirects: ... for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster): ``` to: ```for related_domain in related_domains: ... for redirect in self.input.redirects.get(related_domain): ... for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster): ``` In testing this caused a speedup in the time to prepare redirects from ~0.7 to ~0.1
1 parent 502cce2 commit 5b5a967

File tree

5 files changed

+48
-96
lines changed

5 files changed

+48
-96
lines changed

vaas/vaas/router/models.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# -*- coding: utf-8 -*-
22
import uuid
3-
from typing import Dict, Tuple, List
3+
from typing import Dict
44
from django.db import models
55
from django.conf import settings
66
from django.core.validators import MinValueValidator, MaxValueValidator
7-
from urllib.parse import urlsplit
87

98
from vaas.cluster.models import DomainMapping, LogicalCluster
109
from vaas.manager.models import Director
@@ -37,16 +36,6 @@ class ResponseStatusCode(models.IntegerChoices):
3736
def get_hashed_assertions_pks(self) -> Dict[int, int]:
3837
return {hash((a.given_url, a.expected_location)): a.pk for a in self.assertions.all()}
3938

40-
def fetch_all_destinations_mappings(self, cluster: LogicalCluster) -> Tuple[str, List[str]]:
41-
"""
42-
Fetch tuple containing domain parsed from destination url and all found mappings for input cluster
43-
"""
44-
all_mappings = set()
45-
destination_domain = urlsplit(self.destination).netloc
46-
for domain_mapping in DomainMapping.objects.filter(domain=destination_domain):
47-
all_mappings = all_mappings.union(set(domain_mapping.mapped_domains(cluster)))
48-
return destination_domain, list(all_mappings)
49-
5039
@property
5140
def final_condition(self):
5241
if self.required_custom_header:

vaas/vaas/vcl/renderer.py

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import hashlib
66
import time
77
import functools
8-
from typing import Dict, List
98
from urllib.parse import urlsplit
109

1110
from django.conf import settings
@@ -187,50 +186,36 @@ def __init__(self, varnish, input_data):
187186
'mesh_routing': varnish.cluster.service_mesh_routing
188187
}
189188

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))
189+
def fetch_all_destinations_mappings(self, cluster: LogicalCluster, redirect: str,
190+
domain_mappings: list[DomainMapping]) -> tuple[str, list[str]]:
191+
"""Fetch tuple containing domain parsed from destination url and all found mappings for input cluster
192+
"""
193+
all_mappings = set()
194+
destination_domain = urlsplit(redirect).netloc
195+
for domain_mapping in domain_mappings:
196+
all_mappings = all_mappings.union(set(domain_mapping.mapped_domains(cluster)))
197+
return destination_domain, list(all_mappings)
212198

213199
@collect_processing
214-
def prepare_redirects(self) -> Dict[str, List[VclRedirect]]:
215-
redirects = {}
216-
related_domains = self.provide_related_domains(self.varnish.cluster)
217-
destinations_dict = self.filter_cluster_domain_mappings(self.varnish.cluster)
218-
for redirect in self.input.redirects:
219-
if str(redirect.src_domain) not in related_domains:
200+
def prepare_redirects(self) -> dict[str, list[VclRedirect]]:
201+
redirects = dict()
202+
related_domains = self.input.mapping_provider.provide_related_domains(self.varnish.cluster)
203+
for related_domain in related_domains:
204+
if related_domain not in self.input.redirects.keys():
220205
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)]
206+
for redirect in self.input.redirects.get(related_domain):
207+
destination_domain, destination_mappings = self.fetch_all_destinations_mappings(
208+
self.varnish.cluster, redirect.destination, self.input.domain_mappings)
209+
for mapped_domain in redirect.src_domain.mapped_domains(self.varnish.cluster):
210+
destination = str(redirect.destination)
211+
if destination_domain == redirect.src_domain.domain:
212+
destination = destination.replace(destination_domain, mapped_domain)
213+
elif all((destination_domain, len(destination_mappings) == 1)):
214+
destination = destination.replace(destination_domain, destination_mappings[0])
215+
if entries := redirects.get(mapped_domain, []):
216+
entries.append(VclRedirect(redirect, mapped_domain, destination))
217+
else:
218+
redirects[mapped_domain] = [VclRedirect(redirect, mapped_domain, destination)]
234219
return redirects
235220

236221
@collect_processing
@@ -410,7 +395,7 @@ def fetch_render_data(self):
410395
Prefetch('clusters', queryset=LogicalCluster.objects.only('pk'), to_attr='cluster_ids'),
411396
))
412397
self.routes.sort(key=lambda route: "{:03d}-{}".format(route.priority, route.director.name))
413-
self.redirects = list(Redirect.objects.all().order_by('src_domain', 'priority'))
398+
self.redirects = self.assemble_redirects()
414399
self.dcs = list(Dc.objects.all())
415400
self.template_blocks = list(VclTemplateBlock.objects.all().prefetch_related('template'))
416401
self.vcl_variables = list(VclVariable.objects.all())
@@ -422,16 +407,15 @@ def fetch_render_data(self):
422407
self.distributed_canary_backends = self.prepare_canary_backends(canary_backend_ids, backends)
423408
self.domain_mappings = DomainMapping.objects.all()
424409
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
410+
411+
@collect_processing
412+
def assemble_redirects(self) -> dict[str, list[Redirect]]:
413+
redirects = {}
414+
for redirect in Redirect.objects.all().order_by('src_domain', 'priority'):
415+
if redirect.src_domain.domain not in redirects.keys():
416+
redirects[redirect.src_domain.domain] = []
417+
redirects[redirect.src_domain.domain].append(redirect)
418+
return redirects
435419

436420
@collect_processing
437421
def distribute_backends(self, backends):

vaas/vaas/vcl/tests/expected-vcl-4.0-canary.vcl

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ sub vcl_synth {
339339
if (resp.status == 989) {
340340
set resp.status = 200;
341341
set resp.http.Content-Type = "application/json";
342-
synthetic ( {"{ "vcl_version" : "0bbef", "varnish_status": "disabled" }"} );
342+
synthetic ( {"{ "vcl_version" : "ce716", "varnish_status": "disabled" }"} );
343343
return (deliver);
344344
}
345345
}
@@ -424,12 +424,6 @@ sub vcl_recv {
424424
set req.http.x-response-code = "301";
425425
set req.http.x-action = "redirect";
426426
}
427-
else if (req.url ~ "/external") {
428-
set req.http.x-redirect = "3";
429-
set req.http.x-destination = "http://example-external.com/external_destination";
430-
set req.http.x-response-code = "301";
431-
set req.http.x-action = "redirect";
432-
}
433427
}
434428
if (req.http.host == "example.prod.org") {
435429
if (req.url ~ "/source") {
@@ -444,12 +438,6 @@ sub vcl_recv {
444438
set req.http.x-response-code = "301";
445439
set req.http.x-action = "redirect";
446440
}
447-
else if (req.url ~ "/external") {
448-
set req.http.x-redirect = "3";
449-
set req.http.x-destination = "http://example-external.com/external_destination";
450-
set req.http.x-response-code = "301";
451-
set req.http.x-action = "redirect";
452-
}
453441
}
454442

455443
# Test ROUTER

vaas/vaas/vcl/tests/expected-vcl-4.0.vcl

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ sub vcl_synth {
366366
if (resp.status == 989) {
367367
set resp.status = 200;
368368
set resp.http.Content-Type = "application/json";
369-
synthetic ( {"{ "vcl_version" : "d584a", "varnish_status": "disabled" }"} );
369+
synthetic ( {"{ "vcl_version" : "721d3", "varnish_status": "disabled" }"} );
370370
return (deliver);
371371
}
372372
}
@@ -451,12 +451,6 @@ sub vcl_recv {
451451
set req.http.x-response-code = "301";
452452
set req.http.x-action = "redirect";
453453
}
454-
else if (req.url ~ "/external") {
455-
set req.http.x-redirect = "3";
456-
set req.http.x-destination = "http://example-external.com/external_destination";
457-
set req.http.x-response-code = "301";
458-
set req.http.x-action = "redirect";
459-
}
460454
}
461455
if (req.http.host == "example.prod.org") {
462456
if (req.url ~ "/source") {
@@ -471,12 +465,6 @@ sub vcl_recv {
471465
set req.http.x-response-code = "301";
472466
set req.http.x-action = "redirect";
473467
}
474-
else if (req.url ~ "/external") {
475-
set req.http.x-redirect = "3";
476-
set req.http.x-destination = "http://example-external.com/external_destination";
477-
set req.http.x-response-code = "301";
478-
set req.http.x-action = "redirect";
479-
}
480468
}
481469

482470
# Test ROUTER

vaas/vaas/vcl/tests/test_renderer.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ def setUp(self):
280280
)
281281

282282
Redirect.objects.create(
283-
src_domain=self.example_domain_mapping,
283+
src_domain=self.external_domain_mapping,
284284
condition='req.url ~ "/external"',
285285
destination='http://external.com/external_destination',
286286
action=301,
@@ -436,23 +436,26 @@ def test_should_decorate_set_backend_tag_with_fallback_service_in_dc1(self):
436436
def test_should_decorate_flexible_router_tag_with_properly_mapped_destination_domain(self):
437437
vcl_tag_builder = VclTagBuilder(self.varnish, VclRendererInput())
438438
tag = vcl_tag_builder.get_expanded_tags('FLEXIBLE_ROUTER').pop()
439-
assert_set_equal({'example.prod.com', 'example.prod.org'}, set(tag.parameters['redirects'].keys()))
439+
assert_set_equal({'example.prod.com', 'example-external.com', 'example.prod.org'},
440+
set(tag.parameters['redirects'].keys()))
440441
assert_equals('example.com', tag.parameters['redirects']['example.prod.com'][1].src_domain.domain)
441442
assert_equals('example.com', tag.parameters['redirects']['example.prod.org'][1].src_domain.domain)
442443
assert_equals('http://example.prod.com/destination',
443444
tag.parameters['redirects']['example.prod.com'][1].destination)
444445
assert_equals('http://example.prod.org/destination',
445446
tag.parameters['redirects']['example.prod.org'][1].destination)
446447
assert_equals('http://example-external.com/external_destination',
447-
tag.parameters['redirects']['example.prod.com'][2].destination)
448+
tag.parameters['redirects']['example-external.com'][0].destination)
448449

449450
def test_should_sort_redirects_by_priority(self):
450451
vcl_tag_builder = VclTagBuilder(self.varnish, VclRendererInput())
451452
tag = vcl_tag_builder.get_expanded_tags('FLEXIBLE_ROUTER').pop()
452-
assert_set_equal({'example.prod.com', 'example.prod.org'}, set(tag.parameters['redirects'].keys()))
453+
assert_set_equal({'example.prod.com', 'example-external.com', 'example.prod.org'},
454+
set(tag.parameters['redirects'].keys()))
453455
assert_equals('2/example.prod.com', tag.parameters['redirects']['example.prod.com'][0].id)
454456
assert_equals('1/example.prod.com', tag.parameters['redirects']['example.prod.com'][1].id)
455-
assert_equals('3/example.prod.com', tag.parameters['redirects']['example.prod.com'][2].id)
457+
assert_equals('2/example.prod.org', tag.parameters['redirects']['example.prod.org'][0].id)
458+
assert_equals('3/example-external.com', tag.parameters['redirects']['example-external.com'][0].id)
456459

457460

458461
class VclRendererInputTest(TestCase):

0 commit comments

Comments
 (0)