Example #1
0
    def send(self,
             msg: HorseMessage,
             additional_headers: List[MessageHeader] = None) -> HorseResult:
        """
        Sends a raw message to server. Returns true if all data sent over network.
        :param msg: Sending message
        :param additional_headers: Additional message headers
        :return: Successful if the message sent over network. Otherwise returns failed.
        """

        try:
            writer = ProtocolWriter()
            if msg.source_len == 0:
                msg.source = self.id

            if not msg.message_id:
                msg.message_id = unique_generator.create()

            bytes = writer.write(msg, additional_headers)
            self.__socket.sendall(bytes.getbuffer())
            result = HorseResult()
            result.code = ResultCode.Ok
            return result
        except:
            self.disconnect()
            result = HorseResult()
            result.code = ResultCode.Failed
            return result
Example #2
0
    async def leave(self, channel: str, wait_ack: bool = False) -> HorseResult:
        """
        Leavess from a channel
        :param channel: Channel name
        :param wait_ack: If true, waits for acknowledge from server
        :return: If waits for ack, ack result. Otherview Ok if message is sent successfuly
        """

        msg = HorseMessage()
        msg.type = MessageType.Server
        msg.content_type = KnownContentTypes.LEAVE.value
        msg.target = channel
        msg.pending_response = wait_ack

        result: HorseResult
        if wait_ack:
            msg.message_id = unique_generator.create()
            result = await self.request(msg)
        else:
            result = self.send(msg)

        # remove channel from joined channel list
        if result.code == ResultCode.Ok:
            self.__joined_channels.remove(channel)

        return result
Example #3
0
    async def join(self, channel: str, wait_ack: bool = False) -> HorseResult:
        """
        Joins to a channel
        :param channel: Channel name
        :param wait_ack: If true, waits for acknowledge from server
        :return: If waits for ack, ack result. Otherview Ok if message is sent successfuly
        """

        msg = HorseMessage()
        msg.type = MessageType.Server
        msg.content_type = KnownContentTypes.JOIN.value
        msg.target = channel
        msg.pending_response = wait_ack

        result: HorseResult
        if wait_ack:
            msg.message_id = unique_generator.create()
            result = await self.request(msg)
        else:
            result = self.send(msg)

        # add channel to joined list (if not already added)
        if result.code == ResultCode.Ok:
            has = next((x for x in self.__joined_channels if x == channel),
                       None)
            if not has:
                self.__joined_channels.append(channel)

        return result
Example #4
0
    async def send_get_ack(
        self,
        msg: HorseMessage,
        additional_headers: List[MessageHeader] = None
    ) -> HorseResult:  # Awaitable[HorseResult]:
        """
        Sends a message and waits for acknowledge
        :param msg: Sending message
        :param additional_headers: Additional message headers
        :return: Returns a result after acknowledge received or timed out
        """

        future: asyncio.Future = None
        try:
            writer = ProtocolWriter()
            if msg.source_len == 0:
                msg.source = self.id

            if not msg.message_id:
                msg.message_id = unique_generator.create()

            msg.pending_response = False
            if not msg.pending_acknowledge:
                msg.pending_acknowledge = True

            tracking = await self.__tracker.track(msg, self.ack_timeout)
            bytes = writer.write(msg, additional_headers)
            self.__socket.sendall(bytes.getbuffer())

            while not tracking.future.done():
                time.sleep(0.001)

            resp: HorseMessage = await tracking.future
            result = HorseResult()
            if resp is None:
                result.code = ResultCode.RequestTimeout
                result.reason = "timeout"
            else:
                nack_value = resp.get_header(
                    HorseHeaders.NEGATIVE_ACKNOWLEDGE_REASON)
                if nack_value is None:
                    result.code = ResultCode.Ok
                    result.reason = ""
                else:
                    result.code = ResultCode.Failed
                    result.reason = nack_value

            return result

        except:
            self.disconnect()
            if future is not None:
                await self.__tracker.forget(msg)

            result = HorseResult()
            result.code = ResultCode.SendError
            result.reason = ""
            return result
Example #5
0
    async def pull(
            self, request: PullRequest,
            each_msg_func: Callable[[int, HorseMessage],
                                    None]) -> PullContainer:

        msg = HorseMessage()
        msg.type = MessageType.QueuePullRequest
        msg.message_id = unique_generator.create()
        msg.target = request.channel
        msg.content_type = request.queue_id

        msg.add_header(HorseHeaders.COUNT, str(request.count))

        if request.clear_after == ClearDecision.AllMessages.value:
            msg.add_header(HorseHeaders.CLEAR, "all")
        elif request.clear_after == ClearDecision.PriorityMessages.value:
            msg.add_header(HorseHeaders.CLEAR, "High-Priority")
        elif request.clear_after == ClearDecision.Messages.value:
            msg.add_header(HorseHeaders.CLEAR, "Default-Priority")

        if request.get_counts:
            msg.add_header(HorseHeaders.INFO, "yes")

        if request.order == MessageOrder.LIFO.value:
            msg.add_header(HorseHeaders.ORDER, HorseHeaders.LIFO)

        if request.request_headers:
            for header in request.request_headers:
                msg.add_header(header.key, header.value)

        container = PullContainer()
        container.request_id = msg.message_id
        container.request_count = request.count
        container.received_count = 0
        container.status = PullProcess.Receiving
        container.messages = []
        container.each_msg_func = each_msg_func
        container.last_received = datetime.utcnow()
        container.future = asyncio.Future()

        self.__pull_containers[msg.message_id] = container

        send_result = self.send(msg)
        if send_result.code != ResultCode.Ok:
            self.__pull_containers.pop(msg.message_id)
            return container

        while not container.future.done():
            time.sleep(0.001)
            diff = datetime.utcnow() - container.last_received
            if diff > self.request_timeout:
                self.__pull_containers.pop(msg.message_id)
                container.future.set_result(None)
                break

        await container.future
        return container
Example #6
0
 def __init__(self):
     self.id = unique_generator.create()
     self.__tracker = MessageTracker()
     self.__tracker.run()