def get_publisher_info_by_pk(self, pk): ''' Retrieves information about publisher based on his id in database. :param int pk: publisher's primary key. :rtype: dict :returns: dict with sizes, positions and segments of publisher. ''' cache_val = TargetCache.get_publisher_info(pk) if cache_val is not None: return cache_val # make sure we get representant only try: publisher_tv = self.representants().get(represented__pk=pk) info = { 'sizes': publisher_tv.sizes, 'positions': publisher_tv.positions, 'segments': [seg.appnexus_id for seg in publisher_tv.segments.all()] } TargetCache.set_publisher_info(pk, info) return info except PublisherTargetValue.DoesNotExist: pass
def get_or_create_multi_pk(self, exchange, category, values): """ Get primary key corresponding to exchange, category and value. :param str exchange: exchange code :param str category: target value category :param list values: list of target value hierarchy values :returns: dictionary of values and corresponding primary keys :rtype: dict .. note:: If value does not exists, it will be created! """ cache_values = TargetCache.multi_get_target_pk(exchange, category, values) for value, cache_val in cache_values.iteritems(): if cache_val is not None: continue try: tv, _ = self.get_or_create_representant(category=category, value=value, exchange=exchange, strict=False) TargetCache.set_target_pk(exchange, category, value, tv.pk) cache_values[value] = tv.pk except (InvalidTargetValues, TargetValueQueryError): pass return cache_values
def get_or_create_multi_pk(self, exchange, dimension, values): """ Get primary keys corresponding to exchange, and list of values. :param str exchange: exchange code :param list values: list of target values hierarchy values :returns: dictionary of values and corresponding primary keys :rtype: dict .. note:: If value does not exists, it will be created! """ cache_values = TargetCache.multi_get_publisher_pk(exchange, values) for value, cache_val in cache_values.iteritems(): if cache_val is not None: continue try: publisher_tv, _ = PublisherTargetValue.\ objects.get_or_create_unrepresented( value=value, exchange=exchange, category='publisher', strict=False, ) TargetCache.set_publisher_pk(exchange, value, publisher_tv.pk) cache_values[value] = publisher_tv.pk except (InvalidTargetValues, TargetValueQueryError): pass return cache_values
def get_multi_pk(self, exchange, dimension, values): """ Read primary key from cache, or if not present from database. .. warning:: It's rather impossible to get new segment during system life. To limit the number of database hit, if we won't find it in dimension table, we just set an 0 for it in cache and replace it with None in cache_values instead. We don't set None, since it's the value returned by cache if value isn't set. :param str exchange: exchange code :param str dimension: dimension name :param list values: category values for given exchange :returns: dictionary consisting of values and corresponding primary keys :rtype: dict """ cache_values = TargetCache.multi_get_category_pk(exchange, values) for value, cache_val in cache_values.iteritems(): if cache_val is not None: continue # This models just read primary keys try: category_val = self.get(name=value, exchange=exchange) TargetCache.set_category_pk(exchange, value, category_val.pk) cache_values[value] = category_val.pk except self.model.DoesNotExist: TargetCache.set_category_pk(exchange, value, 0) return cache_values
def publishertargetvalue_clear_info(sender, instance, *args, **kwargs): """ Clear publishers info cache. Should be used in case of save or delete. """ TargetCache.delete_publisher_info(instance.pk)
def publisher_clear_pk(sender, instance, *args, **kwargs): """ Clear publisher pk key. Should be used only when deleting. """ publisher_tv = instance if publisher_tv.exchange: TargetCache.delete_publisher_pk(instance.exchange, instance.value_list)
def targetvalue_clear_pk(sender, instance, *args, **kwargs): """ Clear target value pk key. Should be used only when deleting. """ targetvalue = instance if targetvalue.exchange: TargetCache.delete_target_pk(instance.exchange, instance.category, instance.value_list)
def test_target_cache_multiget(redisdb_targeting_cache, dimension_values, pks): """ Check if multi_get is able to retrieve multiple pks from cache. """ exchange = EXCHANGES.appnexus category = 'region' for param, value in zip(dimension_values, pks): if value: # if None, we won't set it, but we should get None back from cache. TargetCache.set('prefix', exchange, category, param, value) results = TargetCache.multi_get('prefix', [exchange, category], dimension_values) for param, value in zip(dimension_values, pks): assert results[param] == value
def get_multi_pk(self, exchange, dimension, values): """ Read primary keys from cache, or if not present from database. .. note:: segments are returned from appnexus only at the moment. .. warning:: It's rather impossible to get new segment during system life. To limit the number of database hit, if we won't find it in dimension table, we just set an 0 for it in cache and replace it with None in cache_values instead. We don't set None, since it's the value returned by cache if value isn't set. :param str exchange: exchange code :param str dimension: dimension name :param list values: segment values for given exchange :returns: dictionary consisting of values and corresponding primary keys :rtype: dict """ # only appnexus segments are available. if not exchange == 'appnexus': return {} dimension = self.model.DIMENSION cache_values = TargetCache.multi_get_segment_pk( exchange, dimension, values) for value, cache_val in cache_values.iteritems(): if cache_val is not None: continue # This models just read primary keys try: segment_val = self.get(appnexus_id=value) TargetCache.set_segment_pk(exchange, dimension, value, segment_val.pk) cache_values[value] = segment_val.pk except self.model.DoesNotExist: TargetCache.set_segment_pk(exchange, dimension, value, 0) return cache_values
def test_target_cache_disabled(redisdb_targeting_cache): assert settings.targeting_cache_enabled is True TargetCache.tv_cache.client.clear() assert TargetCache.set('AA', 'BB', 'b') is True assert TargetCache.set('AA', 'CC', 'c') is True assert TargetCache.get('AA', 'CC') == 'c' assert TargetCache.multi_get('AA', '', ['BB', 'CC']) == { 'BB': 'b', 'CC': 'c' } settings.targeting_cache_enabled = False assert TargetCache.get('AA', 'CC') is None assert TargetCache.multi_get('AA', '', ['BB', 'CC']) == { 'BB': None, 'CC': None } assert TargetCache.set('AA', 'DD', 'd') is None # Should be ignored. settings.targeting_cache_enabled = True assert TargetCache.get( 'AA', 'DD') is None # Saving keys to disabled cache should have no effect. # Values saved before switching the cache off should remain intact: assert TargetCache.multi_get('AA', '', ['BB', 'CC']) == { 'BB': 'b', 'CC': 'c' } # After re-enabling, the cache should function: assert TargetCache.set('AA', 'EE', 'e') is True assert TargetCache.get('AA', 'EE') == 'e'
def test_target_cache_for_unicode_values(redisdb_targeting_cache, params, value): TargetCache.set_target_pk(*params + [value]) assert TargetCache.get_target_pk(*params) == value