def POST(self): """ Creates an async task to regenerate content applicability data for given updated repositories. body {repo_criteria:<dict>} """ body = self.params() repo_criteria = body.get('repo_criteria', None) if repo_criteria is None: raise exceptions.MissingValue('repo_criteria') try: repo_criteria = Criteria.from_client_input(repo_criteria) except: raise exceptions.InvalidValue('repo_criteria') manager = manager_factory.applicability_regeneration_manager() regeneration_tag = action_tag('applicability_regeneration') call_request = CallRequest(manager.regenerate_applicability_for_repos, [repo_criteria], tags = [regeneration_tag]) # allow only one applicability regeneration task at a time call_request.updates_resource(dispatch_constants.RESOURCE_REPOSITORY_PROFILE_APPLICABILITY_TYPE, dispatch_constants.RESOURCE_ANY_ID) return execution.execute_async(self, call_request)
def regenerate_applicability_for_consumers(consumer_criteria): """ Regenerate and save applicability data for given updated consumers. :param consumer_criteria: The consumer selection criteria :type consumer_criteria: dict """ consumer_criteria = Criteria.from_dict(consumer_criteria) consumer_query_manager = managers.consumer_query_manager() bind_manager = managers.consumer_bind_manager() consumer_profile_manager = managers.consumer_profile_manager() # Process consumer_criteria and get all the consumer ids satisfied by the criteria consumer_criteria.fields = ['id'] consumer_ids = [c['id'] for c in consumer_query_manager.find_by_criteria(consumer_criteria)] # Following logic of checking existing applicability and getting required data # to generate applicability is a bit more complicated than what it could be 'by design'. # It is to optimize the number of db queries and improving applicability generation # performance. Please consider the implications for applicability generation time # when making any modifications to this code. # Get all unit profiles associated with given consumers unit_profile_criteria = Criteria( filters={'consumer_id': {'$in': consumer_ids}}, fields=['consumer_id', 'profile_hash', 'content_type', 'id']) all_unit_profiles = consumer_profile_manager.find_by_criteria(unit_profile_criteria) # Create a consumer-profile map with consumer id as the key and list of tuples # with profile details as the value consumer_unit_profiles_map = {} # Also create a map of profile_id keyed by profile_hash for profile lookup. profile_hash_profile_id_map = {} for unit_profile in all_unit_profiles: profile_hash = unit_profile['profile_hash'] content_type = unit_profile['content_type'] consumer_id = unit_profile['consumer_id'] profile_id = unit_profile['id'] profile_tuple = (profile_hash, content_type) # Add this tuple to the list of profile tuples for a consumer consumer_unit_profiles_map.setdefault(consumer_id, []).append(profile_tuple) # We need just one profile_id per profile_hash to be used in regenerate_applicability # method to get the actual profile corresponding to given profile_hash. if profile_hash not in profile_hash_profile_id_map: profile_hash_profile_id_map[profile_hash] = profile_id # Get all repos bound to given consumers bind_criteria = Criteria(filters={'consumer_id': {'$in': consumer_ids}}, fields=['repo_id', 'consumer_id']) all_repo_bindings = bind_manager.find_by_criteria(bind_criteria) # Create a repo-consumer map with repo_id as the key and consumer_id list as the value repo_consumers_map = {} for binding in all_repo_bindings: repo_consumers_map.setdefault(binding['repo_id'], []).append(binding['consumer_id']) # Create a set of (repo_id, (profile_hash, content_type)) repo_profile_hashes = set() for repo_id, consumer_id_list in repo_consumers_map.items(): for consumer_id in consumer_id_list: if consumer_id in consumer_unit_profiles_map: for unit_profile_tuple in consumer_unit_profiles_map[consumer_id]: repo_profile_hashes.add((repo_id, unit_profile_tuple)) # Iterate through each tuple in repo_profile_hashes set and regenerate applicability, # if it doesn't exist. These are all guaranteed to be unique tuples because of the logic # used to create maps and sets above, eliminating multiple unnecessary queries # to check for existing applicability for same profiles. manager = managers.applicability_regeneration_manager() for repo_id, (profile_hash, content_type) in repo_profile_hashes: # Check if applicability for given profile_hash and repo_id already exists if ApplicabilityRegenerationManager._is_existing_applicability(repo_id, profile_hash): continue # If applicability does not exist, generate applicability data for given profile # and repo id. profile_id = profile_hash_profile_id_map[profile_hash] manager.regenerate_applicability(profile_hash, content_type, profile_id, repo_id)
def regenerate_applicability_for_consumers(consumer_criteria): """ Regenerate and save applicability data for given updated consumers. :param consumer_criteria: The consumer selection criteria :type consumer_criteria: dict """ consumer_criteria = Criteria.from_dict(consumer_criteria) consumer_query_manager = managers.consumer_query_manager() bind_manager = managers.consumer_bind_manager() consumer_profile_manager = managers.consumer_profile_manager() # Process consumer_criteria and get all the consumer ids satisfied by the criteria consumer_criteria.fields = ['id'] consumer_ids = [ c['id'] for c in consumer_query_manager.find_by_criteria(consumer_criteria) ] # Following logic of checking existing applicability and getting required data # to generate applicability is a bit more complicated than what it could be 'by design'. # It is to optimize the number of db queries and improving applicability generation # performance. Please consider the implications for applicability generation time # when making any modifications to this code. # Get all unit profiles associated with given consumers unit_profile_criteria = Criteria( filters={'consumer_id': { '$in': consumer_ids }}, fields=['consumer_id', 'profile_hash', 'content_type', 'id']) all_unit_profiles = consumer_profile_manager.find_by_criteria( unit_profile_criteria) # Create a consumer-profile map with consumer id as the key and list of tuples # with profile details as the value consumer_unit_profiles_map = {} # Also create a map of profile_id keyed by profile_hash for profile lookup. profile_hash_profile_id_map = {} for unit_profile in all_unit_profiles: profile_hash = unit_profile['profile_hash'] content_type = unit_profile['content_type'] consumer_id = unit_profile['consumer_id'] profile_id = unit_profile['id'] profile_tuple = (profile_hash, content_type) # Add this tuple to the list of profile tuples for a consumer consumer_unit_profiles_map.setdefault(consumer_id, []).append(profile_tuple) # We need just one profile_id per profile_hash to be used in regenerate_applicability # method to get the actual profile corresponding to given profile_hash. if profile_hash not in profile_hash_profile_id_map: profile_hash_profile_id_map[profile_hash] = profile_id # Get all repos bound to given consumers bind_criteria = Criteria( filters={'consumer_id': { '$in': consumer_ids }}, fields=['repo_id', 'consumer_id']) all_repo_bindings = bind_manager.find_by_criteria(bind_criteria) # Create a repo-consumer map with repo_id as the key and consumer_id list as the value repo_consumers_map = {} for binding in all_repo_bindings: repo_consumers_map.setdefault(binding['repo_id'], []).append(binding['consumer_id']) # Create a set of (repo_id, (profile_hash, content_type)) repo_profile_hashes = set() for repo_id, consumer_id_list in repo_consumers_map.items(): for consumer_id in consumer_id_list: if consumer_id in consumer_unit_profiles_map: for unit_profile_tuple in consumer_unit_profiles_map[ consumer_id]: repo_profile_hashes.add((repo_id, unit_profile_tuple)) # Iterate through each tuple in repo_profile_hashes set and regenerate applicability, # if it doesn't exist. These are all guaranteed to be unique tuples because of the logic # used to create maps and sets above, eliminating multiple unnecessary queries # to check for existing applicability for same profiles. manager = managers.applicability_regeneration_manager() for repo_id, (profile_hash, content_type) in repo_profile_hashes: # Check if applicability for given profile_hash and repo_id already exists if ApplicabilityRegenerationManager._is_existing_applicability( repo_id, profile_hash): continue # If applicability does not exist, generate applicability data for given profile # and repo id. profile_id = profile_hash_profile_id_map[profile_hash] manager.regenerate_applicability(profile_hash, content_type, profile_id, repo_id)