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
|
||||
|
||||
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 )
|
||||
from ietf.doc.models import Document
|
||||
|
||||
if not in_draft_expire_freeze():
|
||||
syslog.syslog("Expiring drafts ...")
|
||||
for doc in get_expired_drafts():
|
||||
# verify expirability -- it might have changed after get_expired_drafts() was run
|
||||
# (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)
|
||||
expire_draft(doc)
|
||||
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
|
||||
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.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
|
||||
|
||||
|
||||
def expirable_draft(draft):
|
||||
"""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]
|
||||
nonexpirable_states: Optional[List[State]] = None
|
||||
|
||||
def expirable_drafts(queryset=None):
|
||||
"""Return a queryset with expirable drafts."""
|
||||
|
@ -39,31 +31,25 @@ def expirable_drafts(queryset=None):
|
|||
queryset = Document.objects.all()
|
||||
|
||||
# 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
|
||||
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
|
||||
# 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")))
|
||||
# other IRTF states that block expiration
|
||||
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")
|
||||
if not d.exists():
|
||||
return d
|
||||
return queryset.filter(
|
||||
states__type="draft", states__slug="active"
|
||||
).exclude(
|
||||
expires=None
|
||||
).exclude(
|
||||
states__in=nonexpirable_states
|
||||
).exclude(
|
||||
tags="rfc-rev" # under review by the RFC Editor blocks expiry
|
||||
).distinct()
|
||||
|
||||
d = d.exclude(expires=None)
|
||||
if not d.exists():
|
||||
return d
|
||||
|
||||
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):
|
||||
start_date = datetime.date.today() - datetime.timedelta(1)
|
||||
|
|
|
@ -6,7 +6,7 @@ import datetime
|
|||
import debug # pyflakes:ignore
|
||||
|
||||
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.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)
|
||||
|
||||
# misc
|
||||
expirable_pks = expirable_drafts(Document.objects.filter(pk__in=doc_ids)).values_list('pk', flat=True)
|
||||
for d in docs:
|
||||
# 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)
|
||||
|
@ -102,7 +103,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False):
|
|||
else:
|
||||
d.search_heading = "%s Internet-Draft" % d.get_state()
|
||||
if state_slug == "active":
|
||||
d.expirable = expirable_draft(d)
|
||||
d.expirable = d.pk in expirable_pks
|
||||
else:
|
||||
d.expirable = False
|
||||
else:
|
||||
|
|
Loading…
Reference in a new issue