feat: expire submissions after 14 days (#7461)

* feat: expire submissions after 14 days

* test: update test_cancel_stale_submissions
This commit is contained in:
Jennifer Richards 2024-05-24 11:30:01 -03:00 committed by GitHub
parent a1a30974ea
commit 1a2996e5f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 59 additions and 10 deletions

View file

@ -817,6 +817,9 @@ IDSUBMIT_CHECKER_CLASSES = (
# Max time to allow for validation before a submission is subject to cancellation
IDSUBMIT_MAX_VALIDATION_TIME = datetime.timedelta(minutes=20)
# Age at which a submission expires if not posted
IDSUBMIT_EXPIRATION_AGE = datetime.timedelta(days=14)
IDSUBMIT_MANUAL_STAGING_DIR = '/tmp/'
IDSUBMIT_FILE_TYPES = (

View file

@ -37,19 +37,34 @@ def process_and_accept_uploaded_submission_task(submission_id):
@shared_task
def cancel_stale_submissions():
now = timezone.now()
stale_submissions = Submission.objects.filter(
# first check for submissions gone stale awaiting validation
stale_unvalidated_submissions = Submission.objects.filter(
state_id='validating',
).annotate(
submitted_at=Min('submissionevent__time'),
).filter(
submitted_at__lt=now - settings.IDSUBMIT_MAX_VALIDATION_TIME,
)
for subm in stale_submissions:
for subm in stale_unvalidated_submissions:
age = now - subm.submitted_at
log.log(f'Canceling stale submission (id={subm.id}, age={age})')
cancel_submission(subm)
create_submission_event(None, subm, 'Submission canceled: validation checks took too long')
# now check for expired submissions
expired_submissions = Submission.objects.exclude(
state_id__in=["posted", "cancel"],
).annotate(
submitted_at=Min("submissionevent__time"),
).filter(
submitted_at__lt=now - settings.IDSUBMIT_EXPIRATION_AGE,
)
for subm in expired_submissions:
age = now - subm.submitted_at
log.log(f'Canceling expired submission (id={subm.id}, age={age})')
cancel_submission(subm)
create_submission_event(None, subm, 'Submission canceled: expired without being posted')
@shared_task(bind=True)
def poke(self):

View file

@ -42,7 +42,7 @@ from ietf.group.models import Group
from ietf.group.utils import setup_default_community_list_for_group
from ietf.meeting.models import Meeting
from ietf.meeting.factories import MeetingFactory
from ietf.name.models import FormalLanguageName
from ietf.name.models import DraftSubmissionStateName, FormalLanguageName
from ietf.person.models import Person
from ietf.person.factories import UserFactory, PersonFactory, EmailFactory
from ietf.submit.factories import SubmissionFactory, SubmissionExtResourceFactory
@ -3136,28 +3136,59 @@ class AsyncSubmissionTests(BaseSubmitTestCase):
self.assertContains(r, s.name)
self.assertContains(r, 'This submission is being processed and validated.', status_code=200)
@override_settings(IDSUBMIT_MAX_VALIDATION_TIME=datetime.timedelta(minutes=30))
@override_settings(
IDSUBMIT_MAX_VALIDATION_TIME=datetime.timedelta(minutes=30),
IDSUBMIT_EXPIRATION_AGE=datetime.timedelta(minutes=90),
)
def test_cancel_stale_submissions(self):
# these will be lists of (Submission, "state_id") pairs
submissions_to_skip = []
submissions_to_cancel = []
# submissions in the validating state
fresh_submission = SubmissionFactory(state_id='validating')
fresh_submission.submissionevent_set.create(
desc='fake created event',
time=timezone.now() - datetime.timedelta(minutes=15),
)
submissions_to_skip.append((fresh_submission, "validating"))
stale_submission = SubmissionFactory(state_id='validating')
stale_submission.submissionevent_set.create(
desc='fake created event',
time=timezone.now() - datetime.timedelta(minutes=30, seconds=1),
)
submissions_to_cancel.append((stale_submission, "validating"))
# submissions in other states
for state in DraftSubmissionStateName.objects.filter(used=True).exclude(slug="validating"):
to_skip = SubmissionFactory(state_id=state.pk)
to_skip.submissionevent_set.create(
desc="fake created event",
time=timezone.now() - datetime.timedelta(minutes=45), # would be canceled if it were "validating"
)
submissions_to_skip.append((to_skip, state.pk))
to_expire = SubmissionFactory(state_id=state.pk)
to_expire.submissionevent_set.create(
desc="fake created event",
time=timezone.now() - datetime.timedelta(minutes=90, seconds=1),
)
if state.pk in ["posted", "cancel"]:
submissions_to_skip.append((to_expire, state.pk)) # these ones should not be expired regardless of age
else:
submissions_to_cancel.append(((to_expire, state.pk)))
cancel_stale_submissions()
fresh_submission = Submission.objects.get(pk=fresh_submission.pk)
self.assertEqual(fresh_submission.state_id, 'validating')
self.assertEqual(fresh_submission.submissionevent_set.count(), 1)
for _subm, original_state_id in submissions_to_skip:
subm = Submission.objects.get(pk=_subm.pk)
self.assertEqual(subm.state_id, original_state_id)
self.assertEqual(subm.submissionevent_set.count(), 1)
stale_submission = Submission.objects.get(pk=stale_submission.pk)
self.assertEqual(stale_submission.state_id, 'cancel')
self.assertEqual(stale_submission.submissionevent_set.count(), 2)
for _subm, _ in submissions_to_cancel:
subm = Submission.objects.get(pk=_subm.pk)
self.assertEqual(subm.state_id, "cancel")
self.assertEqual(subm.submissionevent_set.count(), 2)
class ApiSubmitTests(BaseSubmitTestCase):