shipSkinComponentTradingSvc.py (5669B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\cosmetics\client\shipSkinComponentTradingSvc.py 2 import log 3 import logging 4 from collections import defaultdict 5 import uthread2 6 from cosmetics.client.messengers.cosmetics.ship.shipSkinComponentTradingRequestMessenger import PublicShipComponentTradingRequestMessenger 7 from cosmetics.client.shipCosmeticTransactionSvc import get_ship_cosmetic_transaction_svc 8 from cosmetics.client.shipSkinComponentSvc import get_ship_skin_component_svc 9 from cosmetics.client.ships.ship_skin_signals import on_component_listing_cache_invalidated, on_ship_skin_component_hub_offers_version_changed 10 from cosmetics.client.ships.skins.errors import ListingError 11 from cosmetics.common.ships.skins.static_data.component import ComponentsDataLoader 12 from stackless_response_router.exceptions import TimeoutException 13 from cosmetics.client.ships.feature_flag import ship_skin_component_hub_offers_version 14 logger = logging.getLogger(__name__) 15 _POPULATE_CACHE_TIMEOUT_IN_SECONDS = 5 16 _POPULATE_CACHE_INCREMENT_IN_SECONDS = 0.1 17 _instance = None 18 19 def get_ship_skin_component_trading_svc(): 20 global _instance 21 if _instance is None: 22 _instance = _ShipSkinComponentTradingSvc() 23 return _instance 24 25 26 class _ShipSkinComponentTradingSvc(object): 27 __startupdependencies__ = ['publicGatewaySvc'] 28 __notifyevents__ = ['OnSessionChanged'] 29 30 def __init__(self): 31 self._fetching = False 32 ComponentsDataLoader.get_components_data() 33 self._component_listing_by_id = {} 34 self._component_listings_by_category = defaultdict(list) 35 public_gateway = sm.GetService('publicGatewaySvc') 36 self._request_messenger = PublicShipComponentTradingRequestMessenger(public_gateway) 37 self._notice_messenger = None 38 ship_skin_component_hub_offers_version() 39 self._connect_signals() 40 41 def __del__(self): 42 self._disconnect_signals() 43 44 def _connect_signals(self): 45 on_ship_skin_component_hub_offers_version_changed.connect(self._on_ship_skin_component_hub_offers_version_changed) 46 sm.RegisterNotify(self) 47 48 def _disconnect_signals(self): 49 on_ship_skin_component_hub_offers_version_changed.disconnect(self._on_ship_skin_component_hub_offers_version_changed) 50 sm.UnregisterNotify(self) 51 52 def OnSessionChanged(self, _isRemote, _sess, change): 53 if 'charid' in change: 54 self._clear_cache() 55 56 def _clear_cache(self): 57 self._component_listing_by_id = {} 58 self._component_listings_by_category = defaultdict(list) 59 self._fetching = False 60 on_component_listing_cache_invalidated() 61 62 def _populate_cache(self): 63 if self._fetching: 64 logger.info('SKIN COMPONENT TRADING - cache is already being populated, waiting for results') 65 timeout = 0 66 while self._fetching: 67 if timeout >= _POPULATE_CACHE_TIMEOUT_IN_SECONDS: 68 raise TimeoutException 69 timeout += _POPULATE_CACHE_INCREMENT_IN_SECONDS 70 uthread2.Sleep(_POPULATE_CACHE_INCREMENT_IN_SECONDS) 71 72 return 73 try: 74 self._fetching = True 75 self._component_listing_by_id = {} 76 self._component_listings_by_category = defaultdict(list) 77 entries = self._request_messenger.get_all_listings_request() 78 for listing_id, listing_data in entries.iteritems(): 79 component_data = listing_data.get_component_data() 80 if component_data is None: 81 logger.warning('could not find component data for listing id %s, skipping', listing_id) 82 continue 83 category_id = component_data.category 84 self._component_listing_by_id[listing_id] = listing_data 85 self._component_listings_by_category[category_id].append(listing_data) 86 87 finally: 88 self._fetching = False 89 90 def _on_ship_skin_component_hub_offers_version_changed(self, *args): 91 logger.info('SKIN COMPONENT TRADING - skin component hub offers version changed, clearing cache') 92 self._clear_cache() 93 94 def get_all_listings(self, force_refresh = True): 95 self._check_populate_cache(force_refresh) 96 return self._component_listing_by_id.values() 97 98 def get_component_listings(self, component_id): 99 listings = self.get_all_listings() 100 return [ l for l in listings if l.component_id == component_id ] 101 102 def _check_populate_cache(self, force_refresh = False): 103 if len(self._component_listing_by_id) == 0 or force_refresh: 104 self._populate_cache() 105 106 def get_category_listings(self, category, force_refresh = False): 107 self._check_populate_cache(force_refresh) 108 return self._component_listings_by_category[category] 109 110 def purchase_listing(self, listing, quantity = 1, immediately_activate = False): 111 self._check_populate_cache() 112 transaction_id, error = self._request_messenger.initiate_purchase_listing_request(listing.identifier, quantity, immediately_activate) 113 if error is not None: 114 return error 115 try: 116 transaction_result = get_ship_cosmetic_transaction_svc().process_transaction(transaction_id) 117 if transaction_result: 118 if immediately_activate: 119 get_ship_skin_component_svc().clear_cache([listing.component_id]) 120 return 121 return ListingError.UNKNOWN 122 except TimeoutException as e: 123 logger.warning('transaction timed out for listing %s purchase' % listing.identifier) 124 raise e