From f36673aff933c31c31fdc5d419672bea4a530a4c Mon Sep 17 00:00:00 2001 From: Emma Green Date: Tue, 26 Feb 2019 10:56:36 -0500 Subject: [PATCH] fix course program cache --- .../management/commands/cache_programs.py | 13 +++++------ .../djangoapps/catalog/tests/test_utils.py | 22 +++++++++++++++++++ openedx/core/djangoapps/catalog/utils.py | 4 +++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/openedx/core/djangoapps/catalog/management/commands/cache_programs.py b/openedx/core/djangoapps/catalog/management/commands/cache_programs.py index 35b2416bd9..5388ccc855 100644 --- a/openedx/core/djangoapps/catalog/management/commands/cache_programs.py +++ b/openedx/core/djangoapps/catalog/management/commands/cache_programs.py @@ -1,3 +1,5 @@ +""""Management command to add program information to the cache.""" +from collections import defaultdict import logging import sys @@ -211,15 +213,12 @@ class Command(BaseCommand): in the cache not just the course runs in a program. Therefore, a cache miss would be different from a course not in a program. """ - course_runs = {} + course_runs = defaultdict(list) failure = False - for program_uuid, program in programs.items(): + for program in programs.values(): for course in program['courses']: for course_run in course['course_runs']: - course_run_key = course_run['key'] - if course_run_key in course_runs: - course_runs[course_run_key] += program_uuid - else: - course_runs[course_run_key] = [program_uuid] + course_run_cache_key = COURSE_PROGRAMS_CACHE_KEY_TPL.format(course_run_id=course_run['key']) + course_runs[course_run_cache_key].append(program['uuid']) return course_runs, failure diff --git a/openedx/core/djangoapps/catalog/tests/test_utils.py b/openedx/core/djangoapps/catalog/tests/test_utils.py index bc5657d4a4..fb7a481c46 100644 --- a/openedx/core/djangoapps/catalog/tests/test_utils.py +++ b/openedx/core/djangoapps/catalog/tests/test_utils.py @@ -16,6 +16,7 @@ from course_modes.tests.factories import CourseModeFactory from entitlements.tests.factories import CourseEntitlementFactory from openedx.core.constants import COURSE_UNPUBLISHED from openedx.core.djangoapps.catalog.cache import ( + COURSE_PROGRAMS_CACHE_KEY_TPL, PATHWAY_CACHE_KEY_TPL, PROGRAM_CACHE_KEY_TPL, SITE_PATHWAY_IDS_CACHE_KEY_TPL, @@ -183,6 +184,27 @@ class TestGetPrograms(CacheIsolationTestCase): self.assertEqual(actual_program, expected_program) self.assertFalse(mock_warning.called) + def test_get_from_course(self, mock_warning, _mock_info): + expected_program = ProgramFactory() + expected_course = expected_program['courses'][0]['course_runs'][0]['key'] + + self.assertEqual(get_programs(course=expected_course), []) + + cache.set( + COURSE_PROGRAMS_CACHE_KEY_TPL.format(course_run_id=expected_course), + [expected_program['uuid']], + None + ) + cache.set( + PROGRAM_CACHE_KEY_TPL.format(uuid=expected_program['uuid']), + expected_program, + None + ) + + actual_program = get_programs(course=expected_course) + self.assertEqual(actual_program, [expected_program]) + self.assertFalse(mock_warning.called) + @skip_unless_lms @mock.patch(UTILS_MODULE + '.logger.info') diff --git a/openedx/core/djangoapps/catalog/utils.py b/openedx/core/djangoapps/catalog/utils.py index 6e07f41eb9..a1c219f72e 100644 --- a/openedx/core/djangoapps/catalog/utils.py +++ b/openedx/core/djangoapps/catalog/utils.py @@ -107,7 +107,9 @@ def get_programs(site=None, uuid=None, course=None): # pylint: disable=redefine elif course: uuids = cache.get(COURSE_PROGRAMS_CACHE_KEY_TPL.format(course_run_id=course)) if not uuids: - logger.warning(missing_details_msg_tpl.format(course=course)) + # Currently, the cache does not differentiate between a cache miss and a course + # without programs. After this is changed, log any cache misses here. + return [] else: uuids = cache.get(SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=site.domain), []) if not uuids: