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
eff9c9c9
Commit
eff9c9c9
authored
Oct 19, 2017
by
Calen Pennington
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move common attributes into Resolver.__init__
parent
27fd73ac
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
64 additions
and
84 deletions
+64
-84
openedx/core/djangoapps/schedules/resolvers.py
+61
-82
openedx/core/djangoapps/schedules/tasks.py
+2
-2
requirements/edx/base.txt
+1
-0
No files found.
openedx/core/djangoapps/schedules/resolvers.py
View file @
eff9c9c9
...
...
@@ -2,6 +2,7 @@ import datetime
from
itertools
import
groupby
import
logging
import
attr
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.contrib.sites.models
import
Site
...
...
@@ -42,6 +43,8 @@ RECURRING_NUDGE_NUM_BINS = DEFAULT_NUM_BINS
UPGRADE_REMINDER_NUM_BINS
=
DEFAULT_NUM_BINS
COURSE_UPDATE_NUM_BINS
=
DEFAULT_NUM_BINS
@attr.s
class
BinnedSchedulesBaseResolver
(
PrefixedDebugLoggerMixin
,
RecipientResolver
):
"""
Starts num_bins number of async tasks, each of which sends emails to an equal group of learners.
...
...
@@ -55,6 +58,15 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
num_bins -- the int number of bins to split the users into
enqueue_config_var -- the string field name of the config variable on ScheduleConfig to check before enqueuing
"""
async_send_task
=
attr
.
ib
()
site
=
attr
.
ib
()
target_datetime
=
attr
.
ib
()
day_offset
=
attr
.
ib
()
bin_num
=
attr
.
ib
()
org_list
=
attr
.
ib
()
exclude_orgs
=
attr
.
ib
(
default
=
False
)
override_recipient_email
=
attr
.
ib
(
default
=
None
)
def
send
(
self
,
msg_type
):
pass
...
...
@@ -156,45 +168,35 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
"""
log_prefix
=
'Scheduled Nudge'
def
schedule_bin
(
self
,
async_send_task
,
site
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
target_datetime
-
datetime
.
timedelta
(
days
=
day_offset
)
msg_type
=
RecurringNudge
(
abs
(
day_offset
))
_annotate_for_monitoring
(
msg_type
,
site
,
bin_num
,
target_datetime
,
day_offset
)
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
(
site
,
current_datetime
,
target_datetime
,
bin_num
,
org_list
,
exclude_orgs
):
def
schedule_bin
(
self
):
msg_type
=
RecurringNudge
(
abs
(
self
.
day_offset
))
_annotate_for_monitoring
(
msg_type
,
self
.
site
,
self
.
bin_num
,
self
.
target_datetime
,
self
.
day_offset
)
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
():
msg
=
msg_type
.
personalize
(
Recipient
(
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
language
,
context
,
)
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
self
.
async_send_task
.
apply_async
(
(
s
elf
.
s
ite
.
id
,
str
(
msg
)),
retry
=
False
)
def
schedules_for_bin
(
self
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
self
.
target_datetime
-
datetime
.
timedelta
(
days
=
self
.
day_offset
)
def
schedules_for_bin
(
self
,
site
,
current_datetime
,
target_datetime
,
bin_num
,
org_list
,
exclude_orgs
=
False
):
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'start'
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
bin_num
=
bin_num
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
self
.
bin_num
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
org_list
=
org_list
,
exclude_orgs
=
exclude_orgs
,
org_list
=
self
.
org_list
,
exclude_orgs
=
self
.
exclude_orgs
,
)
LOG
.
debug
(
'Recurring Nudge: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
...
...
@@ -204,12 +206,12 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
first_schedule
=
user_schedules
[
0
]
template_context
=
get_base_template_context
(
site
)
template_context
=
get_base_template_context
(
s
elf
.
s
ite
)
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'course_url'
:
absolute_url
(
site
,
reverse
(
'course_root'
,
args
=
[
str
(
first_schedule
.
enrollment
.
course_id
)])),
'course_url'
:
absolute_url
(
s
elf
.
s
ite
,
reverse
(
'course_root'
,
args
=
[
str
(
first_schedule
.
enrollment
.
course_id
)])),
# This is used by the bulk email optout policy
'course_ids'
:
course_id_strs
,
...
...
@@ -238,45 +240,34 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
"""
log_prefix
=
'Upgrade Reminder'
def
schedule_bin
(
self
,
async_send_task
,
site
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
target_datetime
-
datetime
.
timedelta
(
days
=
day_offset
)
def
schedule_bin
(
self
):
msg_type
=
UpgradeReminder
()
_annotate_for_monitoring
(
msg_type
,
self
.
site
,
self
.
bin_num
,
self
.
target_datetime
,
self
.
day_offset
)
_annotate_for_monitoring
(
msg_type
,
site
,
bin_num
,
target_datetime
,
day_offset
)
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
(
site
,
current_datetime
,
target_datetime
,
bin_num
,
org_list
,
exclude_orgs
):
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
():
msg
=
msg_type
.
personalize
(
Recipient
(
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
language
,
context
,
)
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
self
.
async_send_task
.
apply_async
(
(
self
.
site
.
id
,
str
(
msg
)),
retry
=
False
)
def
schedules_for_bin
(
self
,
site
,
current_datetime
,
target_datetime
,
bin_num
,
org_list
,
exclude_orgs
=
False
):
def
schedules_for_bin
(
self
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
self
.
target_datetime
-
datetime
.
timedelta
(
days
=
self
.
day_offset
)
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'upgrade_deadline'
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
bin_num
=
bin_num
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
self
.
bin_num
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
org_list
=
org_list
,
exclude_orgs
=
exclude_orgs
,
org_list
=
self
.
org_list
,
exclude_orgs
=
self
.
exclude_orgs
,
)
for
(
user
,
user_schedules
)
in
groupby
(
schedules
,
lambda
s
:
s
.
enrollment
.
user
):
...
...
@@ -284,17 +275,17 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
first_schedule
=
user_schedules
[
0
]
template_context
=
get_base_template_context
(
site
)
template_context
=
get_base_template_context
(
s
elf
.
s
ite
)
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'course_links'
:
[
{
'url'
:
absolute_url
(
site
,
reverse
(
'course_root'
,
args
=
[
str
(
s
.
enrollment
.
course_id
)])),
'url'
:
absolute_url
(
s
elf
.
s
ite
,
reverse
(
'course_root'
,
args
=
[
str
(
s
.
enrollment
.
course_id
)])),
'name'
:
s
.
enrollment
.
course
.
display_name
}
for
s
in
user_schedules
],
'first_course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'cert_image'
:
absolute_url
(
site
,
static
(
'course_experience/images/verified-cert.png'
)),
'cert_image'
:
absolute_url
(
s
elf
.
s
ite
,
static
(
'course_experience/images/verified-cert.png'
)),
# This is used by the bulk email optout policy
'course_ids'
:
course_id_strs
,
...
...
@@ -346,47 +337,35 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
"""
log_prefix
=
'Course Update'
def
schedule_bin
(
self
,
async_send_task
,
site
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
target_datetime
-
datetime
.
timedelta
(
days
=
day_offset
)
def
schedule_bin
(
self
):
msg_type
=
CourseUpdate
()
_annotate_for_monitoring
(
msg_type
,
self
.
site
,
self
.
bin_num
,
self
.
target_datetime
,
self
.
day_offset
)
_annotate_for_monitoring
(
msg_type
,
site
,
bin_num
,
target_datetime
,
day_offset
)
for
(
user
,
language
,
context
)
in
self
.
_course_update_schedules_for_bin
(
site
,
current_datetime
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
):
for
(
user
,
language
,
context
)
in
self
.
_course_update_schedules_for_bin
():
msg
=
msg_type
.
personalize
(
Recipient
(
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
language
,
context
,
)
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
self
.
async_send_task
.
apply_async
(
(
s
elf
.
s
ite
.
id
,
str
(
msg
)),
retry
=
False
)
def
schedules_for_bin
(
self
,
site
,
current_datetime
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
):
week_num
=
abs
(
day_offset
)
/
7
def
schedules_for_bin
(
self
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
current_datetime
=
self
.
target_datetime
-
datetime
.
timedelta
(
days
=
self
.
day_offset
)
week_num
=
abs
(
self
.
day_offset
)
/
7
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'start'
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
bin_num
=
bin_num
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
self
.
bin_num
,
num_bins
=
COURSE_UPDATE_NUM_BINS
,
org_list
=
org_list
,
exclude_orgs
=
exclude_orgs
,
org_list
=
self
.
org_list
,
exclude_orgs
=
self
.
exclude_orgs
,
order_by
=
'enrollment__course'
,
)
LOG
.
debug
(
'Course Update: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
...
...
@@ -402,12 +381,12 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
user
=
enrollment
.
user
course_id_str
=
str
(
enrollment
.
course_id
)
template_context
=
get_base_template_context
(
site
)
template_context
=
get_base_template_context
(
s
elf
.
s
ite
)
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'user_personal_address'
:
user
.
profile
.
name
if
user
.
profile
.
name
else
user
.
username
,
'course_name'
:
schedule
.
enrollment
.
course
.
display_name
,
'course_url'
:
absolute_url
(
site
,
reverse
(
'course_root'
,
args
=
[
str
(
schedule
.
enrollment
.
course_id
)])),
'course_url'
:
absolute_url
(
s
elf
.
s
ite
,
reverse
(
'course_root'
,
args
=
[
str
(
schedule
.
enrollment
.
course_id
)])),
'week_num'
:
week_num
,
'week_summary'
:
week_summary
,
...
...
openedx/core/djangoapps/schedules/tasks.py
View file @
eff9c9c9
...
...
@@ -134,7 +134,7 @@ class ScheduleMessageBaseTask(Task):
def
run
(
self
,
site_id
,
target_day_str
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
):
return
self
.
resolver
(
)
.
schedule_bin
(
return
self
.
resolver
(
self
.
async_send_task
,
Site
.
objects
.
get
(
id
=
site_id
),
deserialize
(
target_day_str
),
...
...
@@ -143,7 +143,7 @@ class ScheduleMessageBaseTask(Task):
org_list
,
exclude_orgs
=
exclude_orgs
,
override_recipient_email
=
override_recipient_email
,
)
)
.
schedule_bin
()
@task
(
ignore_result
=
True
,
routing_key
=
ROUTING_KEY
)
...
...
requirements/edx/base.txt
View file @
eff9c9c9
...
...
@@ -4,6 +4,7 @@
# * @edx/ospr - to check licensing
# * @edx/devops - to check system requirements
attrs==17.2.0
beautifulsoup4==4.1.3
beautifulsoup==3.2.1
bleach==1.4
...
...
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