Exemplo n.º 1
0
    def timed_request(self, subject, payload, timeout=0.5):
        """
        Implements the request/response pattern via pub/sub
        using an ephemeral subscription which will be published
        with a limited interest of 1 reply returning the response
        or raising a Timeout error.

          ->> SUB _INBOX.2007314fe0fcb2cdc2a2914c1 90
          ->> UNSUB 90 1
          ->> PUB hello _INBOX.2007314fe0fcb2cdc2a2914c1 5
          ->> MSG_PAYLOAD: world
          <<- MSG hello 2 _INBOX.2007314fe0fcb2cdc2a2914c1 5

        """
        inbox = new_inbox()
        future = asyncio.Future(loop=self._loop)
        sid = yield from self.subscribe(inbox, future=future, max_msgs=1)
        yield from self.auto_unsubscribe(sid, 1)
        yield from self.publish_request(subject, inbox, payload)

        try:
            msg = yield from asyncio.wait_for(future, timeout, loop=self._loop)
            return msg
        except asyncio.TimeoutError:
            future.cancel()
            raise ErrTimeout
Exemplo n.º 2
0
 def __init__(self, nats_client: Client, subject: str, inbox=''):
     super().__init__(request_size_limit=_NATS_MAX_MESSAGE_SIZE)
     self._nats_client = nats_client
     self._subject = subject
     self._inbox = inbox or new_inbox()
     self._is_open = False
     self._sub_id = None
Exemplo n.º 3
0
 def _sub_to_heartbeat(self):
     # Setup the heartbeat inbox
     self.heart_beat_inbox = new_inbox()
     self.heart_beat_sub = yield from self.nc.subscribe(
         self.heart_beat_inbox, cb=self._process_heartbeat,
         is_async=True
     )
Exemplo n.º 4
0
    def timed_request(self, subject, payload, timeout=0.5):
        """
        Implements the request/response pattern via pub/sub
        using an ephemeral subscription which will be published
        with a limited interest of 1 reply returning the response
        or raising a Timeout error.

          ->> SUB _INBOX.2007314fe0fcb2cdc2a2914c1 90
          ->> UNSUB 90 1
          ->> PUB hello _INBOX.2007314fe0fcb2cdc2a2914c1 5
          ->> MSG_PAYLOAD: world
          <<- MSG hello 2 _INBOX.2007314fe0fcb2cdc2a2914c1 5

        """
        inbox = new_inbox()
        future = asyncio.Future(loop=self._loop)
        sid = yield from self.subscribe(inbox, future=future, max_msgs=1)
        yield from self.auto_unsubscribe(sid, 1)
        yield from self.publish_request(subject, inbox, payload)

        try:
            msg = yield from asyncio.wait_for(future, timeout, loop=self._loop)
            return msg
        except asyncio.TimeoutError:
            future.cancel()
            raise ErrTimeout
async def example():

    # [begin subscribe_w_reply]
    nc = NATS()

    await nc.connect(servers=["nats://demo.nats.io:4222"])

    future = asyncio.Future()

    async def cb(msg):
        nonlocal future
        future.set_result(msg)

    await nc.subscribe("time", cb=cb)

    await nc.publish_request("time", new_inbox(), b'What is the time?')
    await nc.flush()

    # Read the message
    msg = await asyncio.wait_for(future, 1)

    # Send the time
    time_as_bytes = "{}".format(datetime.now()).encode()
    await nc.publish(msg.reply, time_as_bytes)

    # [end subscribe_w_reply]

    await nc.close()
Exemplo n.º 6
0
    def __init__(
        self,
        sc,
        subject,
        message_cb,
        queue_name='',
        durable_name='',
        max_inflight=DEFAULT_MAX_INFLIGHT,
        ack_wait=DEFAULT_ACK_WAIT,
        start_position=NEW_ONLY,
        start_sequence=None,
        start_time=None,
        manual_acks=False,
    ):
        """
        A nice little wrapper around subscribing.

        :type sc StreamClient
        :type subject basestring
        :type message_cb callable(msg: Msg)
        :type queue_name basestring
        :type max_inflight int
        :type ack_wait: int
        :type start_position: int
        :type start_sequence: int
        :type start_time datetime.datetime
        :type manual_acks bool
        """

        self.sc = sc
        self.subject = subject
        self.queue_name = queue_name
        self.message_cb = message_cb

        self.durable_name = durable_name
        self.max_inflight = max_inflight
        self.ack_wait = ack_wait

        self.start_position = start_position
        self.start_sequence = start_sequence  # sequence to start at
        self.start_time = start_time  # datetime to start at
        self.start_at = None

        if start_time and start_sequence:
            raise NATS.ErrBadSubscription(
                "Cannot start at sequence and time! Pick either time or sequence."
            )
        if start_time:
            self.start_at = pb.TimeDeltaStart()
            self.start_at = int(
                (time.time() - self.start_time.timestamp()) / 1e-9)  # nano?

        self.manual_acks = manual_acks

        self.inbox = new_inbox()
        self.inbox_sub = None
        self.ack_inbox = None
Exemplo n.º 7
0
    def request(self, subject, payload, expected=1, cb=None):
        """
        Implements the request/response pattern via pub/sub
        using an ephemeral subscription which will be published
        with customizable limited interest.

          ->> SUB _INBOX.2007314fe0fcb2cdc2a2914c1 90
          ->> UNSUB 90 1
          ->> PUB hello _INBOX.2007314fe0fcb2cdc2a2914c1 5
          ->> MSG_PAYLOAD: world
          <<- MSG hello 2 _INBOX.2007314fe0fcb2cdc2a2914c1 5

        """
        inbox = new_inbox()
        sid = yield from self.subscribe(inbox, cb=cb)
        yield from self.auto_unsubscribe(sid, expected)
        yield from self.publish_request(subject, inbox, payload)
        return sid
Exemplo n.º 8
0
    def request(self, subject, payload, expected=1, cb=None):
        """
        Implements the request/response pattern via pub/sub
        using an ephemeral subscription which will be published
        with customizable limited interest.

          ->> SUB _INBOX.2007314fe0fcb2cdc2a2914c1 90
          ->> UNSUB 90 1
          ->> PUB hello _INBOX.2007314fe0fcb2cdc2a2914c1 5
          ->> MSG_PAYLOAD: world
          <<- MSG hello 2 _INBOX.2007314fe0fcb2cdc2a2914c1 5

        """
        inbox = new_inbox()
        sid = yield from self.subscribe(inbox, cb=cb)
        yield from self.auto_unsubscribe(sid, expected)
        yield from self.publish_request(subject, inbox, payload)
        return sid
Exemplo n.º 9
0
async def example():

    # [begin publish_with_reply]
    nc = NATS()

    future = asyncio.Future()

    async def sub(msg):
        nonlocal future
        future.set_result(msg)

    await nc.connect(servers=["nats://demo.nats.io:4222"])
    await nc.subscribe("time", cb=sub)

    unique_reply_to = new_inbox()
    await nc.publish_request("time", unique_reply_to, b'')

    # Use the response
    msg = await asyncio.wait_for(future, 1)
    print("Reply:", msg)

    # [end publish_with_reply]

    await nc.close()
Exemplo n.º 10
0
 def tests_generate_new_inbox(self):
     inbox = new_inbox()
     self.assertTrue(inbox.startswith(INBOX_PREFIX))
     min_expected_len = len(INBOX_PREFIX)
     self.assertTrue(len(inbox) > min_expected_len)
    def __init__(self, my_args=None, connection_args=None):
        """
        NATS requester constructor
        :param my_args: dict like {connection, request_q}
        :param connection_args: dict like {user, password, host[, port, client_properties]}
        :return: self
        """
        LOGGER.debug("natsd.Requester.__init__")
        if my_args is None:
            raise exceptions.ArianeConfError("requestor arguments")
        if 'request_q' not in my_args or my_args['request_q'] is None or not my_args['request_q']:
            raise exceptions.ArianeConfError("request_q")
        if 'fire_and_forget' not in my_args or my_args['fire_and_forget'] is None or not my_args['fire_and_forget']:
            self.fire_and_forget = False
        else:
            self.fire_and_forget = True
        if 'rpc_timeout' not in connection_args or connection_args['rpc_timeout'] is None or \
                not connection_args['rpc_timeout']:
            # default timeout = no timeout
            self.rpc_timeout = 0
        else:
            self.rpc_timeout = connection_args['rpc_timeout']

        if 'rpc_timeout_err_count_max' not in connection_args or connection_args['rpc_timeout_err_count_max'] is None \
                or not connection_args['rpc_timeout_err_count_max']:
            self.rpc_retry_timeout_err_count_max = 3
        else:
            self.rpc_retry_timeout_err_count_max = connection_args['rpc_timeout_err_count_max']
        self.rpc_retry_timeout_err_count = 0

        if 'rpc_retry' not in connection_args or connection_args['rpc_retry'] is None or \
                not connection_args['rpc_retry']:
            # default retry = no retry
            self.rpc_retry = 0
        else:
            self.rpc_retry = connection_args['rpc_retry']

        Driver.validate_driver_conf(connection_args)

        super(Requester, self).__init__()
        self.connection_args = copy.deepcopy(connection_args)
        self.servers = [
            "nats://" + connection_args['user'] + ":" + connection_args['password'] + "@" +
            connection_args['host']+":"+str(connection_args['port'])
        ]
        self.name = self.connection_args['client_properties']['ariane.app'] + "@" + socket.gethostname() + \
            " - requestor on " + my_args['request_q']
        self.loop = None
        self.options = None
        self.service = None
        self.nc = Client()
        self.requestQ = my_args['request_q']
        self.responseQ = None
        self.responseQS = None
        self.response = None
        self.split_responses = None
        self.split_responses_mid = None
        self.is_started = False
        self.trace = False
        self.max_payload = 0

        if not self.fire_and_forget:
            self.responseQ = new_inbox()
            self.response = None
            self.corr_id = None
Exemplo n.º 12
0
 def tests_generate_new_inbox(self):
   inbox = new_inbox()
   self.assertTrue(inbox.startswith(INBOX_PREFIX))
   min_expected_len = len(INBOX_PREFIX)
   self.assertTrue(len(inbox) > min_expected_len)