Skip to content

Commit 47dad07

Browse files
refactor: Avoid module-level queries (ietf-tools#6916)
* refactor: Avoid module-level queries * refactor: Avoid repeated State queries
1 parent eae048d commit 47dad07

1 file changed

Lines changed: 66 additions & 45 deletions

File tree

ietf/doc/views_search.py

Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
import copy
4040
import operator
4141

42+
from collections import defaultdict
4243
from functools import reduce
44+
4345
from django import forms
4446
from django.conf import settings
4547
from django.core.cache import cache, caches
@@ -360,32 +362,52 @@ def cached_redirect(cache_key, url):
360362
return cached_redirect(cache_key, urlreverse('ietf.doc.views_search.search') + search_args)
361363

362364

363-
def state_name(doc_type, state, shorten=True):
364-
name = ""
365-
# Note doc_type rfc here is _not_ necessarily Document.type - for some callers
366-
# it is a type derived from draft... The ad_workload view needs more rework so that
367-
# the code isn't having to shadow-box so much.
368-
if doc_type == "rfc":
369-
if state == "rfc":
370-
name = "RFC"
371-
if name == "":
372-
s = State.objects.filter(type="rfc",slug=state).first()
373-
if s:
374-
name = s.name
375-
if name == "":
376-
name = State.objects.get(type__in=["draft", "draft-iesg"], slug=state).name
377-
elif doc_type == "draft" and state not in ["rfc", "expired"]:
378-
name = State.objects.get(type__in=["draft", "draft-iesg"], slug=state).name
379-
elif doc_type == "draft" and state == "rfc":
380-
name = "RFC"
381-
elif doc_type == "conflrev" and state.startswith("appr"):
382-
name = "Approved"
383-
else:
384-
name = State.objects.get(type=doc_type, slug=state).name
365+
def get_state_name_calculator():
366+
"""Get a function to calculate state names
367+
368+
Queries the database once when called, then uses cached look-up table for name calculations.
369+
"""
370+
# state_lut always has at least rfc, draft, and draft-iesg keys
371+
state_lut = defaultdict(dict, **{"rfc": {}, "draft":{}, "draft-iesg": {}})
372+
for state in State.objects.filter(used=True):
373+
state_lut[state.type_id][state.slug] = state.name
374+
state_lut = dict(state_lut) # convert to dict to freeze key changes
375+
376+
def _get_state_name(doc_type, state_slug):
377+
"""Get display name for a doc type / state slug
378+
379+
Note doc_type rfc here is _not_ necessarily Document.type - for some callers
380+
it is a type derived from draft... The ad_workload view needs more rework so that
381+
the code isn't having to shadow-box so much.
382+
"""
383+
if doc_type == "rfc":
384+
if state_slug == "rfc":
385+
return "RFC"
386+
elif state_slug in state_lut["rfc"]:
387+
return state_lut["rfc"][state_slug]
388+
else:
389+
return state_lut["draft"].get(
390+
state_slug,
391+
state_lut["draft-iesg"][state_slug],
392+
)
393+
elif doc_type == "draft" and state_slug not in ["rfc", "expired"]:
394+
return state_lut["draft"].get(
395+
state_slug,
396+
state_lut["draft-iesg"][state_slug],
397+
)
398+
elif doc_type == "draft" and state_slug == "rfc":
399+
return "RFC"
400+
elif doc_type == "conflrev" and state_slug.startswith("appr"):
401+
return "Approved"
402+
else:
403+
return state_lut[doc_type][state_slug]
404+
405+
# return the function as a closure
406+
return _get_state_name
385407

386-
if not shorten:
387-
return name
388408

409+
def shorten_state_name(name):
410+
"""Get abbreviated display name for a state"""
389411
for pat, sub in [
390412
(r" \(Internal Steering Group/IAB Review\)", ""),
391413
("Writeup", "Write-up"),
@@ -412,31 +434,27 @@ def state_name(doc_type, state, shorten=True):
412434
(r"\(Message to Community, Selected by Secretariat\)", ""),
413435
]:
414436
name = re.sub(pat, sub, name)
415-
416437
return name.strip()
417438

418439

419-
STATE_SLUGS = {
420-
dt: {state_name(dt, ds, shorten=False): ds for ds in AD_WORKLOAD[dt]} # type: ignore
421-
for dt in AD_WORKLOAD
422-
}
423-
424-
425-
def state_to_doc_type(state):
426-
for dt in STATE_SLUGS:
427-
if state in STATE_SLUGS[dt]:
428-
return dt
429-
return None
430-
431-
432-
IESG_STATES = State.objects.filter(type="draft-iesg").values_list("name", flat=True)
433-
434-
435440
def date_to_bucket(date, now, num_buckets):
436441
return num_buckets - int((now.date() - date.date()).total_seconds() / 60 / 60 / 24)
437442

438443

439444
def ad_workload(request):
445+
_calculate_state_name = get_state_name_calculator()
446+
IESG_STATES = State.objects.filter(type="draft-iesg").values_list("name", flat=True)
447+
STATE_SLUGS = {
448+
dt: {_calculate_state_name(dt, ds): ds for ds in AD_WORKLOAD[dt]} # type: ignore
449+
for dt in AD_WORKLOAD.keys()
450+
}
451+
452+
def _state_to_doc_type(state):
453+
for dt in STATE_SLUGS:
454+
if state in STATE_SLUGS[dt]:
455+
return dt
456+
return None
457+
440458
# number of days (= buckets) to show in the graphs
441459
days = 120 if has_role(request.user, ["Area Director", "Secretariat"]) else 1
442460
now = timezone.now()
@@ -483,7 +501,7 @@ def ad_workload(request):
483501
to_state = None
484502
if dt == "charter":
485503
if e.type == "closed_ballot":
486-
to_state = state_name(dt, state, shorten=False)
504+
to_state = _calculate_state_name(dt, state)
487505
elif e.desc.endswith("has been replaced"):
488506
# stop tracking
489507
last = e.time
@@ -512,7 +530,7 @@ def ad_workload(request):
512530
to_state = "RFC"
513531

514532
if dt == "rfc":
515-
new_dt = state_to_doc_type(to_state)
533+
new_dt = _state_to_doc_type(to_state)
516534
if new_dt is not None and new_dt != dt:
517535
dt = new_dt
518536

@@ -549,7 +567,9 @@ def ad_workload(request):
549567
metadata = [
550568
{
551569
"type": (dt, doc_type_name(dt)),
552-
"states": [(state, state_name(dt, state)) for state in ad.buckets[dt]],
570+
"states": [
571+
(state, shorten_state_name(_calculate_state_name(dt, state))) for state in ad.buckets[dt]
572+
],
553573
"ads": ads,
554574
}
555575
for dt in AD_WORKLOAD
@@ -617,9 +637,10 @@ def sort_key(doc):
617637
)
618638
]
619639

640+
_calculate_state_name = get_state_name_calculator()
620641
for d in results:
621642
dt = d.type.slug
622-
d.search_heading = state_name(dt, doc_state(d), shorten=False)
643+
d.search_heading = _calculate_state_name(dt, doc_state(d))
623644
if d.search_heading != "RFC":
624645
d.search_heading += f" {doc_type_name(dt)}"
625646

0 commit comments

Comments
 (0)