Ejemplo n.º 1
0
    def spawn_worker(self, provider, args, kwargs,
                     context_data=None, handle_result=None):
        """ Spawn a worker thread for running the service method decorated
        with an entrypoint ``provider``.

        ``args`` and ``kwargs`` are used as arguments for the service
        method.

        ``context_data`` is used to initialize a ``WorkerContext``.

        ``handle_result`` is an optional function which may be passed
        in by the entrypoint provider. It is called with the result returned
        or error raised by the service method. If provided it must return a
        value for ``result`` and ``exc_info`` to propagate to dependencies;
        these may be different to those returned by the service method.
        """

        if self._being_killed:
            _log.info("Worker spawn prevented due to being killed")
            raise ContainerBeingKilled()

        service = self.service_cls()
        worker_ctx = self.worker_ctx_cls(
            self, service, provider, args, kwargs, data=context_data)

        _log.debug('spawning %s', worker_ctx)
        gt = self._worker_pool.spawn(self._run_worker, worker_ctx,
                                     handle_result)
        self._active_threads.add(gt)
        gt.link(self._handle_thread_exited)
        return worker_ctx
Ejemplo n.º 2
0
def test_consume_provider(empty_config):

    container = Mock(spec=ServiceContainer)
    container.worker_ctx_cls = WorkerContext
    container.service_name = "service"
    container.config = empty_config

    worker_ctx = WorkerContext(container, None, DummyProvider())

    spawn_worker = container.spawn_worker
    spawn_worker.return_value = worker_ctx

    queue_consumer = Mock()

    consume_provider = ConsumeProvider(queue=foobar_queue,
                                       requeue_on_error=False)
    consume_provider.queue_consumer = queue_consumer
    consume_provider.bind("name", container)

    message = Mock(headers={})

    # test lifecycle
    consume_provider.prepare()
    queue_consumer.register_provider.assert_called_once_with(consume_provider)

    consume_provider.stop()
    queue_consumer.unregister_provider.assert_called_once_with(
        consume_provider)

    # test handling successful call
    queue_consumer.reset_mock()
    consume_provider.handle_message("body", message)
    handle_result = spawn_worker.call_args[1]['handle_result']
    handle_result(worker_ctx, 'result')
    queue_consumer.ack_message.assert_called_once_with(message)

    # test handling failed call without requeue
    queue_consumer.reset_mock()
    consume_provider.requeue_on_error = False
    consume_provider.handle_message("body", message)
    handle_result = spawn_worker.call_args[1]['handle_result']
    handle_result(worker_ctx, None, (Exception, Exception('Error'), "tb"))
    queue_consumer.ack_message.assert_called_once_with(message)

    # test handling failed call with requeue
    queue_consumer.reset_mock()
    consume_provider.requeue_on_error = True
    consume_provider.handle_message("body", message)
    handle_result = spawn_worker.call_args[1]['handle_result']
    handle_result(worker_ctx, None, (Exception, Exception('Error'), "tb"))
    assert not queue_consumer.ack_message.called
    queue_consumer.requeue_message.assert_called_once_with(message)

    # test requeueing on ContainerBeingKilled (even without requeue_on_error)
    queue_consumer.reset_mock()
    consume_provider.requeue_on_error = False
    spawn_worker.side_effect = ContainerBeingKilled()
    consume_provider.handle_message("body", message)
    assert not queue_consumer.ack_message.called
    queue_consumer.requeue_message.assert_called_once_with(message)
Ejemplo n.º 3
0
def test_nova_rpc_provider(empty_config):

    rpc_consumer = Mock()
    message = Mock(headers={})

    message_body = {
        'method': 'method',
        'args': {
            "arg": "arg_value"
        },
        'msg_id': 'msg_id',
        '_context_user_id': 'user_id'
    }

    class Service(object):
        def method(self, arg):
            pass

    container = Mock(spec=ServiceContainer)
    container.service_cls = Service
    container.worker_ctx_cls = WorkerContext
    container.service_name = "service"
    container.config = empty_config

    rpc_provider = NovaRpcProvider()
    rpc_provider.rpc_consumer = rpc_consumer
    rpc_provider.bind("method", container)

    container.spawn_worker.side_effect = ContainerBeingKilled()
    rpc_provider.handle_message(message_body, message)
    assert rpc_consumer.requeue_message.called