Commit eb11ba76 by Calen Pennington

Better unicode handling in instructor tasks/bulk-email

parent 54bd1cbe
...@@ -161,7 +161,7 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name) ...@@ -161,7 +161,7 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name)
# code that doesn't need the entry_id. # code that doesn't need the entry_id.
if course_id != entry.course_id: if course_id != entry.course_id:
format_msg = u"Course id conflict: explicit value %r does not match task value %r" format_msg = u"Course id conflict: explicit value %r does not match task value %r"
log.warning("Task %s: " + format_msg, task_id, course_id, entry.course_id) log.warning(u"Task %s: " + format_msg, task_id, course_id, entry.course_id)
raise ValueError(format_msg % (course_id, entry.course_id)) raise ValueError(format_msg % (course_id, entry.course_id))
# Fetch the CourseEmail. # Fetch the CourseEmail.
...@@ -171,7 +171,7 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name) ...@@ -171,7 +171,7 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name)
except CourseEmail.DoesNotExist: except CourseEmail.DoesNotExist:
# The CourseEmail object should be committed in the view function before the task # The CourseEmail object should be committed in the view function before the task
# is submitted and reaches this point. # is submitted and reaches this point.
log.warning("Task %s: Failed to get CourseEmail with id %s", task_id, email_id) log.warning(u"Task %s: Failed to get CourseEmail with id %s", task_id, email_id)
raise raise
# Check to see if email batches have already been defined. This seems to # Check to see if email batches have already been defined. This seems to
...@@ -182,21 +182,22 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name) ...@@ -182,21 +182,22 @@ def perform_delegate_email_batches(entry_id, course_id, task_input, action_name)
# So we just return right away. We don't raise an exception, because we want # So we just return right away. We don't raise an exception, because we want
# the current task to be marked with whatever it had been marked with before. # the current task to be marked with whatever it had been marked with before.
if len(entry.subtasks) > 0 and len(entry.task_output) > 0: if len(entry.subtasks) > 0 and len(entry.task_output) > 0:
log.warning("Task %s has already been processed for email %s! InstructorTask = %s", task_id, email_id, entry) log.warning(u"Task %s has already been processed for email %s! InstructorTask = %s", task_id, email_id, entry)
progress = json.loads(entry.task_output) progress = json.loads(entry.task_output)
return progress return progress
# Sanity check that course for email_obj matches that of the task referencing it. # Sanity check that course for email_obj matches that of the task referencing it.
if course_id != email_obj.course_id: if course_id != email_obj.course_id:
format_msg = u"Course id conflict: explicit value %r does not match email value %r" format_msg = u"Course id conflict: explicit value %r does not match email value %r"
log.warning("Task %s: " + format_msg, task_id, course_id, email_obj.course_id) log.warning(u"Task %s: " + format_msg, task_id, course_id, email_obj.course_id)
raise ValueError(format_msg % (course_id, email_obj.course_id)) raise ValueError(format_msg % (course_id, email_obj.course_id))
# Fetch the course object. # Fetch the course object.
course = get_course(course_id) course = get_course(course_id)
if course is None: if course is None:
msg = "Task %s: course not found: %s" msg = u"Task %s: course not found: %s"
log.error(msg, task_id, course_id) log.error(msg, task_id, course_id)
raise ValueError(msg % (task_id, course_id)) raise ValueError(msg % (task_id, course_id))
...@@ -282,7 +283,7 @@ def send_course_email(entry_id, email_id, to_list, global_email_context, subtask ...@@ -282,7 +283,7 @@ def send_course_email(entry_id, email_id, to_list, global_email_context, subtask
subtask_status = SubtaskStatus.from_dict(subtask_status_dict) subtask_status = SubtaskStatus.from_dict(subtask_status_dict)
current_task_id = subtask_status.task_id current_task_id = subtask_status.task_id
num_to_send = len(to_list) num_to_send = len(to_list)
log.info("Preparing to send email %s to %d recipients as subtask %s for instructor task %d: context = %s, status=%s", log.info(u"Preparing to send email %s to %d recipients as subtask %s for instructor task %d: context = %s, status=%s",
email_id, num_to_send, current_task_id, entry_id, global_email_context, subtask_status) email_id, num_to_send, current_task_id, entry_id, global_email_context, subtask_status)
# Check that the requested subtask is actually known to the current InstructorTask entry. # Check that the requested subtask is actually known to the current InstructorTask entry.
...@@ -660,7 +661,7 @@ def _submit_for_retry(entry_id, email_id, to_list, global_email_context, current ...@@ -660,7 +661,7 @@ def _submit_for_retry(entry_id, email_id, to_list, global_email_context, current
) )
except RetryTaskError as retry_error: except RetryTaskError as retry_error:
# If the retry call is successful, update with the current progress: # If the retry call is successful, update with the current progress:
log.exception('Task %s: email with id %d caused send_course_email task to retry.', log.exception(u'Task %s: email with id %d caused send_course_email task to retry.',
task_id, email_id) task_id, email_id)
return subtask_status, retry_error return subtask_status, retry_error
except Exception as retry_exc: except Exception as retry_exc:
...@@ -669,7 +670,7 @@ def _submit_for_retry(entry_id, email_id, to_list, global_email_context, current ...@@ -669,7 +670,7 @@ def _submit_for_retry(entry_id, email_id, to_list, global_email_context, current
# (and put it in retry_exc just in case it's different, but it shouldn't be), # (and put it in retry_exc just in case it's different, but it shouldn't be),
# and update status as if it were any other failure. That means that # and update status as if it were any other failure. That means that
# the recipients still in the to_list are counted as failures. # the recipients still in the to_list are counted as failures.
log.exception('Task %s: email with id %d caused send_course_email task to fail to retry. To list: %s', log.exception(u'Task %s: email with id %d caused send_course_email task to fail to retry. To list: %s',
task_id, email_id, [i['email'] for i in to_list]) task_id, email_id, [i['email'] for i in to_list])
num_failed = len(to_list) num_failed = len(to_list)
subtask_status.increment(subtask_status, failed=num_failed, state=FAILURE) subtask_status.increment(subtask_status, failed=num_failed, state=FAILURE)
...@@ -680,5 +681,5 @@ def _statsd_tag(course_title): ...@@ -680,5 +681,5 @@ def _statsd_tag(course_title):
""" """
Calculate the tag we will use for DataDog. Calculate the tag we will use for DataDog.
""" """
tag = u"course_email:{0}".format(course_title) tag = u"course_email:{0}".format(course_title).encode('utf-8')
return tag[:200] return tag[:200]
...@@ -160,7 +160,7 @@ class InstructorTask(models.Model): ...@@ -160,7 +160,7 @@ class InstructorTask(models.Model):
Truncation is indicated by adding "..." to the end of the value. Truncation is indicated by adding "..." to the end of the value.
""" """
tag = '...' tag = '...'
task_progress = {'exception': type(exception).__name__, 'message': str(exception.message)} task_progress = {'exception': type(exception).__name__, 'message': unicode(exception.message)}
if traceback_string is not None: if traceback_string is not None:
# truncate any traceback that goes into the InstructorTask model: # truncate any traceback that goes into the InstructorTask model:
task_progress['traceback'] = traceback_string task_progress['traceback'] = traceback_string
......
...@@ -108,16 +108,16 @@ class BaseInstructorTask(Task): ...@@ -108,16 +108,16 @@ class BaseInstructorTask(Task):
Note that there is no way to record progress made within the task (e.g. attempted, Note that there is no way to record progress made within the task (e.g. attempted,
succeeded, etc.) when such failures occur. succeeded, etc.) when such failures occur.
""" """
TASK_LOG.debug('Task %s: failure returned', task_id) TASK_LOG.debug(u'Task %s: failure returned', task_id)
entry_id = args[0] entry_id = args[0]
try: try:
entry = InstructorTask.objects.get(pk=entry_id) entry = InstructorTask.objects.get(pk=entry_id)
except InstructorTask.DoesNotExist: except InstructorTask.DoesNotExist:
# if the InstructorTask object does not exist, then there's no point # if the InstructorTask object does not exist, then there's no point
# trying to update it. # trying to update it.
TASK_LOG.error("Task (%s) has no InstructorTask object for id %s", task_id, entry_id) TASK_LOG.error(u"Task (%s) has no InstructorTask object for id %s", task_id, entry_id)
else: else:
TASK_LOG.warning("Task (%s) failed: %s %s", task_id, einfo.exception, einfo.traceback) TASK_LOG.warning(u"Task (%s) failed", task_id, exc_info=True)
entry.task_output = InstructorTask.create_output_for_failure(einfo.exception, einfo.traceback) entry.task_output = InstructorTask.create_output_for_failure(einfo.exception, einfo.traceback)
entry.task_state = FAILURE entry.task_state = FAILURE
entry.save_now() entry.save_now()
...@@ -296,7 +296,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta ...@@ -296,7 +296,7 @@ def perform_module_state_update(update_fcn, filter_fcn, _entry_id, course_id, ta
num_attempted += 1 num_attempted += 1
# There is no try here: if there's an error, we let it throw, and the task will # There is no try here: if there's an error, we let it throw, and the task will
# be marked as FAILED, with a stack trace. # be marked as FAILED, with a stack trace.
with dog_stats_api.timer('instructor_tasks.module.time.step', tags=['action:{name}'.format(name=action_name)]): with dog_stats_api.timer('instructor_tasks.module.time.step', tags=[u'action:{name}'.format(name=action_name)]):
update_status = update_fcn(module_descriptor, module_to_update) update_status = update_fcn(module_descriptor, module_to_update)
if update_status == UPDATE_STATUS_SUCCEEDED: if update_status == UPDATE_STATUS_SUCCEEDED:
# If the update_fcn returns true, then it performed some kind of work. # If the update_fcn returns true, then it performed some kind of work.
......
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