NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

notification_state_repository.py (4201B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\store\client\targetaudience\notification_state_repository.py
      2 from __future__ import absolute_import, division, print_function
      3 import logging
      4 from caching.client.storage.disk_storage import BinaryDiskStorage
      5 from imagecaching.client.const import user_cache_folder
      6 from locks import FifoLock, TempLock
      7 from store.client.const import LOG_ENTRY_NAME
      8 from store.client.targetaudience.const import TAO_NOTIFICATION_STATE_FOLDER, TAO_STORAGE_FOLDER
      9 from store.client.targetaudience.feature_flags import tao_enabled
     10 from store.client.targetaudience.notification_state import STATE_DISMISSED, STATE_SEEN, STATE_UNSEEN, states_from_bytes, states_to_bytes
     11 logger = logging.getLogger(__name__)
     12 _instance = None
     13 
     14 def get_notification_state_repository():
     15     global _instance
     16     if not tao_enabled():
     17         logger.info('%s - target audience offers are disabled, returning an empty catalogue', LOG_ENTRY_NAME)
     18         return []
     19     if _instance is None:
     20         _instance = OfferNotificationStateRepository()
     21     return _instance
     22 
     23 
     24 def clear_notification_state_repository():
     25     global _instance
     26     _instance = None
     27 
     28 
     29 def notification_state_content_id(user_id):
     30     return u'%s/%s' % (TAO_STORAGE_FOLDER, user_cache_folder(user_id, TAO_NOTIFICATION_STATE_FOLDER))
     31 
     32 
     33 class OfferNotificationStateRepository(object):
     34 
     35     def __init__(self, storage_factory = None):
     36         self._storage_factory = storage_factory or BinaryDiskStorage
     37         self._storage_by_user = {}
     38         self._states_by_user = {}
     39 
     40     def get_state(self, offer_id):
     41         return self._states(offer_id.user_id).get(_offer_key(offer_id), STATE_UNSEEN)
     42 
     43     def mark_seen(self, offer_id):
     44         self._update(offer_id, _seen_after)
     45 
     46     def mark_dismissed(self, offer_id):
     47         self._update(offer_id, _dismissed_after)
     48 
     49     def _update(self, offer_id, transition):
     50         user_id = offer_id.user_id
     51         offer_key = _offer_key(offer_id)
     52         with TempLock(notification_state_content_id(user_id), FifoLock):
     53             states = self._load(user_id)
     54             self._states_by_user[user_id] = states
     55             current_state = states.get(offer_key, STATE_UNSEEN)
     56             new_state = transition(current_state)
     57             if new_state == current_state:
     58                 return
     59             states[offer_key] = new_state
     60             self._save(user_id, states)
     61 
     62     def _states(self, user_id):
     63         states = self._states_by_user.get(user_id)
     64         if states is not None:
     65             return states
     66         with TempLock(notification_state_content_id(user_id), FifoLock):
     67             states = self._states_by_user.get(user_id)
     68             if states is None:
     69                 states = self._load(user_id)
     70                 self._states_by_user[user_id] = states
     71             return states
     72 
     73     def _load(self, user_id):
     74         try:
     75             payload_bytes = self._storage(user_id).get()
     76         except (OSError, IOError):
     77             logger.exception('%s - could not read the target audience notification state of user %s', LOG_ENTRY_NAME, user_id)
     78             return {}
     79 
     80         try:
     81             return states_from_bytes(payload_bytes)
     82         except Exception:
     83             logger.exception('%s - discarding the unreadable target audience notification state of user %s', LOG_ENTRY_NAME, user_id)
     84             return {}
     85 
     86     def _save(self, user_id, states):
     87         try:
     88             self._storage(user_id).set(states_to_bytes(states))
     89         except (OSError, IOError):
     90             logger.exception('%s - could not persist the target audience notification state of user %s', LOG_ENTRY_NAME, user_id)
     91 
     92     def _storage(self, user_id):
     93         storage = self._storage_by_user.get(user_id)
     94         if storage is None:
     95             storage = self._storage_factory(notification_state_content_id(user_id))
     96             self._storage_by_user[user_id] = storage
     97         return storage
     98 
     99 
    100 def _offer_key(offer_id):
    101     return u'%s' % offer_id.catalogue_entry_name
    102 
    103 
    104 def _seen_after(current_state):
    105     if current_state == STATE_DISMISSED:
    106         return current_state
    107     return STATE_SEEN
    108 
    109 
    110 def _dismissed_after(_current_state):
    111     return STATE_DISMISSED