def register_participant(self, routing_identifier: str) -> None: if not self.__client.is_connected: self._error("NATS.IO CLIENT NOT CONNECTED") return None try: node: str = Configuration.get_instance().node() request: ParticipantJoined = ParticipantJoined( identifier=routing_identifier, node=node) response = self.__client.request( subject="{}/{}".format(ADDRESS_SERVICE, "/register"), payload=request.SerializeToString()) result: Result = Result() result.ParseFromString(response.data) if result.status == Result.Status.SUCCESS: self._info("REGISTERED TO NODE: {} TO NODE: {} \n {}".format( routing_identifier, node, result.message)) elif result.status == Result.Status.SUCCESS: self._error( "FAILED TO REGISTER :{} TO NODE: {} TO NONE: {} \n {}". format(routing_identifier, node, result.message)) except ErrConnectionClosed as e: self._error("Connection closed prematurely. {}", e) return None except ErrTimeout as e: self._error("Timeout occurred when publishing msg :{}".format(e)) return None
async def test_subscription(self): payload = ParticipantPassOver() payload.sender_identifier = "XXXXXX" payload.target_identifier = "YYYYYY" payload.originating_node = "saber-fox" payload.payload = "guniowevw".encode() await self.__client.publish( subject="v1/node/{}/participants/pass-over".format( Configuration.get_instance().node()), payload=payload.SerializeToString())
def migrate() -> None: configuration: Configuration = Configuration.get_instance() click.echo("DATABASE URL: {}\n".format(configuration.database_uri())) click.echo("MIGRATIONS FOLDER: {}\n".format(MIGRATIONS_FOLDER)) handler = SQLMigrationHandler( database_url=configuration.database_uri(), migration_folder=MIGRATIONS_FOLDER ) handler.migrate()
def setUp(self) -> None: configuration: Configuration = Configuration.get_instance(testing=True) self.migration_handler = SQLMigrationHandler( database_url=configuration.database_uri(), migration_folder=MIGRATIONS_FOLDER) self.migration_handler.migrate() self.__debug = True engine = create_engine(configuration.database_uri(), echo=self.__debug) session_factory = sessionmaker(bind=engine) self.session = scoped_session(session_factory) BaseModel.set_session(session=self.session) BaseModel.prepare(engine, reflect=True)
class ParticipantService(LoggerMixin): def __init__(self, configuration: Configuration, command_bus: CommandBus, participant_repository: ParticipantRepository, message_repository: MessageRepository) -> None: self.__configuration = configuration self.__online_participants: Dict[Participant] = {} self.__contact_pairing: Dict[str] = {} self.__route_pairing: Dict[str] = {} self.__command_bus: CommandBus = command_bus self.__participant_repository: ParticipantRepository = participant_repository self.__message_repository: MessageRepository = message_repository def fetch(self, identifier) -> Participant: if identifier != self.__online_participants: self.__fetch_details(identifier=identifier) return self.__online_participants[identifier] @EventListener(subject="v1/node/{}/participants/pass-over".format( Configuration.get_instance().node()), event_type=ParticipantPassOver) def on_external_participant_event(self, event: ParticipantPassOver) -> None: self._info("SENDER : {0}".format(event.sender_identifier)) self._info("TARGET : {0}".format(event.target_identifier)) self._info("ORIGINATING NODE : {0}".format(event.originating_node)) self._info("MARKER : {0}".format(event.marker)) if event.target_identifier in self.__route_pairing: target_identifier = self.__route_pairing[event.target_identifier] self.__command_bus.handle( MessageDispatchCommand( participant_identifier=target_identifier, payload=event.payload, response_type=ResponseType.RECEIVE_DIRECT_MESSAGE)) self.__save_direct_message( sender_identifier=event.sender_identifier, target_identifier=target_identifier, message=event.payload, marker=event.marker) def resolve_contacts(self, content: bytearray) -> bytearray: contact_batch_request = BatchContactMatchRequest() contact_batch_request.ParseFromString(content) resolved_contact_batch = self.__resolve_contacts( contact_batch_request=contact_batch_request) return resolved_contact_batch.SerializeToString() def __resolve_contacts( self, contact_batch_request: BatchContactMatchRequest ) -> BatchContactMatchResponse: response = BatchContactMatchResponse() for contact_request in contact_batch_request.requests: if contact_request.type is ContactRequest.ContactType.EMAIL and \ contact_request.value in self.__contact_pairing: participant: Participant = self.__online_participants[ self.__contact_pairing[contact_request.value]] response.contacts.append( Contact(profile_picture_url=participant.photo_url, nickname=participant.nickname, identifier=participant.routing_identity)) return response def __fetch_details(self, identifier: str) -> None: url: str = "{0}/{1}/{2}".format( self.__configuration.account_service_url(), "/api/v1/account-service/users/details", ) response: requests.Response = requests.get(url=url) if response.status_code is not 200: self._error("FAILED TO FETCH USER: {}".format(response.text)) else: content_map: Dict = response.json() if not self.is_identity_known( participant_identifier=content_map['identifier']): self.create_routing_identity( participant_identifier=content_map['identifier']) routing_identifier = self.fetch_routing_identity( participant_identifier=content_map['identifier']) self.__online_participants[identifier] = Participant( routing_identity=routing_identifier, content_map=response.json()) self.__route_pairing[routing_identifier] = content_map['identity'] self.__contact_pairing[response.json()["email"]] = identifier self._info("ADDED PARTICIPANT ENTRY FOR: {}".format(identifier)) get_client().register_participant( routing_identifier=routing_identifier) def is_identity_known(self, participant_identifier: str) -> bool: return self.__participant_repository.has_identity( participant_identifier=participant_identifier) def fetch_routing_identity(self, participant_identifier: str) -> str: identity: Identity = self.__participant_repository.fetch_identity( participant_identifier=participant_identifier) return identity.routing_identity def create_routing_identity(self, participant_identifier: str) -> None: routing_identifier = str(uuid.uuid4()) self.__participant_repository.create_identity( participant_identifier=participant_identifier, routing_identifier=routing_identifier) def relay_direct_message(self, sender_identifier: str, payload: bytearray) -> None: direct_message = DirectMessage() direct_message.ParseFromString(payload) marker = str(uuid.uuid4()) if direct_message.target_identifier in self.__route_pairing: target_identifier = self.__route_pairing[ direct_message.target_identifier] self.__command_bus.handle( MessageDispatchCommand( participant_identifier=target_identifier, payload=payload, response_type=ResponseType.RECEIVE_DIRECT_MESSAGE)) self.__save_direct_message(sender_identifier=sender_identifier, target_identifier=target_identifier, message=payload, marker=marker) self.__report_delivery_success( sender_identifier=sender_identifier, target_identifier=direct_message.target_identifier, marker=marker) else: node: str = self.__resolve_last_known_node( target_identifier=direct_message.target_identifier) if node is None: self.__report_delivery_failure( sender_identifier=sender_identifier, target_identifier=direct_message.target_identifier, delivery_failed_at=direct_message.sent_at) else: self.__send_direct_message_to_node( node=node, sender_identifier=sender_identifier, target_identifier=direct_message.target_identifier, marker=marker, payload=payload) def save_device_information(self, participant_identifier: str, device_information: DeviceDetails) -> None: self.__participant_repository.add_device( participant_identifier=participant_identifier, device=device_information) def __save_direct_message(self, sender_identifier: str, target_identifier: str, message: bytearray, marker: str) -> None: current_time = datetime.utcnow() self.__message_repository.save(sender=sender_identifier, target=target_identifier, payload=message, marker=marker, received_at=current_time) def __report_delivery_success(self, sender_identifier: str, target_identifier: str, marker: str) -> None: utc_now = datetime.utcnow() current_time = Timestamp() current_time.FromDatetime(utc_now) self.__send_delivery_status(sender_identifier=sender_identifier, target_identifier=target_identifier, message="Successfully delivered message", marker=marker, status=Delivery.State.FAILED, sent_at=current_time) def __report_message_read(self, sender_identifier: str, target_identifier: str, marker: str) -> None: utc_now = datetime.utcnow() current_time = Timestamp() current_time.FromDatetime(utc_now) self.__send_delivery_status(sender_identifier=sender_identifier, target_identifier=target_identifier, message="Successfully delivered message", marker=marker, status=Delivery.State.READ, sent_at=current_time) def __report_delivery_failure(self, sender_identifier: str, target_identifier: str, sender_timestamp: Timestamp) -> None: self.__send_delivery_status(sender_identifier=sender_identifier, target_identifier=target_identifier, message="Failed to deliver the message :(", marker="", status=Delivery.State.FAILED, sent_at=sender_timestamp) def __send_delivery_status(self, sender_identifier: str, target_identifier: str, message: str, marker: str, status: Delivery.State, sender_timestamp: Timestamp) -> None: delivery_note: Delivery = Delivery(message=message, state=status, marker=marker, target_identifier=target_identifier, sent_at=sender_timestamp) self.__command_bus.handle( MessageDispatchCommand( participant_identifier=self.__route_pairing[sender_identifier], payload=delivery_note.SerializeToString(), response_type=ResponseType.DELIVERY_STATE, sent_at=sender_timestamp)) @staticmethod def __resolve_last_known_node(target_identifier: str) -> Optional[str]: client: ParticipantClient = get_client() return client.fetch_last_known_node( target_identifier=target_identifier) @staticmethod def __send_direct_message_to_node(node: str, sender_identifier: str, target_identifier: str, payload: bytearray) -> None: client: ParticipantClient = get_client() passover: ParticipantPassOver = ParticipantPassOver( originating_node=node, sender_identifier=sender_identifier, target_identifier=target_identifier, payload=payload) client.passover_direct_message_to(passover=passover)
def __init__(self): self.__configuration = NATSConfiguration( content_map=Configuration.get_instance().nats_configuration()) self.__client: Client = Client()
# This is a sample Python script. # Press Shift+F10 to execute it or replace it with your code. # Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. # Press the green button in the gutter to run the script. from app.application import Application from app.configuration import Configuration if __name__ == '__main__': application: Application = Application(configuration=Configuration.get_instance()) application.run()
def get_client() -> ParticipantClient: configuration: Configuration = Configuration.get_instance() if configuration.is_in_test_mode(): return FakeParticipantClient.instance() return NATSParticipantClient.instance()
def run() -> falcon.App: application = ServerApplication(configuration=Configuration.get_instance()) return application.run()
def configuration(): return Configuration.get_instance(testing=True)