Example #1
0
    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
Example #2
0
 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())
Example #3
0
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)
Example #6
0
    def __init__(self):

        self.__configuration = NATSConfiguration(
            content_map=Configuration.get_instance().nats_configuration())
        self.__client: Client = Client()
Example #7
0
# 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()


Example #8
0
def get_client() -> ParticipantClient:
    configuration: Configuration = Configuration.get_instance()
    if configuration.is_in_test_mode():
        return FakeParticipantClient.instance()
    return NATSParticipantClient.instance()
Example #9
0
def run() -> falcon.App:
    application = ServerApplication(configuration=Configuration.get_instance())
    return application.run()
 def configuration():
     return Configuration.get_instance(testing=True)