Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
aee4b332
Commit
aee4b332
authored
May 17, 2017
by
Adam Palay
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
write management command to fail old tasks stuck in queueing state
parent
31e00d58
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
234 additions
and
0 deletions
+234
-0
lms/djangoapps/instructor_task/management/__init__.py
+0
-0
lms/djangoapps/instructor_task/management/commands/__init__.py
+0
-0
lms/djangoapps/instructor_task/management/commands/fail_old_queueing_tasks.py
+100
-0
lms/djangoapps/instructor_task/management/commands/tests/__init__.py
+0
-0
lms/djangoapps/instructor_task/management/commands/tests/test_fail_old_queueing_tasks.py
+134
-0
No files found.
lms/djangoapps/instructor_task/management/__init__.py
0 → 100644
View file @
aee4b332
lms/djangoapps/instructor_task/management/commands/__init__.py
0 → 100644
View file @
aee4b332
lms/djangoapps/instructor_task/management/commands/fail_old_queueing_tasks.py
0 → 100644
View file @
aee4b332
from
__future__
import
unicode_literals
,
print_function
from
datetime
import
datetime
from
celery.states
import
FAILURE
from
django.core.management.base
import
BaseCommand
,
CommandError
from
pytz
import
utc
from
lms.djangoapps.instructor_task.models
import
InstructorTask
,
QUEUING
class
Command
(
BaseCommand
):
"""
Command to manually fail old "QUEUING" tasks in the instructor task table.
Example:
./manage.py lms fail_old_queueing_tasks --dry-run --after 2001-01-03
\
--before 2001-01-06 --task-type bulk_course_email
"""
def
add_arguments
(
self
,
parser
):
"""
Add arguments to the command parser.
"""
parser
.
add_argument
(
'--before'
,
type
=
str
,
dest
=
'before'
,
help
=
'Manually fail instructor tasks created before or on this date.'
,
)
parser
.
add_argument
(
'--after'
,
type
=
str
,
dest
=
'after'
,
help
=
'Manually fail instructor tasks created after or on this date.'
,
)
parser
.
add_argument
(
'--dry-run'
,
action
=
'store_true'
,
dest
=
'dry_run'
,
default
=
False
,
help
=
'Return the records this command will update without updating them.'
,
)
parser
.
add_argument
(
'--task-type'
,
dest
=
'task_type'
,
type
=
str
,
default
=
None
,
help
=
'Specify the type of task that you want to fail.'
,
)
@staticmethod
def
parse_date
(
date_string
):
"""
Converts an isoformat string into a python datetime object. Localizes
that datetime object to UTC.
"""
return
utc
.
localize
(
datetime
.
strptime
(
date_string
,
"
%
Y-
%
m-
%
d"
))
def
handle
(
self
,
*
args
,
**
options
):
if
options
[
'before'
]
is
None
:
raise
CommandError
(
"Must provide a 'before' date"
)
if
options
[
'after'
]
is
None
:
raise
CommandError
(
"Must provide an 'after' date"
)
before
=
self
.
parse_date
(
options
[
'before'
])
after
=
self
.
parse_date
(
options
[
'after'
])
filter_kwargs
=
{
"task_state"
:
QUEUING
,
"created__lte"
:
before
,
"created__gte"
:
after
,
}
if
options
[
'task_type'
]
is
not
None
:
filter_kwargs
.
update
({
"task_type"
:
options
[
'task_type'
]})
tasks
=
InstructorTask
.
objects
.
filter
(
**
filter_kwargs
)
for
task
in
tasks
:
print
(
"Queueing task '{task_id}', of type '{task_type}', created on '{created}', will be marked as 'FAILURE'"
.
format
(
task_id
=
task
.
task_id
,
task_type
=
task
.
task_type
,
created
=
task
.
created
,
)
)
if
not
options
[
'dry_run'
]:
tasks_updated
=
tasks
.
update
(
task_state
=
FAILURE
,
)
print
(
"{tasks_updated} records updated."
.
format
(
tasks_updated
=
tasks_updated
)
)
else
:
print
(
"This was a dry run, so no records were updated."
)
lms/djangoapps/instructor_task/management/commands/tests/__init__.py
0 → 100644
View file @
aee4b332
lms/djangoapps/instructor_task/management/commands/tests/test_fail_old_queueing_tasks.py
0 → 100644
View file @
aee4b332
from
datetime
import
datetime
import
ddt
from
celery.states
import
FAILURE
from
django.core.management
import
call_command
from
django.core.management.base
import
CommandError
from
lms.djangoapps.instructor_task.models
import
InstructorTask
,
QUEUING
from
lms.djangoapps.instructor_task.tests.factories
import
InstructorTaskFactory
from
lms.djangoapps.instructor_task.tests.test_base
import
InstructorTaskTestCase
@ddt.ddt
class
TestFailOldQueueingTasksCommand
(
InstructorTaskTestCase
):
"""
Tests for the `fail_old_queueing_tasks` management command
"""
def
setUp
(
self
):
super
(
TestFailOldQueueingTasksCommand
,
self
)
.
setUp
()
type_1_queueing
=
InstructorTaskFactory
.
create
(
task_state
=
QUEUING
,
task_type
=
"type_1"
,
task_key
=
''
,
task_id
=
1
,
)
type_1_non_queueing
=
InstructorTaskFactory
.
create
(
task_state
=
'NOT QUEUEING'
,
task_type
=
"type_1"
,
task_key
=
''
,
task_id
=
2
,
)
type_2_queueing
=
InstructorTaskFactory
.
create
(
task_state
=
QUEUING
,
task_type
=
"type_2"
,
task_key
=
''
,
task_id
=
3
,
)
self
.
tasks
=
[
type_1_queueing
,
type_1_non_queueing
,
type_2_queueing
]
def
update_task_created
(
self
,
created_date
):
"""
Override each task's "created" date
"""
for
task
in
self
.
tasks
:
task
.
created
=
datetime
.
strptime
(
created_date
,
"
%
Y-
%
m-
%
d"
)
task
.
save
()
def
get_tasks
(
self
):
"""
After the command is run, this queries again for the tasks we created
in `setUp`.
"""
type_1_queueing
=
InstructorTask
.
objects
.
get
(
task_id
=
1
)
type_1_non_queueing
=
InstructorTask
.
objects
.
get
(
task_id
=
2
)
type_2_queueing
=
InstructorTask
.
objects
.
get
(
task_id
=
3
)
return
type_1_queueing
,
type_1_non_queueing
,
type_2_queueing
@ddt.data
(
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-06'
),
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-08'
),
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-04'
),
)
@ddt.unpack
def
test_dry_run
(
self
,
after
,
before
,
created
):
"""
Tests that nothing is updated when run with the `dry_run` option
"""
self
.
update_task_created
(
created
)
call_command
(
'fail_old_queueing_tasks'
,
dry_run
=
True
,
before
=
before
,
after
=
after
,
)
type_1_queueing
,
type_1_non_queueing
,
type_2_queueing
=
self
.
get_tasks
()
self
.
assertEqual
(
type_1_queueing
.
task_state
,
QUEUING
)
self
.
assertEqual
(
type_2_queueing
.
task_state
,
QUEUING
)
self
.
assertEqual
(
type_1_non_queueing
.
task_state
,
'NOT QUEUEING'
)
@ddt.data
(
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-06'
,
FAILURE
),
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-08'
,
QUEUING
),
(
'2015-05-05'
,
'2015-05-07'
,
'2015-05-04'
,
QUEUING
),
)
@ddt.unpack
def
test_tasks_updated
(
self
,
after
,
before
,
created
,
expected_state
):
"""
Test that tasks created outside the window of dates don't get changed,
while tasks created in the window do get changed.
Verifies that non-queueing tasks never get changed.
"""
self
.
update_task_created
(
created
)
call_command
(
'fail_old_queueing_tasks'
,
before
=
before
,
after
=
after
)
type_1_queueing
,
type_1_non_queueing
,
type_2_queueing
=
self
.
get_tasks
()
self
.
assertEqual
(
type_1_queueing
.
task_state
,
expected_state
)
self
.
assertEqual
(
type_2_queueing
.
task_state
,
expected_state
)
self
.
assertEqual
(
type_1_non_queueing
.
task_state
,
'NOT QUEUEING'
)
def
test_filter_by_task_type
(
self
):
"""
Test that if we specify which task types to update, only tasks with
those types are updated
"""
self
.
update_task_created
(
'2015-05-06'
)
call_command
(
'fail_old_queueing_tasks'
,
before
=
'2015-05-07'
,
after
=
'2015-05-05'
,
task_type
=
"type_1"
,
)
type_1_queueing
,
type_1_non_queueing
,
type_2_queueing
=
self
.
get_tasks
()
self
.
assertEqual
(
type_1_queueing
.
task_state
,
FAILURE
)
# the other type of task shouldn't be updated
self
.
assertEqual
(
type_2_queueing
.
task_state
,
QUEUING
)
self
.
assertEqual
(
type_1_non_queueing
.
task_state
,
'NOT QUEUEING'
)
@ddt.data
(
(
'2015-05-05'
,
None
),
(
None
,
'2015-05-05'
),
)
@ddt.unpack
def
test_date_errors
(
self
,
after
,
before
):
"""
Test that we get a CommandError when we don't supply before and after
dates.
"""
with
self
.
assertRaises
(
CommandError
):
call_command
(
'fail_old_queueing_tasks'
,
before
=
before
,
after
=
after
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment