Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Release Notes
=============

Version 0.20.1
--------------

- fix Safari MIT logo bug (#1631)
- Retry recreate_index subtasks on worker exit (#1615)
- Email for saved searches (#1619)

Version 0.20.0 (Released October 01, 2024)
--------------

Expand Down
3 changes: 1 addition & 2 deletions docker-compose.apps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ services:
command: >
/bin/bash -c '
sleep 3;
celery -A main.celery:app worker -Q default -B -l ${MITOL_LOG_LEVEL:-INFO} &
celery -A main.celery:app worker -Q edx_content,default -l ${MITOL_LOG_LEVEL:-INFO}'
celery -A main.celery:app worker -E -Q default,edx_content -B -l ${MITOL_LOG_LEVEL:-INFO}'
depends_on:
db:
condition: service_healthy
Expand Down
8 changes: 6 additions & 2 deletions frontends/mit-learn/src/GlobalStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ const pageCss = css`
}

#app-container {
height: calc(100vh - 60px);
margin-top: 60px;
height: calc(100vh - 72px);
margin-top: 72px;
${theme.breakpoints.down("sm")} {
margin-top: 60px;
height: calc(100vh - 60px);
}
}

a {
Expand Down
16 changes: 9 additions & 7 deletions frontends/mit-learn/src/page-components/Header/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,15 @@ const UserMenuChevron: React.FC<{ open: boolean }> = ({ open }) => {
}

const StyledMITLogoLink = styled(MITLogoLink)(({ theme }) => ({
width: "64px",
height: "32px",
marginLeft: "16px",
[theme.breakpoints.down("sm")]: {
width: "48px",
height: "24px",
marginLeft: "0",
img: {
width: "64px",
height: "32px",
marginLeft: "16px",
[theme.breakpoints.down("sm")]: {
width: "48px",
height: "24px",
marginLeft: "0",
},
},
}))

Expand Down
7 changes: 5 additions & 2 deletions learning_resources_search/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,17 @@ def source_description(self):
channel = self.source_channel()
if self.display_label:
return self.display_label
if channel:
if channel and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE:
return channel.title
return self.original_url_params()

def source_channel(self):
original_query_params = self.original_url_params()
channels_filtered = Channel.objects.filter(search_filter=original_query_params)
if channels_filtered.exists():
if (
channels_filtered.exists()
and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE
):
return channels_filtered.first()
return None

Expand Down
16 changes: 13 additions & 3 deletions learning_resources_search/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from learning_resources_search.indexing_api import (
get_reindexing_alias_name,
)
from learning_resources_search.models import PercolateQuery

pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("mocked_es")]

Expand Down Expand Up @@ -63,7 +64,9 @@ def test_percolate_query_unit_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "offered_by=mitx"
assert query.source_label() == "unit"
Expand Down Expand Up @@ -91,7 +94,9 @@ def test_percolate_query_topic_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "topic=Math"
assert query.source_label() == "topic"
Expand All @@ -118,7 +123,9 @@ def test_percolate_query_department_labels(mocker, mocked_es):
"yearly_decay_percent": None,
}
query = PercolateQueryFactory.create(
original_query=original_query, query=original_query
original_query=original_query,
query=original_query,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == "department=physics"
assert query.source_label() == "department"
Expand Down Expand Up @@ -196,6 +203,9 @@ def encode_params(oparams):
original_query=original_query,
query=original_query,
display_label=test_label,
source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE
if is_channel_query
else PercolateQuery.SEARCH_SUBSCRIPTION_TYPE,
)
assert query.original_url_params() == encode_params(original_query)
if not is_channel_query:
Expand Down
63 changes: 49 additions & 14 deletions learning_resources_search/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from opensearchpy.exceptions import NotFoundError, RequestError
from requests.models import PreparedRequest

from learning_resources.constants import LearningResourceType
from learning_resources.etl.constants import RESOURCE_FILE_ETL_SOURCES
from learning_resources.models import (
ContentFile,
Expand Down Expand Up @@ -167,7 +168,7 @@ def _infer_percolate_group(percolate_query):
elif key == "offered_by":
return LearningResourceOfferor.objects.get(code=val[0]).name
return val[0]
return None
return percolate_query.original_url_params()


def _infer_percolate_group_url(percolate_query):
Expand All @@ -181,6 +182,8 @@ def _infer_percolate_group_url(percolate_query):
query_string_params = {k: v for k, v in original_query.items() if v}
if "endpoint" in query_string_params:
query_string_params.pop("endpoint")
if "sortby" not in query_string_params:
query_string_params["sortby"] = "new"
query_string = urlencode(query_string_params, doseq=True)
return frontend_absolute_url(f"/search?{query_string}")

Expand Down Expand Up @@ -232,7 +235,9 @@ def _get_percolated_rows(resources, subscription_type):
"resource_image_url": resource.image.url
if resource.image
else "",
"resource_type": resource.resource_type,
"resource_type": LearningResourceType[
resource.resource_type
].value,
"user_id": user,
"source_label": query.source_label(),
"source_channel_type": source_channel.channel_type
Expand Down Expand Up @@ -275,7 +280,13 @@ def send_subscription_emails(self, subscription_type, period="daily"):
return self.replace(email_tasks)


@app.task(autoretry_for=(RetryError,), retry_backoff=True, rate_limit="600/m")
@app.task(
acks_late=True,
reject_on_worker_lost=True,
autoretry_for=(RetryError, SystemExit),
retry_backoff=True,
rate_limit="600/m",
)
def index_learning_resources(ids, resource_type, index_types):
"""
Index courses
Expand All @@ -290,7 +301,7 @@ def index_learning_resources(ids, resource_type, index_types):
try:
with wrap_retry_exception(*SEARCH_CONN_EXCEPTIONS):
api.index_learning_resources(ids, resource_type, index_types)
except (RetryError, Ignore):
except (RetryError, Ignore, SystemExit):
raise
except: # noqa: E722
error = "index_courses threw an error"
Expand Down Expand Up @@ -348,7 +359,13 @@ def bulk_deindex_percolators(ids):
return error


@app.task(autoretry_for=(RetryError,), retry_backoff=True, rate_limit="600/m")
@app.task(
acks_late=True,
reject_on_worker_lost=True,
autoretry_for=(RetryError, SystemExit),
retry_backoff=True,
rate_limit="600/m",
)
def bulk_index_percolate_queries(percolate_ids, index_types):
"""
Bulk index percolate queries for provided percolate query Ids
Expand All @@ -366,7 +383,7 @@ def bulk_index_percolate_queries(percolate_ids, index_types):
PERCOLATE_INDEX_TYPE,
index_types,
)
except (RetryError, Ignore):
except (RetryError, Ignore, SystemExit):
raise
except: # noqa: E722
error = "bulk_index_percolate_queries threw an error"
Expand Down Expand Up @@ -397,7 +414,13 @@ def index_course_content_files(course_ids, index_types):
return error


@app.task(autoretry_for=(RetryError,), retry_backoff=True, rate_limit="600/m")
@app.task(
acks_late=True,
reject_on_worker_lost=True,
autoretry_for=(RetryError, SystemExit),
retry_backoff=True,
rate_limit="600/m",
)
def index_content_files(
content_file_ids,
learning_resource_id,
Expand All @@ -418,7 +441,7 @@ def index_content_files(
api.index_content_files(
content_file_ids, learning_resource_id, index_types=index_types
)
except (RetryError, Ignore):
except (RetryError, Ignore, SystemExit):
raise
except: # noqa: E722
error = "index_content_files threw an error"
Expand Down Expand Up @@ -843,7 +866,7 @@ def get_update_learning_resource_tasks(resource_type):
@app.task(
acks_late=True,
reject_on_worker_lost=True,
autoretry_for=(RetryError,),
autoretry_for=(RetryError, SystemExit),
retry_backoff=True,
rate_limit="600/m",
)
Expand Down Expand Up @@ -881,23 +904,35 @@ def finish_recreate_index(results, backing_indices):
def _generate_subscription_digest_subject(
sample_course, source_name, unique_resource_types, total_count, shortform
):
prefix = "" if shortform else "MIT Learn: "
"""
Generate the subject line and/or content header for subscription emails
Args:
sample_course (a learning resource): A sample resource to reference
source_name (string): the subscription type (saved_search etc)
unique_resource_types (list): set of unique resource types in the email
total_count (int): total number of resources in the email
shortform (bool): if False return the (longer) email subject
otherwise short content header

"""
prefix = "" if shortform else "MIT Learn: "
resource_type = unique_resource_types.pop()
if sample_course["source_channel_type"] == "saved_search":
if shortform:
return f"New {resource_type}{pluralize(total_count)} from MIT Learn"
return (
f"{prefix}New"
f' "{source_name}" '
f"{unique_resource_types.pop().capitalize()}{pluralize(total_count)}"
f" {resource_type}{pluralize(total_count)}: "
f"{sample_course['resource_title']}"
)
preposition = "from"
if sample_course["source_channel_type"] == "topic":
preposition = "in"

suffix = "" if shortform else f": {sample_course['resource_title']}"

return (
f"{prefix}New"
f" {unique_resource_types.pop().capitalize()}{pluralize(total_count)} "
f" {resource_type}{pluralize(total_count)} "
f"{preposition} {source_name}{suffix}"
)

Expand Down
8 changes: 4 additions & 4 deletions learning_resources_search/tasks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -951,7 +951,7 @@ def test_subscription_digest_subject():
total_count=1,
shortform=False,
)
assert subject_line == "MIT Learn: New Program in electronics: robotics"
assert subject_line == "MIT Learn: New program in electronics: robotics"

sample_course = {"source_channel_type": "podcast", "resource_title": "robotics"}
resource_types = {"program"}
Expand All @@ -963,7 +963,7 @@ def test_subscription_digest_subject():
total_count=9,
shortform=False,
)
assert subject_line == "MIT Learn: New Programs from xpro: robotics"
assert subject_line == "MIT Learn: New programs from xpro: robotics"

resource_types = {"podcast"}
subject_line = _generate_subscription_digest_subject(
Expand All @@ -973,13 +973,13 @@ def test_subscription_digest_subject():
total_count=19,
shortform=False,
)
assert subject_line == "MIT Learn: New Podcasts from engineering: robotics"
assert subject_line == "MIT Learn: New podcasts from engineering: robotics"

resource_types = {"course"}
subject_line = _generate_subscription_digest_subject(
sample_course, "management", resource_types, 19, shortform=True
)
assert subject_line == "New Courses from management"
assert subject_line == "New courses from management"


def test_update_featured_rank(mocker, offeror_featured_lists):
Expand Down
2 changes: 1 addition & 1 deletion main/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from main.settings_pluggy import * # noqa: F403
from openapi.settings_spectacular import open_spectacular_settings

VERSION = "0.20.0"
VERSION = "0.20.1"

log = logging.getLogger()

Expand Down
5 changes: 5 additions & 0 deletions main/settings_celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
"schedule": crontab(minute=30, hour=18), # 2:30pm EST
"kwargs": {"period": "daily", "subscription_type": "channel_subscription_type"},
},
"send-search-subscription-emails-every-1-days": {
"task": "learning_resources_search.tasks.send_subscription_emails",
"schedule": crontab(minute=0, hour=19), # 3:00pm EST
"kwargs": {"period": "daily", "subscription_type": "search_subscription_type"},
},
"update-search-featured-ranks-1-days": {
"task": "learning_resources_search.tasks.update_featured_rank",
"schedule": crontab(minute=30, hour=7), # 3:30am EST
Expand Down
Loading