BOTO:S3 handle rate limit exceed and do not expose 500 errors
This commit is contained in:
@@ -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 [
|
||||
|
||||
Reference in New Issue
Block a user