Refactor expirable_drafts() and its usage to speed up doc.views_search.recent_drafts view (and discourage inefficient use of the method). Commit ready for merge.
- Legacy-Id: 19490
This commit is contained in:
parent
3386e59a61
commit
0d955b6328
|
@ -27,15 +27,22 @@ django.setup()
|
||||||
from ietf.utils.log import logger
|
from ietf.utils.log import logger
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ietf.doc.expire import ( in_draft_expire_freeze, get_expired_drafts, expirable_draft,
|
from ietf.doc.expire import ( in_draft_expire_freeze, get_expired_drafts, expirable_drafts,
|
||||||
send_expire_notice_for_draft, expire_draft, clean_up_draft_files )
|
send_expire_notice_for_draft, expire_draft, clean_up_draft_files )
|
||||||
|
from ietf.doc.models import Document
|
||||||
|
|
||||||
if not in_draft_expire_freeze():
|
if not in_draft_expire_freeze():
|
||||||
syslog.syslog("Expiring drafts ...")
|
syslog.syslog("Expiring drafts ...")
|
||||||
for doc in get_expired_drafts():
|
for doc in get_expired_drafts():
|
||||||
# verify expirability -- it might have changed after get_expired_drafts() was run
|
# verify expirability -- it might have changed after get_expired_drafts() was run
|
||||||
# (this whole loop took about 2 minutes on 04 Jan 2018)
|
# (this whole loop took about 2 minutes on 04 Jan 2018)
|
||||||
if expirable_draft(doc) and doc.expires < datetime.datetime.today() + datetime.timedelta(1):
|
# N.B., re-running expirable_drafts() repeatedly is fairly expensive. Where possible,
|
||||||
|
# it's much faster to run it once on a superset query of the objects you are going
|
||||||
|
# to test and keep its results. That's not desirable here because it would defeat
|
||||||
|
# the purpose of double-checking that a document is still expirable when it is actually
|
||||||
|
# being marked as expired.
|
||||||
|
if (expirable_drafts(Document.objects.filter(pk=doc.pk)).exists()
|
||||||
|
and doc.expires < datetime.datetime.today() + datetime.timedelta(1)):
|
||||||
send_expire_notice_for_draft(doc)
|
send_expire_notice_for_draft(doc)
|
||||||
expire_draft(doc)
|
expire_draft(doc)
|
||||||
syslog.syslog(" Expired draft %s-%s" % (doc.name, doc.rev))
|
syslog.syslog(" Expired draft %s-%s" % (doc.name, doc.rev))
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.conf import settings
|
||||||
import datetime, os, shutil, glob, re
|
import datetime, os, shutil, glob, re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from typing import List, Tuple # pyflakes:ignore
|
from typing import List, Optional # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.utils import log
|
from ietf.utils import log
|
||||||
from ietf.utils.mail import send_mail
|
from ietf.utils.mail import send_mail
|
||||||
|
@ -19,15 +19,7 @@ from ietf.doc.utils import add_state_change_event, update_action_holders
|
||||||
from ietf.mailtrigger.utils import gather_address_lists
|
from ietf.mailtrigger.utils import gather_address_lists
|
||||||
|
|
||||||
|
|
||||||
def expirable_draft(draft):
|
nonexpirable_states: Optional[List[State]] = None
|
||||||
"""Return whether draft is in an expirable state or not. This is
|
|
||||||
the single draft version of the logic in expirable_drafts. These
|
|
||||||
two functions need to be kept in sync."""
|
|
||||||
if draft.type_id != 'draft':
|
|
||||||
return False
|
|
||||||
return bool(expirable_drafts(Document.objects.filter(pk=draft.pk)))
|
|
||||||
|
|
||||||
nonexpirable_states = [] # type: List[State]
|
|
||||||
|
|
||||||
def expirable_drafts(queryset=None):
|
def expirable_drafts(queryset=None):
|
||||||
"""Return a queryset with expirable drafts."""
|
"""Return a queryset with expirable drafts."""
|
||||||
|
@ -39,31 +31,25 @@ def expirable_drafts(queryset=None):
|
||||||
queryset = Document.objects.all()
|
queryset = Document.objects.all()
|
||||||
|
|
||||||
# Populate this first time through (but after django has been set up)
|
# Populate this first time through (but after django has been set up)
|
||||||
if nonexpirable_states == []:
|
if nonexpirable_states is None:
|
||||||
# all IESG states except I-D Exists, AD Watching, and Dead block expiry
|
# all IESG states except I-D Exists, AD Watching, and Dead block expiry
|
||||||
nonexpirable_states += list(State.objects.filter(used=True, type="draft-iesg").exclude(slug__in=("idexists","watching", "dead")))
|
nonexpirable_states = list(State.objects.filter(used=True, type="draft-iesg").exclude(slug__in=("idexists","watching", "dead")))
|
||||||
# sent to RFC Editor and RFC Published block expiry (the latter
|
# sent to RFC Editor and RFC Published block expiry (the latter
|
||||||
# shouldn't be possible for an active draft, though)
|
# shouldn't be possible for an active draft, though)
|
||||||
nonexpirable_states += list(State.objects.filter(used=True, type__in=("draft-stream-iab", "draft-stream-irtf", "draft-stream-ise"), slug__in=("rfc-edit", "pub")))
|
nonexpirable_states += list(State.objects.filter(used=True, type__in=("draft-stream-iab", "draft-stream-irtf", "draft-stream-ise"), slug__in=("rfc-edit", "pub")))
|
||||||
# other IRTF states that block expiration
|
# other IRTF states that block expiration
|
||||||
nonexpirable_states += list(State.objects.filter(used=True, type_id="draft-stream-irtf", slug__in=("irsgpoll", "iesg-rev",)))
|
nonexpirable_states += list(State.objects.filter(used=True, type_id="draft-stream-irtf", slug__in=("irsgpoll", "iesg-rev",)))
|
||||||
|
|
||||||
d = queryset.filter(states__type="draft", states__slug="active")
|
return queryset.filter(
|
||||||
if not d.exists():
|
states__type="draft", states__slug="active"
|
||||||
return d
|
).exclude(
|
||||||
|
expires=None
|
||||||
d = d.exclude(expires=None)
|
).exclude(
|
||||||
if not d.exists():
|
states__in=nonexpirable_states
|
||||||
return d
|
).exclude(
|
||||||
|
tags="rfc-rev" # under review by the RFC Editor blocks expiry
|
||||||
|
).distinct()
|
||||||
|
|
||||||
d = d.exclude(states__in=nonexpirable_states)
|
|
||||||
if not d.exists():
|
|
||||||
return d
|
|
||||||
|
|
||||||
# under review by the RFC Editor blocks expiry
|
|
||||||
d = d.exclude(tags="rfc-rev")
|
|
||||||
|
|
||||||
return d.distinct()
|
|
||||||
|
|
||||||
def get_soon_to_expire_drafts(days_of_warning):
|
def get_soon_to_expire_drafts(days_of_warning):
|
||||||
start_date = datetime.date.today() - datetime.timedelta(1)
|
start_date = datetime.date.today() - datetime.timedelta(1)
|
||||||
|
|
|
@ -6,7 +6,7 @@ import datetime
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from ietf.doc.models import Document, DocAlias, RelatedDocument, DocEvent, TelechatDocEvent, BallotDocEvent
|
from ietf.doc.models import Document, DocAlias, RelatedDocument, DocEvent, TelechatDocEvent, BallotDocEvent
|
||||||
from ietf.doc.expire import expirable_draft
|
from ietf.doc.expire import expirable_drafts
|
||||||
from ietf.doc.utils import augment_docs_and_user_with_user_info
|
from ietf.doc.utils import augment_docs_and_user_with_user_info
|
||||||
from ietf.meeting.models import SessionPresentation, Meeting, Session
|
from ietf.meeting.models import SessionPresentation, Meeting, Session
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
|
||||||
fill_in_document_sessions(docs, doc_dict, doc_ids)
|
fill_in_document_sessions(docs, doc_dict, doc_ids)
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
expirable_pks = expirable_drafts(Document.objects.filter(pk__in=doc_ids)).values_list('pk', flat=True)
|
||||||
for d in docs:
|
for d in docs:
|
||||||
# emulate canonical name which is used by a lot of the utils
|
# emulate canonical name which is used by a lot of the utils
|
||||||
d.canonical_name = wrap_value(rfc_aliases[d.pk] if d.pk in rfc_aliases else d.name)
|
d.canonical_name = wrap_value(rfc_aliases[d.pk] if d.pk in rfc_aliases else d.name)
|
||||||
|
@ -102,7 +103,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
|
||||||
else:
|
else:
|
||||||
d.search_heading = "%s Internet-Draft" % d.get_state()
|
d.search_heading = "%s Internet-Draft" % d.get_state()
|
||||||
if state_slug == "active":
|
if state_slug == "active":
|
||||||
d.expirable = expirable_draft(d)
|
d.expirable = d.pk in expirable_pks
|
||||||
else:
|
else:
|
||||||
d.expirable = False
|
d.expirable = False
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in a new issue