messenger.py (6494B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\freelanceprojects\client\contributionmethods\itemdelivery\messenger.py 2 import logging 3 import uuid 4 from eveProto.generated.eve_public.freelance.contributionmethod.itemdelivery.api.notices_pb2 import ContributionSucceededNotice, ContributionFailedNotice 5 from eveProto.generated.eve_public.freelance.contributionmethod.itemdelivery.api.requests_pb2 import DeliverRequest, DeliverResponse, GetStatusRequest, GetStatusResponse 6 from freelanceprojects.client.contributionmethods.itemdelivery.delivery import DeliveryStatus 7 from freelanceprojects.client.contributionmethods.itemdelivery.errors import ItemMissingError, ProjectInactiveError, QuantityTooHighError, NotCommittedError, InvalidStructureError, InvalidItemTypeError, GenericDeliveryError, StatusRequestError 8 from freelanceprojects.client.contributionmethods.itemdelivery.item_delivery_signals import on_contribution_failed_internal, on_contribution_successful_internal, on_contribution_error 9 from freelanceprojects.common.errors import ServiceUnavailableError 10 from six.moves.http_client import OK 11 from stackless_response_router.exceptions import TimeoutException, UnpackException 12 logger = logging.getLogger('freelance_projects') 13 WAIT_UNTIL_STATUS_CHECK = 5 14 15 class DeliveryMessenger(object): 16 17 def __init__(self, public_gateway): 18 self.public_gateway = public_gateway 19 self.public_gateway.subscribe_to_notice(ContributionSucceededNotice, self._on_contribution_successful_notice) 20 self.public_gateway.subscribe_to_notice(ContributionFailedNotice, self._on_contribution_failed_notice) 21 22 def deliver_item(self, project_id, item_id, quantity, flag_id, location_id, location_is_station, item_location_id): 23 request = DeliverRequest() 24 request.project.uuid = project_id.bytes 25 if location_is_station: 26 request.delivery_location.station.sequential = location_id 27 else: 28 request.delivery_location.structure.sequential = location_id 29 request.item.sequential = item_id 30 request.quantity = quantity 31 request.item_location.item.sequential = item_location_id 32 request.item_location.flag.value = flag_id 33 info_log = ' DeliverRequest: \n{request}\n'.format(request=request) 34 status_code, payload = self._send_request(request, response_class=DeliverResponse, info_log=info_log) 35 if payload.HasField('escrowed') and status_code == OK: 36 logger.info(info_log + 'SUCCESS') 37 return uuid.UUID(bytes=payload.escrowed.delivery.uuid) 38 if payload.HasField('delivery_location_not_in_full_power'): 39 self._raise_custom_error(info_log, InvalidStructureError()) 40 elif payload.HasField('item_not_found_at_location'): 41 self._raise_custom_error(info_log, ItemMissingError()) 42 elif payload.HasField('invalid_item_type'): 43 self._raise_custom_error(info_log, InvalidItemTypeError()) 44 elif payload.HasField('quantity_too_high'): 45 if payload.quantity_too_high.HasField('max_remaining_project_contributions'): 46 self._raise_custom_error(info_log, QuantityTooHighError(max_quantity=payload.quantity_too_high.max_remaining_project_contributions)) 47 elif payload.HasField('character_not_committed'): 48 self._raise_custom_error(info_log, NotCommittedError()) 49 elif payload.HasField('project_does_not_allow_item_delivery'): 50 self._raise_custom_error(info_log, ProjectInactiveError()) 51 else: 52 self._raise_custom_error(info_log, GenericDeliveryError(status_code=status_code)) 53 if status_code != OK: 54 on_contribution_error(project_id=project_id) 55 56 def get_status(self, delivery): 57 request = GetStatusRequest() 58 request.delivery.uuid = delivery.delivery_id.bytes 59 info_log = ' GetStatusRequest: \n{request}\n'.format(request=request) 60 status_code, payload = self._send_request(request, response_class=GetStatusResponse, info_log=info_log) 61 if status_code == OK: 62 if payload.HasField('escrowed'): 63 delivery.update_status(DeliveryStatus.ESCROWED) 64 logger.info(info_log + 'SUCCESS \n ' + str(payload)) 65 elif payload.HasField('succeeded'): 66 logger.info(info_log + 'SUCCESS \n ' + str(payload)) 67 delivery.update_status(DeliveryStatus.SUCCESS, quantity_delivered=payload.succeeded.quantity_delivered, quantity_returned=payload.succeeded.quantity_returned) 68 elif payload.HasField('failed'): 69 logger.info(info_log + 'SUCCESS \n ' + str(payload)) 70 delivery.update_status(DeliveryStatus.FAILURE) 71 else: 72 delivery.update_status(DeliveryStatus.UNSPECIFIED) 73 self._raise_custom_error(info_log, StatusRequestError(status_code=status_code)) 74 75 @staticmethod 76 def _on_contribution_successful_notice(payload, _primitive): 77 delivery_id = uuid.UUID(bytes=payload.delivery.uuid) 78 logger.info('on_contribution_successful_internal delivery_id: %s - payload: %s', delivery_id, payload) 79 on_contribution_successful_internal(delivery_id) 80 81 @staticmethod 82 def _on_contribution_failed_notice(payload, _primitive): 83 delivery_id = uuid.UUID(bytes=payload.delivery.uuid) 84 logger.info('on_contribution_failed_internal project: %s - payload: %s', delivery_id, payload) 85 on_contribution_failed_internal(delivery_id) 86 87 def _send_request(self, request, response_class, info_log, timeout_seconds = 10, max_attempts = 1): 88 try: 89 response_primitive, response = self.public_gateway.send_blocking_character_request_and_receive_response(request_payload=request, expected_response_class=response_class, timeout_seconds=timeout_seconds, max_attempts=max_attempts, retry_delay_in_seconds=1) 90 except (TimeoutException, UnpackException) as exc: 91 error_info = 'ERROR: %s' % exc.__class__.__name__ 92 info_log += error_info 93 logger.info(info_log) 94 request_cls = request.__class__.__name__ 95 raise ServiceUnavailableError('%s, Failed to receive response from %s: %s' % (error_info, request_cls, exc)) 96 97 return (response_primitive.status_code, response) 98 99 @staticmethod 100 def _raise_custom_error(info_log, error): 101 info_log += '\nRaising %s' % error.__str__() 102 logger.error(info_log) 103 raise error