Skip to content

Commit e2b2709

Browse files
authored
ocf_www: speed up build-vhosts with bulk LDAP query and parallelism (#1464)
1 parent c52abc4 commit e2b2709

1 file changed

Lines changed: 34 additions & 3 deletions

File tree

modules/ocf_www/files/build-vhosts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import subprocess
88
import sys
99
import tempfile
1010
from collections import namedtuple
11+
from concurrent.futures import ThreadPoolExecutor
1112
from itertools import chain
1213
from pathlib import Path
1314
from socket import getfqdn
1415

1516
import jinja2
17+
from ocflib.account.search import SORRIED_SHELL
1618
from ocflib.account.search import user_is_sorried
1719
from ocflib.account.utils import web_dir
20+
from ocflib.infra.ldap import ldap_ocf
1821
from ocflib.misc.mail import email_for_user
1922
from ocflib.vhost.application import get_app_vhosts
2023
from ocflib.vhost.web import get_vhosts
@@ -99,7 +102,7 @@ class VirtualHost(namedtuple('VirtualHost', (
99102
"""
100103
@property
101104
def contact_email(self):
102-
return email_for_user(self.user)
105+
return email_for_user(self.user, check_exists=False)
103106

104107
@property
105108
def is_redirect(self):
@@ -130,6 +133,8 @@ class VirtualHost(namedtuple('VirtualHost', (
130133

131134
@property
132135
def disabled(self):
136+
if _sorried_users is not None:
137+
return self.user in _sorried_users
133138
return user_is_sorried(self.user)
134139

135140
@property
@@ -175,6 +180,25 @@ def report(*args, **kwargs):
175180
kwargs['file'].flush()
176181

177182

183+
def _prefetch_vhost_lookups():
184+
"""Pre-fetch LDAP data used during template rendering.
185+
186+
VirtualHost.disabled makes a per-vhost LDAP query to check if the user is
187+
sorried. This fetches all sorried users in a single bulk query instead.
188+
"""
189+
global _sorried_users
190+
with ldap_ocf() as c:
191+
c.search(
192+
'ou=People,dc=OCF,dc=Berkeley,dc=EDU',
193+
f'(loginShell={SORRIED_SHELL})',
194+
attributes=['uid'],
195+
)
196+
_sorried_users = {entry['uid'].value for entry in c.entries}
197+
198+
199+
_sorried_users = None
200+
201+
178202
def build_config(src_vhosts, template, dev_config=False):
179203
vhosts = list()
180204

@@ -405,17 +429,24 @@ def main():
405429
changed |= process_app_vhosts()
406430

407431
if args.target == 'web':
432+
# Fetch app vhosts, web vhosts, and sorried users in parallel
433+
# to avoid sequential LDAP round-trips (~5s total vs 30s+)
434+
with ThreadPoolExecutor(max_workers=3) as pool:
435+
app_future = pool.submit(get_app_vhosts)
436+
web_future = pool.submit(get_vhosts)
437+
pool.submit(_prefetch_vhost_lookups)
438+
408439
# Build app vhosts so that they can get proxied to apphost.o.b.e
409440
# Placed before regular vhosts so they take priority in domain matching
410441
# (sometimes hosts have entries in both vhost.conf and vhost-app.conf)
411442
# Filter out dev app vhosts so they don't clobber existing vhost entries
412443
prod_app_vhosts = {
413444
domain: conf
414-
for domain, conf in get_app_vhosts().items()
445+
for domain, conf in app_future.result().items()
415446
if 'dev' not in conf['flags']
416447
}
417448

418-
web_vhosts = get_vhosts()
449+
web_vhosts = web_future.result()
419450

420451
# Exclude web vhosts that overlap with app vhosts (app vhosts
421452
# take priority and are proxied directly to apphost by nginx)

0 commit comments

Comments
 (0)