Skip to content

Commit

Permalink
refactor: Avoid module-level queries (#6916)
Browse files Browse the repository at this point in the history
* refactor: Avoid module-level queries

* refactor: Avoid repeated State queries
  • Loading branch information
jennifer-richards authored Jan 16, 2024
1 parent eae048d commit 47dad07
Showing 1 changed file with 66 additions and 45 deletions.
111 changes: 66 additions & 45 deletions ietf/doc/views_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@
import copy
import operator

from collections import defaultdict
from functools import reduce

from django import forms
from django.conf import settings
from django.core.cache import cache, caches
Expand Down Expand Up @@ -360,32 +362,52 @@ def cached_redirect(cache_key, url):
return cached_redirect(cache_key, urlreverse('ietf.doc.views_search.search') + search_args)


def state_name(doc_type, state, shorten=True):
name = ""
# Note doc_type rfc here is _not_ necessarily Document.type - for some callers
# it is a type derived from draft... The ad_workload view needs more rework so that
# the code isn't having to shadow-box so much.
if doc_type == "rfc":
if state == "rfc":
name = "RFC"
if name == "":
s = State.objects.filter(type="rfc",slug=state).first()
if s:
name = s.name
if name == "":
name = State.objects.get(type__in=["draft", "draft-iesg"], slug=state).name
elif doc_type == "draft" and state not in ["rfc", "expired"]:
name = State.objects.get(type__in=["draft", "draft-iesg"], slug=state).name
elif doc_type == "draft" and state == "rfc":
name = "RFC"
elif doc_type == "conflrev" and state.startswith("appr"):
name = "Approved"
else:
name = State.objects.get(type=doc_type, slug=state).name
def get_state_name_calculator():
"""Get a function to calculate state names
Queries the database once when called, then uses cached look-up table for name calculations.
"""
# state_lut always has at least rfc, draft, and draft-iesg keys
state_lut = defaultdict(dict, **{"rfc": {}, "draft":{}, "draft-iesg": {}})
for state in State.objects.filter(used=True):
state_lut[state.type_id][state.slug] = state.name
state_lut = dict(state_lut) # convert to dict to freeze key changes

def _get_state_name(doc_type, state_slug):
"""Get display name for a doc type / state slug
Note doc_type rfc here is _not_ necessarily Document.type - for some callers
it is a type derived from draft... The ad_workload view needs more rework so that
the code isn't having to shadow-box so much.
"""
if doc_type == "rfc":
if state_slug == "rfc":
return "RFC"
elif state_slug in state_lut["rfc"]:
return state_lut["rfc"][state_slug]
else:
return state_lut["draft"].get(
state_slug,
state_lut["draft-iesg"][state_slug],
)
elif doc_type == "draft" and state_slug not in ["rfc", "expired"]:
return state_lut["draft"].get(
state_slug,
state_lut["draft-iesg"][state_slug],
)
elif doc_type == "draft" and state_slug == "rfc":
return "RFC"
elif doc_type == "conflrev" and state_slug.startswith("appr"):
return "Approved"
else:
return state_lut[doc_type][state_slug]

# return the function as a closure
return _get_state_name

if not shorten:
return name

def shorten_state_name(name):
"""Get abbreviated display name for a state"""
for pat, sub in [
(r" \(Internal Steering Group/IAB Review\)", ""),
("Writeup", "Write-up"),
Expand All @@ -412,31 +434,27 @@ def state_name(doc_type, state, shorten=True):
(r"\(Message to Community, Selected by Secretariat\)", ""),
]:
name = re.sub(pat, sub, name)

return name.strip()


STATE_SLUGS = {
dt: {state_name(dt, ds, shorten=False): ds for ds in AD_WORKLOAD[dt]} # type: ignore
for dt in AD_WORKLOAD
}


def state_to_doc_type(state):
for dt in STATE_SLUGS:
if state in STATE_SLUGS[dt]:
return dt
return None


IESG_STATES = State.objects.filter(type="draft-iesg").values_list("name", flat=True)


def date_to_bucket(date, now, num_buckets):
return num_buckets - int((now.date() - date.date()).total_seconds() / 60 / 60 / 24)


def ad_workload(request):
_calculate_state_name = get_state_name_calculator()
IESG_STATES = State.objects.filter(type="draft-iesg").values_list("name", flat=True)
STATE_SLUGS = {
dt: {_calculate_state_name(dt, ds): ds for ds in AD_WORKLOAD[dt]} # type: ignore
for dt in AD_WORKLOAD.keys()
}

def _state_to_doc_type(state):
for dt in STATE_SLUGS:
if state in STATE_SLUGS[dt]:
return dt
return None

# number of days (= buckets) to show in the graphs
days = 120 if has_role(request.user, ["Area Director", "Secretariat"]) else 1
now = timezone.now()
Expand Down Expand Up @@ -483,7 +501,7 @@ def ad_workload(request):
to_state = None
if dt == "charter":
if e.type == "closed_ballot":
to_state = state_name(dt, state, shorten=False)
to_state = _calculate_state_name(dt, state)
elif e.desc.endswith("has been replaced"):
# stop tracking
last = e.time
Expand Down Expand Up @@ -512,7 +530,7 @@ def ad_workload(request):
to_state = "RFC"

if dt == "rfc":
new_dt = state_to_doc_type(to_state)
new_dt = _state_to_doc_type(to_state)
if new_dt is not None and new_dt != dt:
dt = new_dt

Expand Down Expand Up @@ -549,7 +567,9 @@ def ad_workload(request):
metadata = [
{
"type": (dt, doc_type_name(dt)),
"states": [(state, state_name(dt, state)) for state in ad.buckets[dt]],
"states": [
(state, shorten_state_name(_calculate_state_name(dt, state))) for state in ad.buckets[dt]
],
"ads": ads,
}
for dt in AD_WORKLOAD
Expand Down Expand Up @@ -617,9 +637,10 @@ def sort_key(doc):
)
]

_calculate_state_name = get_state_name_calculator()
for d in results:
dt = d.type.slug
d.search_heading = state_name(dt, doc_state(d), shorten=False)
d.search_heading = _calculate_state_name(dt, doc_state(d))
if d.search_heading != "RFC":
d.search_heading += f" {doc_type_name(dt)}"

Expand Down

0 comments on commit 47dad07

Please sign in to comment.