Skip to content

Commit

Permalink
send_queued() now raises an exception if batch_delivery_timeout is ex…
Browse files Browse the repository at this point in the history
…ceeded.
  • Loading branch information
selwin committed Oct 22, 2023
1 parent 4afa3d0 commit 3204f3f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
42 changes: 26 additions & 16 deletions post_office/mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,16 +304,22 @@ def send_queued(processes=1, log_level=None):

timeout = get_batch_delivery_timeout()
results = []
try:
# Wait for all tasks to complete with a timeout
# The get method is used with a timeout to wait for each result
for task in tasks:
results.append(task.get(timeout=timeout))
except (TimeoutError, ContextTimeoutError):
logger.exception("Process timed out after %d seconds" % timeout)

# results = pool.map(_send_bulk, email_lists)

# Wait for all tasks to complete with a timeout
# The get method is used with a timeout to wait for each result
for task in tasks:
results.append(task.get(timeout=timeout))
# for task in tasks:
# try:
# # Wait for all tasks to complete with a timeout
# # The get method is used with a timeout to wait for each result
# results.append(task.get(timeout=timeout))
# except (TimeoutError, ContextTimeoutError):
# logger.exception("Process timed out after %d seconds" % timeout)

# results = pool.map(_send_bulk, email_lists)
pool.terminate()
pool.join()

total_sent = sum(result[0] for result in results)
total_failed = sum(result[1] for result in results)
Expand Down Expand Up @@ -377,13 +383,17 @@ def send(email):

timeout = get_batch_delivery_timeout()

try:
# Wait for all tasks to complete with a timeout
# The get method is used with a timeout to wait for each result
for result in results:
result.get(timeout=timeout)
except TimeoutError:
logger.exception("Process timed out after %d seconds" % timeout)
# Wait for all tasks to complete with a timeout
# The get method is used with a timeout to wait for each result
for result in results:
result.get(timeout=timeout)
# for result in results:
# try:
# # Wait for all tasks to complete with a timeout
# # The get method is used with a timeout to wait for each result
# result.get(timeout=timeout)
# except TimeoutError:
# logger.exception("Process timed out after %d seconds" % timeout)

pool.close()
pool.join()
Expand Down
1 change: 1 addition & 0 deletions post_office/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def get_message_id_fqdn():
return get_config().get('MESSAGE_ID_FQDN', DNS_NAME)


# BATCH_DELIVERY_TIMEOUT defaults to 180 seconds (3 minutes)
def get_batch_delivery_timeout():
return get_config().get('BATCH_DELIVERY_TIMEOUT', 180)

Expand Down
12 changes: 9 additions & 3 deletions post_office/tests/test_mail.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SlowTestBackend(mail.backends.base.BaseEmailBackend):
'''

def send_messages(self, email_messages):
time.sleep(10)
time.sleep(5)


class MailTest(TestCase):
Expand Down Expand Up @@ -496,8 +496,14 @@ def test_batch_delivery_timeout(self):
email = Email.objects.create(to=['[email protected]'],
from_email='[email protected]', subject='',
message='', status=STATUS.queued, backend_alias='slow_backend')
send_queued()

start_time = timezone.now()
# slow backend sleeps for 5 seconds, so we should get a timeout error since we set
# BATCH_DELIVERY_TIMEOUT timeout to 2 seconds in test_settings.py
with self.assertRaises(TimeoutError):
send_queued()
end_time = timezone.now()
# Assert that running time is less than 3 seconds (2 seconds timeout + 1 second buffer)
self.assertTrue(end_time - start_time < timezone.timedelta(seconds=3))

@patch('post_office.signals.email_queued.send')
def test_backend_signal(self, mock):
Expand Down

0 comments on commit 3204f3f

Please sign in to comment.