Esempio n. 1
0
    def subscribe(self, sub):
        self.sub_map[sub.inbox] = sub

        sub.inbox_sub = yield from self.nc.subscribe_async(sub.inbox, cb=self._process_msg)

        # Setup STAN sub request
        stan_sub = pb.SubscriptionRequest()
        stan_sub.clientID = self.client_id
        stan_sub.subject = sub.subject
        stan_sub.qGroup = sub.queue_name
        stan_sub.inbox = sub.inbox
        stan_sub.maxInFlight = sub.max_inflight
        stan_sub.ackWaitInSecs = sub.ack_wait
        stan_sub.startPosition = sub.start_position
        stan_sub.durableName = sub.durable_name

        if sub.start_at:
            stan_sub.startTimeDelta = sub.start_at
        elif sub.start_sequence:
            stan_sub.startSequence = sub.start_sequence

        # TODO: Timeout?
        reply = yield from self.nc.timed_request(self.sub_requests, stan_sub.SerializeToString())

        sub_resp = pb.SubscriptionResponse()
        sub_resp.ParseFromString(reply.data)
        if sub_resp.error:
            try:
                yield from self.unsubscribe(sub)
            except NATS.NatsError:
                # Subscription may never have completed so an error that it cannot unsub is ok
                pass
            raise NATS.NatsError("Error subscribing: '{}'".format(sub_resp.error))

        sub.ack_inbox = sub_resp.ackInbox
Esempio n. 2
0
 def _process_ack(self, msg):
     pub_ack = pb.PubAck()
     pub_ack.ParseFromString(msg.data)
     ack = self.pub_ack_map.pop(pub_ack.guid)
     if ack:
         if pub_ack.error:
             raise NATS.NatsError(pub_ack.error)
         if ack.handler and callable(ack.handler):
             if asyncio.iscoroutinefunction(ack.handler):
                 yield from ack.handler(pub_ack.guid)
             else:
                 ack.handler(pub_ack.guid)
Esempio n. 3
0
    def _send_connection_request(self, connect_timeout):
        # Create connect request for streaming service
        connect_req = pb.ConnectRequest()
        connect_req.clientID = self.client_id
        connect_req.heartbeatInbox = self.heart_beat_inbox

        discover_subject = DEFAULT_DISCOVER_PREFIX + "." + self.cluster_id
        # TODO: Add Timeout
        reply = yield from self.nc.timed_request(
            discover_subject, connect_req.SerializeToString(), connect_timeout)

        connect_response = pb.ConnectResponse()
        connect_response.ParseFromString(reply.data)
        if connect_response.error:
            raise NATS.NatsError("Connection error: '{}'".format(
                connect_response.error))

        self.pub_prefix = connect_response.pubPrefix
        self.sub_requests = connect_response.subRequests
        self.unsub_requests = connect_response.unsubRequests
        self.close_requests = connect_response.closeRequests
Esempio n. 4
0
    def unsubscribe(self, sub, close=False):
        yield from self.nc.unsubscribe(sub.inbox_sub)
        del self.sub_map[sub.inbox]

        unsub_req = pb.UnsubscribeRequest()
        unsub_req.clientID = self.client_id
        unsub_req.subject = sub.subject
        unsub_req.inbox = sub.ack_inbox
        if sub.durable_name:
            unsub_req.durableName = sub.durable_name

        req_subject = self.unsub_requests if not close else self.close_requests

        # TODO: Timeout
        reply = yield from self.nc.timed_request(req_subject, unsub_req.SerializeToString())
        unsub_resp = pb.SubscriptionResponse()
        unsub_resp.ParseFromString(reply.data)
        if unsub_resp.error:
            raise NATS.NatsError(
                "Error unsubscribing from {subject}: '{err}'".format(subject=sub.subject, err=unsub_resp.error)
            )
Esempio n. 5
0
    def close(self):
        """
        Shut's down the Stream Client and possibly the NATS Client.
        """
        if not self.nc.is_connected or self.nc.is_closed:
            LOG.warning("NC is already closed!")
            return

        yield from self.nc.unsubscribe(self.ack_subscription)

        close_req = pb.CloseRequest()
        close_req.clientID = self.client_id
        response = yield from self.nc.timed_request(self.close_requests, close_req.SerializeToString())
        close_resp = pb.CloseResponse()
        close_resp.ParseFromString(response.data)
        if close_resp.error:
            if "unknown clientID" not in close_resp.error:
                raise NATS.NatsError(close_resp.error)
        elif self.nc_owned:
            yield from self.nc.flush()
            yield from self.nc.close()