Commit 3e06d681 by Awais Jibran Committed by GitHub

Merge pull request #16025 from edx/aj/handle-rate-limit-s3

BOTO:S3 handle rate limit exceed and do not expose 500 errors
parents c25925c0 79915b37
......@@ -12,6 +12,7 @@ import tempfile
import ddt
import pytz
from boto.exception import BotoServerError
from django.conf import settings
from django.contrib.auth.models import User
from django.core import mail
......@@ -3020,6 +3021,27 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
body.endswith('"{user_id}","41","42"\n'.format(user_id=self.students[-1].id))
)
@patch('lms.djangoapps.instructor_task.models.logger.error')
@patch.dict(settings.GRADES_DOWNLOAD, {'STORAGE_TYPE': 's3'})
def test_list_report_downloads_error(self, mock_error):
"""
Tests the Rate-Limit exceeded is handled and does not raise 500 error.
"""
ex_status = 503
ex_reason = 'Slow Down'
url = reverse('list_report_downloads', kwargs={'course_id': self.course.id.to_deprecated_string()})
with patch('openedx.core.storage.S3ReportStorage.listdir', side_effect=BotoServerError(ex_status, ex_reason)):
response = self.client.post(url, {})
mock_error.assert_called_with(
u'Fetching files failed for course: %s, status: %s, reason: %s',
self.course.id,
ex_status,
ex_reason,
)
res_json = json.loads(response.content)
self.assertEqual(res_json, {"downloads": []})
def test_list_report_downloads(self):
url = reverse('list_report_downloads', kwargs={'course_id': self.course.id.to_deprecated_string()})
with patch('lms.djangoapps.instructor_task.models.DjangoStorageReportStore.links_for') as mock_links_for:
......
......@@ -15,9 +15,11 @@ ASSUMPTIONS: modules have unique IDs, even across different module_types
import csv
import hashlib
import json
import logging
import os.path
from uuid import uuid4
from boto.exception import BotoServerError
from django.conf import settings
from django.contrib.auth.models import User
from django.core.files.base import ContentFile
......@@ -26,6 +28,8 @@ from django.db import models, transaction
from openedx.core.djangoapps.xmodule_django.models import CourseKeyField
from openedx.core.storage import get_storage
logger = logging.getLogger(__name__)
# define custom states used by InstructorTask
QUEUING = 'QUEUING'
PROGRESS = 'PROGRESS'
......@@ -283,6 +287,14 @@ class DjangoStorageReportStore(ReportStore):
# Django's FileSystemStorage fails with an OSError if the course
# dir does not exist; other storage types return an empty list.
return []
except BotoServerError as ex:
logger.error(
u'Fetching files failed for course: %s, status: %s, reason: %s',
course_id,
ex.status,
ex.reason
)
return []
files = [(filename, os.path.join(course_dir, filename)) for filename in filenames]
files.sort(key=lambda f: self.storage.modified_time(f[1]), reverse=True)
return [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment