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
...
@@ -2,6 +2,7 @@ import datetime
from
itertools
import
groupby
from
itertools
import
groupby
import
logging
import
logging
import
attr
from
django.conf
import
settings
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
from
django.contrib.sites.models
import
Site
from
django.contrib.sites.models
import
Site
...
@@ -42,6 +43,8 @@ RECURRING_NUDGE_NUM_BINS = DEFAULT_NUM_BINS
...
@@ -42,6 +43,8 @@ RECURRING_NUDGE_NUM_BINS = DEFAULT_NUM_BINS
UPGRADE_REMINDER_NUM_BINS
=
DEFAULT_NUM_BINS
UPGRADE_REMINDER_NUM_BINS
=
DEFAULT_NUM_BINS
COURSE_UPDATE_NUM_BINS
=
DEFAULT_NUM_BINS
COURSE_UPDATE_NUM_BINS
=
DEFAULT_NUM_BINS
@attr.s
class
BinnedSchedulesBaseResolver
(
PrefixedDebugLoggerMixin
,
RecipientResolver
):
class
BinnedSchedulesBaseResolver
(
PrefixedDebugLoggerMixin
,
RecipientResolver
):
"""
"""
Starts num_bins number of async tasks, each of which sends emails to an equal group of learners.
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):
...
@@ -55,6 +58,15 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
num_bins -- the int number of bins to split the users into
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
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
):
def
send
(
self
,
msg_type
):
pass
pass
...
@@ -156,45 +168,35 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
...
@@ -156,45 +168,35 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
"""
"""
log_prefix
=
'Scheduled Nudge'
log_prefix
=
'Scheduled Nudge'
def
schedule_bin
(
def
schedule_bin
(
self
):
self
,
async_send_task
,
site
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
msg_type
=
RecurringNudge
(
abs
(
self
.
day_offset
))
):
_annotate_for_monitoring
(
msg_type
,
self
.
site
,
self
.
bin_num
,
self
.
target_datetime
,
self
.
day_offset
)
# 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
)
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
():
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
):
msg
=
msg_type
.
personalize
(
msg
=
msg_type
.
personalize
(
Recipient
(
Recipient
(
user
.
username
,
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
),
language
,
language
,
context
,
context
,
)
)
with
function_trace
(
'enqueue_send_task'
):
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
self
.
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
(
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
(
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'start'
,
schedule_date_field
=
'start'
,
current_datetime
=
current_datetime
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
bin_num
,
bin_num
=
self
.
bin_num
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
org_list
=
org_list
,
org_list
=
self
.
org_list
,
exclude_orgs
=
exclude_orgs
,
exclude_orgs
=
self
.
exclude_orgs
,
)
)
LOG
.
debug
(
'Recurring Nudge: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
LOG
.
debug
(
'Recurring Nudge: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
...
@@ -204,12 +206,12 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
...
@@ -204,12 +206,12 @@ class ScheduleStartResolver(BinnedSchedulesBaseResolver):
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
first_schedule
=
user_schedules
[
0
]
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
({
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'student_name'
:
user
.
profile
.
name
,
'course_name'
:
first_schedule
.
enrollment
.
course
.
display_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
# This is used by the bulk email optout policy
'course_ids'
:
course_id_strs
,
'course_ids'
:
course_id_strs
,
...
@@ -238,45 +240,34 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
...
@@ -238,45 +240,34 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
"""
"""
log_prefix
=
'Upgrade Reminder'
log_prefix
=
'Upgrade Reminder'
def
schedule_bin
(
def
schedule_bin
(
self
):
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
=
UpgradeReminder
()
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
():
for
(
user
,
language
,
context
)
in
self
.
schedules_for_bin
(
site
,
current_datetime
,
target_datetime
,
bin_num
,
org_list
,
exclude_orgs
):
msg
=
msg_type
.
personalize
(
msg
=
msg_type
.
personalize
(
Recipient
(
Recipient
(
user
.
username
,
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
),
language
,
language
,
context
,
context
,
)
)
with
function_trace
(
'enqueue_send_task'
):
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
self
.
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
(
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
(
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'upgrade_deadline'
,
schedule_date_field
=
'upgrade_deadline'
,
current_datetime
=
current_datetime
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
bin_num
,
bin_num
=
self
.
bin_num
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
num_bins
=
RECURRING_NUDGE_NUM_BINS
,
org_list
=
org_list
,
org_list
=
self
.
org_list
,
exclude_orgs
=
exclude_orgs
,
exclude_orgs
=
self
.
exclude_orgs
,
)
)
for
(
user
,
user_schedules
)
in
groupby
(
schedules
,
lambda
s
:
s
.
enrollment
.
user
):
for
(
user
,
user_schedules
)
in
groupby
(
schedules
,
lambda
s
:
s
.
enrollment
.
user
):
...
@@ -284,17 +275,17 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
...
@@ -284,17 +275,17 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver):
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
course_id_strs
=
[
str
(
schedule
.
enrollment
.
course_id
)
for
schedule
in
user_schedules
]
first_schedule
=
user_schedules
[
0
]
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
({
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'student_name'
:
user
.
profile
.
name
,
'course_links'
:
[
'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
'name'
:
s
.
enrollment
.
course
.
display_name
}
for
s
in
user_schedules
}
for
s
in
user_schedules
],
],
'first_course_name'
:
first_schedule
.
enrollment
.
course
.
display_name
,
'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
# This is used by the bulk email optout policy
'course_ids'
:
course_id_strs
,
'course_ids'
:
course_id_strs
,
...
@@ -346,47 +337,35 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
...
@@ -346,47 +337,35 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
"""
"""
log_prefix
=
'Course Update'
log_prefix
=
'Course Update'
def
schedule_bin
(
def
schedule_bin
(
self
):
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
=
CourseUpdate
()
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
():
for
(
user
,
language
,
context
)
in
self
.
_course_update_schedules_for_bin
(
site
,
current_datetime
,
target_datetime
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
):
msg
=
msg_type
.
personalize
(
msg
=
msg_type
.
personalize
(
Recipient
(
Recipient
(
user
.
username
,
user
.
username
,
override_recipient_email
or
user
.
email
,
self
.
override_recipient_email
or
user
.
email
,
),
),
language
,
language
,
context
,
context
,
)
)
with
function_trace
(
'enqueue_send_task'
):
with
function_trace
(
'enqueue_send_task'
):
async_send_task
.
apply_async
(
self
.
async_send_task
.
apply_async
(
(
site
.
id
,
str
(
msg
)),
retry
=
False
)
(
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
,
def
schedules_for_bin
(
self
):
exclude_orgs
=
False
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
week_num
=
abs
(
day_offset
)
/
7
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
(
schedules
=
get_schedules_with_target_date_by_bin_and_orgs
(
schedule_date_field
=
'start'
,
schedule_date_field
=
'start'
,
current_datetime
=
current_datetime
,
current_datetime
=
current_datetime
,
target_datetime
=
target_datetime
,
target_datetime
=
self
.
target_datetime
,
bin_num
=
bin_num
,
bin_num
=
self
.
bin_num
,
num_bins
=
COURSE_UPDATE_NUM_BINS
,
num_bins
=
COURSE_UPDATE_NUM_BINS
,
org_list
=
org_list
,
org_list
=
self
.
org_list
,
exclude_orgs
=
exclude_orgs
,
exclude_orgs
=
self
.
exclude_orgs
,
order_by
=
'enrollment__course'
,
order_by
=
'enrollment__course'
,
)
)
LOG
.
debug
(
'Course Update: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
LOG
.
debug
(
'Course Update: Query =
%
r'
,
schedules
.
query
.
sql_with_params
())
...
@@ -402,12 +381,12 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
...
@@ -402,12 +381,12 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
user
=
enrollment
.
user
user
=
enrollment
.
user
course_id_str
=
str
(
enrollment
.
course_id
)
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
({
template_context
.
update
({
'student_name'
:
user
.
profile
.
name
,
'student_name'
:
user
.
profile
.
name
,
'user_personal_address'
:
user
.
profile
.
name
if
user
.
profile
.
name
else
user
.
username
,
'user_personal_address'
:
user
.
profile
.
name
if
user
.
profile
.
name
else
user
.
username
,
'course_name'
:
schedule
.
enrollment
.
course
.
display_name
,
'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_num'
:
week_num
,
'week_summary'
:
week_summary
,
'week_summary'
:
week_summary
,
...
...
openedx/core/djangoapps/schedules/tasks.py
View file @
eff9c9c9
...
@@ -134,7 +134,7 @@ class ScheduleMessageBaseTask(Task):
...
@@ -134,7 +134,7 @@ class ScheduleMessageBaseTask(Task):
def
run
(
def
run
(
self
,
site_id
,
target_day_str
,
day_offset
,
bin_num
,
org_list
,
exclude_orgs
=
False
,
override_recipient_email
=
None
,
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
,
self
.
async_send_task
,
Site
.
objects
.
get
(
id
=
site_id
),
Site
.
objects
.
get
(
id
=
site_id
),
deserialize
(
target_day_str
),
deserialize
(
target_day_str
),
...
@@ -143,7 +143,7 @@ class ScheduleMessageBaseTask(Task):
...
@@ -143,7 +143,7 @@ class ScheduleMessageBaseTask(Task):
org_list
,
org_list
,
exclude_orgs
=
exclude_orgs
,
exclude_orgs
=
exclude_orgs
,
override_recipient_email
=
override_recipient_email
,
override_recipient_email
=
override_recipient_email
,
)
)
.
schedule_bin
()
@task
(
ignore_result
=
True
,
routing_key
=
ROUTING_KEY
)
@task
(
ignore_result
=
True
,
routing_key
=
ROUTING_KEY
)
...
...
requirements/edx/base.txt
View file @
eff9c9c9
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
# * @edx/ospr - to check licensing
# * @edx/ospr - to check licensing
# * @edx/devops - to check system requirements
# * @edx/devops - to check system requirements
attrs==17.2.0
beautifulsoup4==4.1.3
beautifulsoup4==4.1.3
beautifulsoup==3.2.1
beautifulsoup==3.2.1
bleach==1.4
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