Use a stable ordering for shuffled tasks.
This commit is contained in:
@@ -4,8 +4,8 @@ Command to compute all grades for specified courses.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
from random import shuffle
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
import six
|
||||
@@ -88,7 +88,8 @@ class Command(BaseCommand):
|
||||
Enqueue all tasks, in shuffled order.
|
||||
"""
|
||||
task_options = {'routing_key': options['routing_key']} if options.get('routing_key') else {}
|
||||
for kwargs in self._shuffled_task_kwargs(options):
|
||||
for seq_id, kwargs in enumerate(self._shuffled_task_kwargs(options)):
|
||||
kwargs['seq_id'] = seq_id
|
||||
result = tasks.compute_grades_for_course_v2.apply_async(kwargs=kwargs, **task_options)
|
||||
log.info("Grades: Created {task_name}[{task_id}] with arguments {kwargs}".format(
|
||||
task_name=tasks.compute_grades_for_course.name,
|
||||
@@ -116,7 +117,7 @@ class Command(BaseCommand):
|
||||
# The dictionaries with their extra overhead will be created
|
||||
# and consumed one at a time.
|
||||
all_args.append((six.text_type(course_key), offset, batch_size))
|
||||
shuffle(all_args)
|
||||
all_args.sort(key=lambda x: hashlib.md5(b'{!r}'.format(x)))
|
||||
for args in all_args:
|
||||
yield {
|
||||
'course_key': args[0],
|
||||
|
||||
@@ -27,6 +27,14 @@ def _sorted_by_batch(calls):
|
||||
return sorted(calls, key=lambda x: (x[1]['kwargs']['course_key'], x[1]['kwargs']['offset']))
|
||||
|
||||
|
||||
class Any(object):
|
||||
"""
|
||||
Dummy object that compares equal to all other objects.
|
||||
"""
|
||||
def __eq__(self, other):
|
||||
return True
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
"""
|
||||
@@ -100,7 +108,8 @@ class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
'course_key': course_key,
|
||||
'batch_size': 2,
|
||||
'offset': offset,
|
||||
'estimate_first_attempted': estimate_first_attempted
|
||||
'estimate_first_attempted': estimate_first_attempted,
|
||||
'seq_id': Any(),
|
||||
}
|
||||
self.assertEqual(
|
||||
_sorted_by_batch(mock_task.apply_async.call_args_list),
|
||||
@@ -136,7 +145,8 @@ class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
'course_key': self.course_keys[1],
|
||||
'batch_size': 2,
|
||||
'offset': 0,
|
||||
'estimate_first_attempted': True
|
||||
'estimate_first_attempted': True,
|
||||
'seq_id': Any(),
|
||||
},
|
||||
},),
|
||||
({
|
||||
@@ -144,7 +154,8 @@ class TestComputeGrades(SharedModuleStoreTestCase):
|
||||
'course_key': self.course_keys[1],
|
||||
'batch_size': 2,
|
||||
'offset': 2,
|
||||
'estimate_first_attempted': True
|
||||
'estimate_first_attempted': True,
|
||||
'seq_id': Any(),
|
||||
},
|
||||
},),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user