Пример #1
0
    def _new_transport(self, ch_number=None):
        """
        Creates a new AMQPTransport with an underlying Pika channel.
        """
        amq_chan = blocking_cb(self.client.channel,
                               'on_open_callback',
                               channel_number=ch_number)
        if amq_chan is None:
            log.error(
                "AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s",
                ch_number)
            from pyon.container.cc import Container
            if Container.instance is not None:
                Container.instance.fail_fast(
                    "AMQCHAN IS NONE, messaging has failed", True)
            raise StandardError(
                "AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s"
                % ch_number)

        transport = AMQPTransport(amq_chan)

        # return the pending in collection (lets this number be assigned again later)
        self.client._pending.remove(transport.channel_number)

        # by default, everything should have a prefetch count of 1 (configurable)
        # this can be overridden by the channel get_n related methods
        transport.qos_impl(prefetch_count=CFG.get_safe(
            'container.messaging.endpoint.prefetch_count', 1))

        return transport
Пример #2
0
    def test__on_underlying_close_error(self, mocklog):
        tp = AMQPTransport(Mock())

        tp._on_underlying_close(404, sentinel.text)

        self.assertEquals(mocklog.error.call_count, 1)
        self.assertIn(sentinel.text, mocklog.error.call_args[0])
        self.assertEquals(mocklog.debug.call_count, 0)
Пример #3
0
    def test__sync_call_with_kwarg_rets(self):
        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam(sup=sentinel.val, sup2=sentinel.val2)

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertEquals(rv, {'sup': sentinel.val, 'sup2': sentinel.val2})
Пример #4
0
    def test__on_underlying_close_error(self, mocklog):
        tp = AMQPTransport(Mock())

        tp._on_underlying_close(404, sentinel.text)

        self.assertEquals(mocklog.error.call_count, 1)
        self.assertIn(sentinel.text, mocklog.error.call_args[0])
        self.assertEquals(mocklog.debug.call_count, 0)
Пример #5
0
    def test__sync_call_with_ret_value(self):
        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam(sentinel.val)

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertEquals(rv, sentinel.val)
Пример #6
0
    def test_close_while_locked(self):
        tp = AMQPTransport(Mock())
        tp.lock = True

        tp.close()

        self.assertEquals(tp._client.close.call_count, 0)
        self.assertEquals(tp._client.callbacks.remove.call_count, 0)
Пример #7
0
    def test__sync_call_with_mult_rets(self):
        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam(sentinel.val, sentinel.val2)

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertEquals(rv, (sentinel.val, sentinel.val2))
Пример #8
0
    def test__sync_call_with_normal_and_kwarg_rets(self):
        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam(sentinel.arg, sup=sentinel.val, sup2=sentinel.val2)

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertEquals(rv, (sentinel.arg, {'sup':sentinel.val, 'sup2':sentinel.val2}))
Пример #9
0
    def test__sync_call_no_ret_value(self):
        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam()

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertIsNone(rv)
Пример #10
0
    def test_close_while_locked(self):
        tp = AMQPTransport(Mock())
        tp.lock = True

        tp.close()

        self.assertEquals(tp._client.close.call_count, 0)
        self.assertEquals(tp._client.callbacks.remove.call_count, 0)
Пример #11
0
    def test__sync_call_no_ret_value(self):

        def async_func(*args, **kwargs):
            cbparam = kwargs.get('callback')
            cbparam()

        tp = AMQPTransport(Mock())
        rv = tp._sync_call(async_func, 'callback')
        self.assertIsNone(rv)
Пример #12
0
    def test__on_underlying_close(self, mocklog):
        tp = AMQPTransport(Mock())
        cb = Mock()
        tp.add_on_close_callback(cb)

        tp._on_underlying_close(200, sentinel.text)

        cb.assert_called_once_with(tp, 200, sentinel.text)
        self.assertEquals(mocklog.debug.call_count, 1)
        self.assertIn(sentinel.text, mocklog.debug.call_args[0])
Пример #13
0
    def accept(self, n=1, timeout=None):
        """
        Accepts new connections for listening endpoints.

        Can accept more than one message at at time before it returns a new channel back to the
        caller. Optionally can specify a timeout - if n messages aren't received in that time,
        will raise an Empty exception.

        Sets the channel in the ACCEPTED state - caller is responsible for acking all messages
        received on the returned channel in order to put this channel back in the CONSUMING
        state.
        """

        assert self._fsm.current_state in [
            self.S_ACTIVE, self.S_CLOSED
        ], "Channel must be in active/closed state to accept, currently %s (forget to ack messages?)" % str(
            self._fsm.current_state)

        was_consuming = self._consuming

        if not self._should_discard and not was_consuming:
            # tune QOS to get exactly n messages
            if not (self._queue_auto_delete
                    and self._transport is AMQPTransport.get_instance()):
                self._transport.qos_impl(self._amq_chan, prefetch_count=n)

            # start consuming
            self.start_consume()

        with self._recv_queue.await_n(n=n) as ar:
            log.debug("accept: waiting for %s msgs, timeout=%s", n, timeout)
            ar.get(timeout=timeout)

        if not was_consuming:
            # turn consuming back off if we already were off
            if not (self._queue_auto_delete
                    and self._transport is AMQPTransport.get_instance()):
                self.stop_consume()
            else:
                log.debug(
                    "accept should turn consume off, but queue is auto_delete and this would destroy the queue"
                )

        ms = [self.recv() for x in xrange(n)]

        ch = self._create_accepted_channel(self._amq_chan, ms)
        map(ch._recv_queue.put, ms)

        # transition to ACCEPT
        self._fsm.process(self.I_ENTER_ACCEPT)

        # return the channel
        return ch
Пример #14
0
    def test_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        tp.close()

        client.close.assert_called_once_with()

        self.assertEquals(client.callbacks.remove.call_count, 4)
        self.assertEquals(client.callbacks.remove.call_args_list, [call(client.channel_number, 'Basic.GetEmpty'),
                                                                   call(client.channel_number, 'Channel.Close'),
                                                                   call(client.channel_number, '_on_basic_deliver'),
                                                                   call(client.channel_number, '_on_basic_get')])
Пример #15
0
    def test_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        tp.close()

        client.close.assert_called_once_with()

        self.assertEquals(client.callbacks.remove.call_count, 4)
        self.assertEquals(client.callbacks.remove.call_args_list, [
            call(client.channel_number, 'Basic.GetEmpty'),
            call(client.channel_number, 'Channel.Close'),
            call(client.channel_number, '_on_basic_deliver'),
            call(client.channel_number, '_on_basic_get')
        ])
Пример #16
0
    def test__on_underlying_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        cb = Mock()
        tp.add_on_close_callback(cb)

        tp._on_underlying_close(200, sentinel.text)

        cb.assert_called_once_with(tp, 200, sentinel.text)

        self.assertEquals(client.callbacks.remove.call_count, 4)
        self.assertEquals(client.callbacks.remove.call_args_list, [call(client.channel_number, 'Basic.GetEmpty'),
                                                                   call(client.channel_number, 'Channel.Close'),
                                                                   call(client.channel_number, '_on_basic_deliver'),
                                                                   call(client.channel_number, '_on_basic_get')])
Пример #17
0
    def test_delete_xn(self):
        raise unittest.SkipTest("broken 2 mar, skipping for now")
        # same as the other deletes except with queues instead

        xn = self.container.ex_manager.create_xn_service('test_service')

        # prove queue is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._queue_auto_delete = not xn._xn_auto_delete

        # must set recv_name
        ch._recv_name = xn
        self.assertRaises(TransportError, ch._declare_queue, xn.queue)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xn(xn)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xn._xs._xs_auto_delete

        # must set recv_name
        ch._recv_name = xn
        ch._declare_queue(xn.queue)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_queue_impl(ch._amq_chan, xn.queue)
Пример #18
0
    def test_delete_xn(self):
        raise unittest.SkipTest("broken 2 mar, skipping for now")
        # same as the other deletes except with queues instead

        xn = self.container.ex_manager.create_xn_service('test_service')

        # prove queue is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._queue_auto_delete = not xn._xn_auto_delete

        # must set recv_name
        ch._recv_name = xn
        self.assertRaises(TransportError, ch._declare_queue, xn.queue)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xn(xn)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xn._xs._xs_auto_delete

        # must set recv_name
        ch._recv_name = xn
        ch._declare_queue(xn.queue)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_queue_impl(ch._amq_chan, xn.queue)
Пример #19
0
    def __init__(self, transport=None, close_callback=None):
        """
        Initializes a BaseChannel instance.

        @param  transport       Underlying transport used for broker communication. Can be None, if so, will
                                use the AMQPTransport stateless singleton.
        @type   transport       BaseTransport
        @param  close_callback  The method to invoke when close() is called on this BaseChannel. May be left as None,
                                in which case close_impl() will be called. This expects to be a callable taking one
                                param, this channel instance.
        """
        self.set_close_callback(close_callback)
        self._transport = transport or AMQPTransport.get_instance()

        # setup FSM for BaseChannel / SendChannel tree
        self._fsm = FSM(self.S_INIT)
        self._fsm.add_transition(self.I_ATTACH, self.S_INIT, None,
                                 self.S_ACTIVE)
        self._fsm.add_transition(self.I_CLOSE, self.S_ACTIVE, self._on_close,
                                 self.S_CLOSED)
        self._fsm.add_transition(
            self.I_CLOSE, self.S_CLOSED, None, self.S_CLOSED
        )  # closed is a goal state, multiple closes are ok and are no-ops
        self._fsm.add_transition(self.I_CLOSE, self.S_INIT, None,
                                 self.S_CLOSED)  # INIT to CLOSED is fine too
Пример #20
0
    def accept(self, n=1, timeout=None):
        """
        Accepts new connections for listening endpoints.

        Can accept more than one message at at time before it returns a new channel back to the
        caller. Optionally can specify a timeout - if n messages aren't received in that time,
        will raise an Empty exception.

        Sets the channel in the ACCEPTED state - caller is responsible for acking all messages
        received on the returned channel in order to put this channel back in the CONSUMING
        state.
        """

        assert self._fsm.current_state in [self.S_ACTIVE, self.S_CLOSED], "Channel must be in active/closed state to accept, currently %s (forget to ack messages?)" % str(self._fsm.current_state)

        was_consuming = self._consuming

        if not self._should_discard and not was_consuming:
            # tune QOS to get exactly n messages
            if not (self._queue_auto_delete and self._transport is AMQPTransport.get_instance()):
                self._transport.qos_impl(self._amq_chan, prefetch_count=n)

            # start consuming
            self.start_consume()

        with self._recv_queue.await_n(n=n) as ar:
            log.debug("accept: waiting for %s msgs, timeout=%s", n, timeout)
            ar.get(timeout=timeout)

        if not was_consuming:
            # turn consuming back off if we already were off
            if not (self._queue_auto_delete and self._transport is AMQPTransport.get_instance()):
                self.stop_consume()
            else:
                log.debug("accept should turn consume off, but queue is auto_delete and this would destroy the queue")

        ms = [self.recv() for x in xrange(n)]

        ch = self._create_accepted_channel(self._amq_chan, ms)
        map(ch._recv_queue.put, ms)

        # transition to ACCEPT
        self._fsm.process(self.I_ENTER_ACCEPT)

        # return the channel
        return ch
Пример #21
0
    def close_impl(self):
        if not self._queue_auto_delete and self._recv_name and self._transport is AMQPTransport.get_instance(
        ) and self._recv_name.queue.startswith("amq.gen-"):
            log.debug("Anonymous Subscriber detected, deleting queue (%s)",
                      self._recv_name)
            self._destroy_queue()

        ListenChannel.close_impl(self)
Пример #22
0
    def test__sync_call_with_error(self):
        tp = AMQPTransport(Mock())

        def async_func(*args, **kwargs):
            raise TransportError('haha')

        self.assertRaises(TransportError, tp._sync_call, async_func,
                          'callback')
Пример #23
0
    def test_stop_consume_raises_warning_with_auto_delete(self):
        transport = AMQPTransport(Mock())
        transport.stop_consume_impl = Mock()
        self.ch.on_channel_open(transport)
        #transport.channel_number = sentinel.channel_number

        self.ch._consumer_tag = sentinel.consumer_tag
        self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue, sentinel.binding)
        self.ch._fsm.current_state = self.ch.S_ACTIVE
        self.ch._consuming = True

        #self.ch._ensure_transport = MagicMock()
        self.ch._queue_auto_delete = True

        self.ch.stop_consume()

        self.assertTrue(self.ch._transport.stop_consume_impl.called)
        self.assertIn(self.ch._consumer_tag, self.ch._transport.stop_consume_impl.call_args[0])
Пример #24
0
    def start(self):
        log.debug("ExchangeManager.start")

        total_count = 0

        def handle_failure(name, node):
            log.warn("Node %s could not be started", name)
            node.ready.set()        # let it fall out below

        # Establish connection(s) to broker
        for name, cfgkey in CFG.container.messaging.server.iteritems():
            if not cfgkey:
                continue

            if cfgkey not in CFG.server:
                raise ExchangeManagerError("Config key %s (name: %s) (from CFG.container.messaging.server) not in CFG.server" % (cfgkey, name))

            total_count += 1
            log.debug("Starting connection: %s", name)

            # start it with a zero timeout so it comes right back to us
            try:
                node, ioloop = messaging.make_node(CFG.server[cfgkey], name, 0)

                # install a finished handler directly on the ioloop just for this startup period
                fail_handle = lambda _: handle_failure(name, node)
                ioloop.link(fail_handle)

                # wait for the node ready event, with a large timeout just in case
                node_ready = node.ready.wait(timeout=15)

                # remove the finished handler, we don't care about it here
                ioloop.unlink(fail_handle)

                # only add to our list if we started successfully
                if not node.running:
                    ioloop.kill()      # make sure ioloop dead
                else:
                    self._nodes[name]   = node
                    self._ioloops[name] = ioloop

            except socket.error as e:
                log.warn("Could not start connection %s due to socket error, continuing", name)

        fail_count = total_count - len(self._nodes)
        if fail_count > 0 or total_count == 0:
            if fail_count == total_count:
                raise ExchangeManagerError("No node connection was able to start (%d nodes attempted, %d nodes failed)" % (total_count, fail_count))

            log.warn("Some nodes could not be started, ignoring for now")   # @TODO change when ready

        self._transport = AMQPTransport.get_instance()

        # load interceptors into each
        map(lambda x: x.setup_interceptors(CFG.interceptor), self._nodes.itervalues())

        log.debug("Started %d connections (%s)", len(self._nodes), ",".join(self._nodes.iterkeys()))
Пример #25
0
    def _new_transport(self, ch_number=None):
        """
        Creates a new AMQPTransport with an underlying Pika channel.
        """
        amq_chan = blocking_cb(self.client.channel, 'on_open_callback', channel_number=ch_number)
        if amq_chan is None:
            log.error("AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s", ch_number)
            from pyon.container.cc import Container
            if Container.instance is not None:
                Container.instance.fail_fast("AMQCHAN IS NONE, messaging has failed", True)
            raise StandardError("AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s" % ch_number)

        transport = AMQPTransport(amq_chan)

        # by default, everything should have a prefetch count of 1 (configurable)
        # this can be overridden by the channel get_n related methods
        transport.qos_impl(prefetch_count=CFG.get_safe('container.messaging.endpoint.prefetch_count', 1))

        return transport
Пример #26
0
    def test_close_does_delete_if_anonymous_and_not_auto_delete(self):
        transport = AMQPTransport(Mock())
        ch = SubscriberChannel()
        ch.on_channel_open(transport)
        ch._queue_auto_delete = False
        ch._destroy_queue = Mock()
        ch._recv_name = NameTrio(sentinel.exchange, 'amq.gen-ABCD')

        ch.close_impl()
        ch._destroy_queue.assert_called_once_with()
Пример #27
0
    def test_stop_consume_raises_warning_with_auto_delete(self, mocklog):
        transport = AMQPTransport(Mock())
        transport.stop_consume_impl = Mock()
        self.ch.on_channel_open(transport)
        #transport.channel_number = sentinel.channel_number

        self.ch._consumer_tag = sentinel.consumer_tag
        self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue,
                                      sentinel.binding)
        self.ch._fsm.current_state = self.ch.S_ACTIVE
        self.ch._consuming = True

        #self.ch._ensure_transport = MagicMock()
        self.ch._queue_auto_delete = True

        self.ch.stop_consume()

        self.assertTrue(mocklog.debug.called)
        self.assertIn(sentinel.queue, mocklog.debug.call_args[0])
Пример #28
0
    def test__sync_call_with_close_indicating_error(self):
        tp = AMQPTransport(Mock())

        def async_func(*args, **kwargs):
            tp._client.add_on_close_callback.call_args[0][0](sentinel.ch,
                                                             sentinel.arg)

        self.assertRaises(TransportError, tp._sync_call, async_func,
                          'callback')
        tp._client.transport.connection.mark_bad_channel.assert_called_once_with(
            tp._client.channel_number)
Пример #29
0
    def test_start_consume_with_consumer_tag_and_auto_delete(self, mocklog):
        transport = AMQPTransport(Mock())
        self.ch.on_channel_open(transport)
        self.ch._fsm.current_state = self.ch.S_ACTIVE

        # set up recv name for queue
        self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue)
        self.ch._consumer_tag = sentinel.consumer_tag
        self.ch._queue_auto_delete = True

        self.ch.start_consume()
        self.assertTrue(mocklog.warn.called)
Пример #30
0
    def start(self):
        log.debug("ExchangeManager starting ...")

        # Establish connection to broker
        # @TODO: raise error if sux
        node, ioloop = messaging.make_node()

        self._transport = AMQPTransport.get_instance()
        self._client = self._get_channel(node)

        # Declare root exchange
        #self.default_xs.ensure_exists(self._get_channel())
        return node, ioloop
Пример #31
0
    def __init__(self, transport=None, close_callback=None):
        """
        Initializes a BaseChannel instance.

        @param  transport       Underlying transport used for broker communication. Can be None, if so, will
                                use the AMQPTransport stateless singleton.
        @type   transport       BaseTransport
        @param  close_callback  The method to invoke when close() is called on this BaseChannel. May be left as None,
                                in which case close_impl() will be called. This expects to be a callable taking one
                                param, this channel instance.
        """
        self.set_close_callback(close_callback)
        self._transport = transport or AMQPTransport.get_instance()
Пример #32
0
    def start(self):
        log.debug("ExchangeManager starting ...")

        # Establish connection to broker
        # @TODO: raise error if sux
        node, ioloop = messaging.make_node()

        self._transport = AMQPTransport.get_instance()
        self._client    = self._get_channel(node)

        # Declare root exchange
        #self.default_xs.ensure_exists(self._get_channel())
        return node, ioloop
Пример #33
0
    def _on_stop_consume(self):
        """
        Stops consuming messages.

        If the queue has auto_delete, this will delete it.
        """
        #log.debug("RecvChannel._on_stop_consume")

        if self._queue_auto_delete and self._transport is AMQPTransport.get_instance():
            log.debug("Autodelete is on, this will destroy this queue: %s", self._recv_name.queue)

        self._ensure_amq_chan()

        self._sync_call(self._amq_chan.basic_cancel, 'callback', self._consumer_tag)
Пример #34
0
    def _new_transport(self, ch_number=None):
        """
        Creates a new AMQPTransport with an underlying Pika channel.
        """
        amq_chan = blocking_cb(self.client.channel, 'on_open_callback', channel_number=ch_number)
        if amq_chan is None:
            log.error("AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s", ch_number)
            traceback.print_stack()
            from pyon.container.cc import Container
            if Container.instance is not None:
                Container.instance.fail_fast("AMQCHAN IS NONE, messaging has failed", True)
            raise StandardError("AMQCHAN IS NONE THIS SHOULD NEVER HAPPEN, chan number requested: %s" % ch_number)

        transport = AMQPTransport(amq_chan)
        return transport
Пример #35
0
    def test__on_underlying_close(self, mocklog):
        tp = AMQPTransport(Mock())
        cb = Mock()
        tp.add_on_close_callback(cb)

        tp._on_underlying_close(200, sentinel.text)

        cb.assert_called_once_with(tp, 200, sentinel.text)
        self.assertEquals(mocklog.debug.call_count, 1)
        self.assertIn(sentinel.text, mocklog.debug.call_args[0])
Пример #36
0
    def _on_stop_consume(self):
        """
        Stops consuming messages.

        If the queue has auto_delete, this will delete it.
        """
        #log.debug("RecvChannel._on_stop_consume")

        if self._queue_auto_delete and self._transport is AMQPTransport.get_instance(
        ):
            log.debug("Autodelete is on, this will destroy this queue: %s",
                      self._recv_name.queue)

        self._ensure_amq_chan()

        self._sync_call(self._amq_chan.basic_cancel, 'callback',
                        self._consumer_tag)
Пример #37
0
    def _on_start_consume(self):
        """
        Starts consuming messages.

        setup_listener must have been called first.
        """
        #log.debug("RecvChannel._on_start_consume")

        if self._consumer_tag and (self._queue_auto_delete and self._transport is AMQPTransport.get_instance()):
            log.warn("Attempting to start consuming on a queue that may have been auto-deleted")

        self._ensure_amq_chan()

        self._consumer_tag = self._amq_chan.basic_consume(self._on_deliver,
                                                          queue=self._recv_name.queue,
                                                          no_ack=self._consumer_no_ack,
                                                          exclusive=self._consumer_exclusive)
Пример #38
0
    def __init__(self, transport=None, close_callback=None):
        """
        Initializes a BaseChannel instance.

        @param  transport       Underlying transport used for broker communication. Can be None, if so, will
                                use the AMQPTransport stateless singleton.
        @type   transport       BaseTransport
        @param  close_callback  The method to invoke when close() is called on this BaseChannel. May be left as None,
                                in which case close_impl() will be called. This expects to be a callable taking one
                                param, this channel instance.
        """
        self.set_close_callback(close_callback)
        self._transport = transport or AMQPTransport.get_instance()

        # setup FSM for BaseChannel / SendChannel tree
        self._fsm = FSM(self.S_INIT)
        self._fsm.add_transition(self.I_ATTACH, self.S_INIT, None, self.S_ACTIVE)
        self._fsm.add_transition(self.I_CLOSE, self.S_ACTIVE, self._on_close, self.S_CLOSED)
        self._fsm.add_transition(self.I_CLOSE, self.S_CLOSED, None, self.S_CLOSED)              # closed is a goal state, multiple closes are ok and are no-ops
        self._fsm.add_transition(self.I_CLOSE, self.S_INIT, None, self.S_CLOSED)                # INIT to CLOSED is fine too
Пример #39
0
    def _on_start_consume(self):
        """
        Starts consuming messages.

        setup_listener must have been called first.
        """
        #log.debug("RecvChannel._on_start_consume")

        if self._consumer_tag and (self._queue_auto_delete and self._transport
                                   is AMQPTransport.get_instance()):
            log.warn(
                "Attempting to start consuming on a queue that may have been auto-deleted"
            )

        self._ensure_amq_chan()

        self._consumer_tag = self._amq_chan.basic_consume(
            self._on_deliver,
            queue=self._recv_name.queue,
            no_ack=self._consumer_no_ack,
            exclusive=self._consumer_exclusive)
Пример #40
0
    def test_delete_xp(self):
        # same as test_delete_xs
        xp = self.container.ex_manager.create_xp('test_xp')

        # prove XS is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xp._xs._xs_auto_delete

        self.assertRaises(TransportError, ch._declare_exchange, xp.exchange)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xp(xp)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xp._xs._xs_auto_delete

        ch._declare_exchange(xp.exchange)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_exchange_impl(ch._amq_chan, xp.exchange)
Пример #41
0
    def test_delete_xp(self):
        # same as test_delete_xs
        xp = self.container.ex_manager.create_xp('test_xp')

        # prove XS is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xp._xs._xs_auto_delete

        self.assertRaises(TransportError, ch._declare_exchange, xp.exchange)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xp(xp)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xp._xs._xs_auto_delete

        ch._declare_exchange(xp.exchange)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_exchange_impl(ch._amq_chan, xp.exchange)
Пример #42
0
    def test__on_underlying_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        cb = Mock()
        tp.add_on_close_callback(cb)

        tp._on_underlying_close(200, sentinel.text)

        cb.assert_called_once_with(tp, 200, sentinel.text)

        self.assertEquals(client.callbacks.remove.call_count, 4)
        self.assertEquals(client.callbacks.remove.call_args_list, [
            call(client.channel_number, 'Basic.GetEmpty'),
            call(client.channel_number, 'Channel.Close'),
            call(client.channel_number, '_on_basic_deliver'),
            call(client.channel_number, '_on_basic_get')
        ])
Пример #43
0
    def test_delete_xs(self):
        # we get interesting here.  we have to create or xs, try to declare again to prove it is there,
        # then delete, then declare to prove we CAN create, then make sure to clean it up.  whew.
        xs = self.container.ex_manager.create_xs('test_xs')

        # prove XS is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xs._xs_auto_delete

        self.assertRaises(TransportError, ch._declare_exchange, xs.exchange)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xs(xs)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xs._xs_auto_delete

        ch._declare_exchange(xs.exchange)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_exchange_impl(ch._amq_chan, xs.exchange)
Пример #44
0
    def test_delete_xs(self):
        # we get interesting here.  we have to create or xs, try to declare again to prove it is there,
        # then delete, then declare to prove we CAN create, then make sure to clean it up.  whew.
        xs = self.container.ex_manager.create_xs('test_xs')

        # prove XS is declared already (can't declare the same named one with diff params)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xs._xs_auto_delete

        self.assertRaises(TransportError, ch._declare_exchange, xs.exchange)

        # now let's delete via ex manager
        self.container.ex_manager.delete_xs(xs)

        # grab another channel and declare (should work fine this time)
        ch = self.container.node.channel(RecvChannel)
        ch._exchange_auto_delete = not xs._xs_auto_delete

        ch._declare_exchange(xs.exchange)

        # cool, now cleanup (we don't expose this via Channel)
        at = AMQPTransport.get_instance()
        at.delete_exchange_impl(ch._amq_chan, xs.exchange)
Пример #45
0
    def test_add_on_close_callback(self):
        tp = AMQPTransport(Mock())
        tp.add_on_close_callback(sentinel.one)
        tp.add_on_close_callback(sentinel.two)

        self.assertEquals(tp._close_callbacks, [sentinel.one, sentinel.two])
Пример #46
0
 def test_channel_number(self):
     client = Mock()
     tp = AMQPTransport(client)
     self.assertEquals(tp.channel_number, client.channel_number)
Пример #47
0
    def close_impl(self):
        if not self._queue_auto_delete and self._recv_name and self._transport is AMQPTransport.get_instance() and self._recv_name.queue.startswith("amq.gen-"):
            log.debug("Anonymous Subscriber detected, deleting queue (%s)", self._recv_name)
            self._destroy_queue()

        ListenChannel.close_impl(self)
Пример #48
0
    def test_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        tp.close()

        client.close.assert_called_once_with()
Пример #49
0
    def test_active_no_client(self):
        tp = AMQPTransport(Mock())
        tp._client = None

        self.assertFalse(tp.active)
Пример #50
0
    def test_close(self):
        client = Mock()
        tp = AMQPTransport(client)
        tp.close()

        client.close.assert_called_once_with()
Пример #51
0
    def test_add_on_close_callback(self):
        tp = AMQPTransport(Mock())
        tp.add_on_close_callback(sentinel.one)
        tp.add_on_close_callback(sentinel.two)

        self.assertEquals(tp._close_callbacks, [sentinel.one, sentinel.two])
Пример #52
0
class TestAMQPTransportCommonMethods(PyonTestCase):

    def setUp(self):
        self.tp = AMQPTransport(MagicMock())
        self.tp._sync_call = Mock()

    def test_declare_exchange_impl(self):
        self.tp.declare_exchange_impl(sentinel.exchange)

        self.tp._sync_call.assert_called_once_with(self.tp._client.exchange_declare,
                                                   'callback',
                                                   exchange=sentinel.exchange,
                                                   type='topic',
                                                   durable=False,
                                                   auto_delete=True,
                                                   arguments={})

    @patch('pyon.net.transport.os', new_callable=MagicMock)
    def test_declare_exchange_impl_queue_blame(self, osmock):
        osmock.environ.get.return_value = True
        osmock.environ.__getitem__.return_value = sentinel.testid

        self.tp.declare_exchange_impl(sentinel.exchange)

        self.tp._sync_call.assert_called_once_with(self.tp._client.exchange_declare,
                                                   'callback',
                                                   exchange=sentinel.exchange,
                                                   type='topic',
                                                   durable=False,
                                                   auto_delete=True,
                                                   arguments={'created-by':sentinel.testid})

    def test_delete_exchange_impl(self):
        self.tp.delete_exchange_impl(sentinel.exchange)
        self.tp._sync_call.assert_called_once_with(self.tp._client.exchange_delete,
                                                   'callback',
                                                   exchange=sentinel.exchange)

    def test_declare_queue_impl(self):
        retqueue = self.tp.declare_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_declare,
                                                   'callback',
                                                   queue=sentinel.queue,
                                                   auto_delete=True,
                                                   durable=False,
                                                   arguments={})

        self.assertEquals(retqueue, self.tp._sync_call.return_value.method.queue)

    @patch('pyon.net.transport.os', new_callable=MagicMock)
    def test_declare_queue_impl_queue_blame(self, osmock):
        osmock.environ.get.return_value = True
        osmock.environ.__getitem__.return_value = sentinel.testid

        retqueue = self.tp.declare_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_declare,
                                                   'callback',
                                                   queue=sentinel.queue,
                                                   durable=False,
                                                   auto_delete=True,
                                                   arguments={'created-by':sentinel.testid})

        self.assertEquals(retqueue, self.tp._sync_call.return_value.method.queue)

    def test_delete_queue(self):
        self.tp.delete_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_delete,
                                                   'callback',
                                                   queue=sentinel.queue)

    def test_bind_impl(self):
        self.tp.bind_impl(sentinel.exchange, sentinel.queue, sentinel.binding)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_bind,
                                                   'callback',
                                                   queue=sentinel.queue,
                                                   exchange=sentinel.exchange,
                                                   routing_key=sentinel.binding)

    def test_unbind_impl(self):
        self.tp.unbind_impl(sentinel.exchange, sentinel.queue, sentinel.binding)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_unbind,
                                                   'callback',
                                                   queue=sentinel.queue,
                                                   exchange=sentinel.exchange,
                                                   routing_key=sentinel.binding)

    def test_ack_impl(self):
        self.tp.ack_impl(sentinel.dtag)

        self.tp._client.basic_ack.assert_called_once_with(sentinel.dtag)

    def test_reject_impl(self):
        self.tp.reject_impl(sentinel.dtag)

        self.tp._client.basic_reject.assert_called_once_with(sentinel.dtag, requeue=False)

    def test_start_consume_impl(self):
        rettag = self.tp.start_consume_impl(sentinel.callback, sentinel.queue)

        self.tp._client.basic_consume.assert_called_once_with(sentinel.callback,
                                                              queue=sentinel.queue,
                                                              no_ack=False,
                                                              exclusive=False)

        self.assertEquals(rettag, self.tp._client.basic_consume.return_value)

    def test_stop_consume_impl(self):
        self.tp.stop_consume_impl(sentinel.ctag)

        self.tp._sync_call.assert_called_once_with(self.tp._client.basic_cancel,
                                                   'callback',
                                                   sentinel.ctag)

    @patch('pyon.net.transport.sleep', Mock())      # patch to make sleep() be a mock call and therefore superfast
    def test_stop_consume_remains_in_consumers(self):
        self.tp._client._consumers = [sentinel.ctag]
        self.assertRaises(TransportError, self.tp.stop_consume_impl, sentinel.ctag)

    @patch('pyon.net.transport.sleep')
    def test_stop_consume_eventually_removed(self, sleepmock):
        self.tp._client._consumers.__contains__.side_effect = [True, False, False] # is checked once more at exit of method

        self.tp.stop_consume_impl(sentinel.ctag)
        sleepmock.assert_called_once_with(1)

    def test_setup_listener(self):
        cb = Mock()
        self.tp.setup_listener(sentinel.binding, cb)

        cb.assert_called_once_with(self.tp, sentinel.binding)

    def test_get_stats_impl(self):
        mo = Mock()
        self.tp._sync_call.return_value = mo
        ret = self.tp.get_stats_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_declare,
                                                   'callback',
                                                   queue=sentinel.queue,
                                                   passive=True)

        self.assertEquals(ret, (mo.method.message_count, mo.method.consumer_count))

    def test_purge_impl(self):
        self.tp.purge_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_purge,
                                                   'callback',
                                                   queue=sentinel.queue)

    def test_qos_impl(self):
        self.tp.qos_impl()

        self.tp._sync_call.assert_called_once_with(self.tp._client.basic_qos,
                                                   'callback',
                                                   prefetch_size=0,
                                                   prefetch_count=0,
                                                   global_=False)

    @patch('pyon.net.transport.BasicProperties')
    def test_publish_impl(self, bpmock):
        self.tp.publish_impl(sentinel.exchange, sentinel.routing_key, sentinel.body, sentinel.properties)

        self.tp._client.basic_publish.assert_called_once_with(exchange=sentinel.exchange,
                                                              routing_key=sentinel.routing_key,
                                                              body=sentinel.body,
                                                              properties=bpmock(headers=sentinel.properties,
                                                                                delivery_mode=None),
                                                              immediate=False,
                                                              mandatory=False)

    @patch('pyon.net.transport.BasicProperties')
    def test_publish_impl_durable(self, bpmock):
        self.tp.publish_impl(sentinel.exchange, sentinel.routing_key, sentinel.body, sentinel.properties, durable_msg=True)

        self.tp._client.basic_publish.assert_called_once_with(exchange=sentinel.exchange,
                                                              routing_key=sentinel.routing_key,
                                                              body=sentinel.body,
                                                              properties=bpmock(headers=sentinel.properties,
                                                                                delivery_mode=2),
                                                              immediate=False,
                                                              mandatory=False)
Пример #53
0
class TestAMQPTransportCommonMethods(PyonTestCase):
    def setUp(self):
        self.tp = AMQPTransport(MagicMock())
        self.tp._sync_call = Mock()

    def test_declare_exchange_impl(self):
        self.tp.declare_exchange_impl(sentinel.exchange)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.exchange_declare,
            'callback',
            exchange=sentinel.exchange,
            type='topic',
            durable=False,
            auto_delete=True,
            arguments={})

    @patch('pyon.net.transport.os', new_callable=MagicMock)
    def test_declare_exchange_impl_queue_blame(self, osmock):
        osmock.environ.get.return_value = True
        osmock.environ.__getitem__.return_value = sentinel.testid

        self.tp.declare_exchange_impl(sentinel.exchange)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.exchange_declare,
            'callback',
            exchange=sentinel.exchange,
            type='topic',
            durable=False,
            auto_delete=True,
            arguments={'created-by': sentinel.testid})

    def test_delete_exchange_impl(self):
        self.tp.delete_exchange_impl(sentinel.exchange)
        self.tp._sync_call.assert_called_once_with(
            self.tp._client.exchange_delete,
            'callback',
            exchange=sentinel.exchange)

    def test_declare_queue_impl(self):
        retqueue = self.tp.declare_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_declare,
            'callback',
            queue=sentinel.queue,
            auto_delete=True,
            durable=False,
            arguments={})

        self.assertEquals(retqueue,
                          self.tp._sync_call.return_value.method.queue)

    @patch('pyon.net.transport.os', new_callable=MagicMock)
    def test_declare_queue_impl_queue_blame(self, osmock):
        osmock.environ.get.return_value = True
        osmock.environ.__getitem__.return_value = sentinel.testid

        retqueue = self.tp.declare_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_declare,
            'callback',
            queue=sentinel.queue,
            durable=False,
            auto_delete=True,
            arguments={'created-by': sentinel.testid})

        self.assertEquals(retqueue,
                          self.tp._sync_call.return_value.method.queue)

    def test_delete_queue(self):
        self.tp.delete_queue_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_delete, 'callback', queue=sentinel.queue)

    def test_bind_impl(self):
        self.tp.bind_impl(sentinel.exchange, sentinel.queue, sentinel.binding)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_bind,
            'callback',
            queue=sentinel.queue,
            exchange=sentinel.exchange,
            routing_key=sentinel.binding)

    def test_unbind_impl(self):
        self.tp.unbind_impl(sentinel.exchange, sentinel.queue,
                            sentinel.binding)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_unbind,
            'callback',
            queue=sentinel.queue,
            exchange=sentinel.exchange,
            routing_key=sentinel.binding)

    def test_ack_impl(self):
        self.tp.ack_impl(sentinel.dtag)

        self.tp._client.basic_ack.assert_called_once_with(sentinel.dtag)

    def test_reject_impl(self):
        self.tp.reject_impl(sentinel.dtag)

        self.tp._client.basic_reject.assert_called_once_with(sentinel.dtag,
                                                             requeue=False)

    def test_start_consume_impl(self):
        rettag = self.tp.start_consume_impl(sentinel.callback, sentinel.queue)

        self.tp._client.basic_consume.assert_called_once_with(
            sentinel.callback,
            queue=sentinel.queue,
            no_ack=False,
            exclusive=False)

        self.assertEquals(rettag, self.tp._client.basic_consume.return_value)

    def test_stop_consume_impl(self):
        self.tp.stop_consume_impl(sentinel.ctag)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.basic_cancel, 'callback', sentinel.ctag)

    @patch('pyon.net.transport.sleep', Mock()
           )  # patch to make sleep() be a mock call and therefore superfast
    def test_stop_consume_remains_in_consumers(self):
        self.tp._client._consumers = [sentinel.ctag]
        self.assertRaises(TransportError, self.tp.stop_consume_impl,
                          sentinel.ctag)

    @patch('pyon.net.transport.sleep')
    def test_stop_consume_eventually_removed(self, sleepmock):
        self.tp._client._consumers.__contains__.side_effect = [
            True, False, False
        ]  # is checked once more at exit of method

        self.tp.stop_consume_impl(sentinel.ctag)
        sleepmock.assert_called_once_with(1)

    def test_setup_listener(self):
        cb = Mock()
        self.tp.setup_listener(sentinel.binding, cb)

        cb.assert_called_once_with(self.tp, sentinel.binding)

    def test_get_stats_impl(self):
        mo = Mock()
        self.tp._sync_call.return_value = mo
        ret = self.tp.get_stats_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(
            self.tp._client.queue_declare,
            'callback',
            queue=sentinel.queue,
            passive=True)

        self.assertEquals(ret,
                          (mo.method.message_count, mo.method.consumer_count))

    def test_purge_impl(self):
        self.tp.purge_impl(sentinel.queue)

        self.tp._sync_call.assert_called_once_with(self.tp._client.queue_purge,
                                                   'callback',
                                                   queue=sentinel.queue)

    def test_qos_impl(self):
        self.tp.qos_impl()

        self.tp._sync_call.assert_called_once_with(self.tp._client.basic_qos,
                                                   'callback',
                                                   prefetch_size=0,
                                                   prefetch_count=0,
                                                   global_=False)

    @patch('pyon.net.transport.BasicProperties')
    def test_publish_impl(self, bpmock):
        self.tp.publish_impl(sentinel.exchange, sentinel.routing_key,
                             sentinel.body, sentinel.properties)

        self.tp._client.basic_publish.assert_called_once_with(
            exchange=sentinel.exchange,
            routing_key=sentinel.routing_key,
            body=sentinel.body,
            properties=bpmock(headers=sentinel.properties, delivery_mode=None),
            immediate=False,
            mandatory=False)

    @patch('pyon.net.transport.BasicProperties')
    def test_publish_impl_durable(self, bpmock):
        self.tp.publish_impl(sentinel.exchange,
                             sentinel.routing_key,
                             sentinel.body,
                             sentinel.properties,
                             durable_msg=True)

        self.tp._client.basic_publish.assert_called_once_with(
            exchange=sentinel.exchange,
            routing_key=sentinel.routing_key,
            body=sentinel.body,
            properties=bpmock(headers=sentinel.properties, delivery_mode=2),
            immediate=False,
            mandatory=False)
Пример #54
0
 def setUp(self):
     self.tp = AMQPTransport(MagicMock())
     self.tp._sync_call = Mock()
Пример #55
0
 def setUp(self):
     self.tp = AMQPTransport(MagicMock())
     self.tp._sync_call = Mock()