def init_cache(self): """ This function plays the role of the ``cache_programs`` management command. """ all_programs = [ self.masters_program_1, self.masters_program_2, self.bachelors_program, self.no_type_program, self.masters_program_other_site ] cached_programs = { PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in all_programs } cache.set_many(cached_programs, None) programs_by_type = defaultdict(list) programs_by_type_slug = defaultdict(list) for program in all_programs: program_type = normalize_program_type(program.get('type')) program_type_slug = (program.get('type_attrs') or {}).get('slug') site_id = self.site.id if program == self.masters_program_other_site: site_id = self.other_site.id program_type_cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format( site_id=site_id, program_type=program_type) program_type_slug_cache_key = PROGRAMS_BY_TYPE_SLUG_CACHE_KEY_TPL.format( site_id=site_id, program_slug=program_type_slug) programs_by_type[program_type_cache_key].append(program['uuid']) programs_by_type_slug[program_type_slug_cache_key].append( program['uuid']) cache.set_many(programs_by_type, None) cache.set_many(programs_by_type_slug, None)
def get_programs_by_type(self, site, programs): """ Returns a dictionary mapping site-aware cache keys corresponding to program types to lists of program uuids with that type. """ programs_by_type = defaultdict(list) for program in programs.values(): program_type = normalize_program_type(program.get('type')) cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format(site_id=site.id, program_type=program_type) programs_by_type[cache_key].append(program['uuid']) return programs_by_type
def get_programs_by_type(site, program_type): """ Keyword Arguments: site (Site): The corresponding Site object to fetch programs for. program_type (string): The program_type that matching programs must have. Returns: A list of programs for the given site with the given program_type. """ program_type_cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format( site_id=site.id, program_type=normalize_program_type(program_type)) uuids = cache.get(program_type_cache_key, []) if not uuids: logger.warning( str(f'Failed to get program UUIDs from cache for site {site.id} and type {program_type}' )) return get_programs_by_uuids(uuids)
def test_handle_programs(self): """ Verify that the command requests and caches program UUIDs and details. """ # Ideally, this user would be created in the test setup and deleted in # the one test case which covers the case where the user is missing. However, # that deletion causes "OperationalError: no such table: wiki_attachmentrevision" # when run on Jenkins. UserFactory(username=self.catalog_integration.service_username) programs = { PROGRAM_CACHE_KEY_TPL.format(uuid=program['uuid']): program for program in self.programs } self.mock_list() self.mock_pathways(self.pathways) for uuid in self.uuids: program = programs[PROGRAM_CACHE_KEY_TPL.format(uuid=uuid)] self.mock_detail(uuid, program) call_command('cache_programs') cached_uuids = cache.get( SITE_PROGRAM_UUIDS_CACHE_KEY_TPL.format(domain=self.site_domain)) self.assertEqual(set(cached_uuids), set(self.uuids)) program_keys = list(programs.keys()) cached_programs = cache.get_many(program_keys) # Verify that the keys were all cache hits. self.assertEqual(set(cached_programs), set(programs)) # We can't use a set comparison here because these values are dictionaries # and aren't hashable. We've already verified that all programs came out # of the cache above, so all we need to do here is verify the accuracy of # the data itself. for key, program in cached_programs.items(): # cached programs have a pathways field added to them, remove before comparing del program['pathway_ids'] self.assertEqual(program, programs[key]) # the courses in the child program's first curriculum (the active one) # should point to both the child program and the first program # in the cache. for course in self.child_program['curricula'][0]['courses']: for course_run in course['course_runs']: course_run_cache_key = COURSE_PROGRAMS_CACHE_KEY_TPL.format( course_run_id=course_run['key']) self.assertIn(self.programs[0]['uuid'], cache.get(course_run_cache_key)) self.assertIn(self.child_program['uuid'], cache.get(course_run_cache_key)) # for each program, assert that the program's UUID is in a cached list of # program UUIDS by program type and a cached list of UUIDs by authoring organization for program in self.programs: program_type = normalize_program_type(program.get('type', 'None')) program_type_cache_key = PROGRAMS_BY_TYPE_CACHE_KEY_TPL.format( site_id=self.site.id, program_type=program_type) self.assertIn(program['uuid'], cache.get(program_type_cache_key)) for organization in program['authoring_organizations']: organization_cache_key = PROGRAMS_BY_ORGANIZATION_CACHE_KEY_TPL.format( org_key=organization['key']) self.assertIn(program['uuid'], cache.get(organization_cache_key))