Esempio n. 1
0
def test_example_service(container_factory, rabbit_config):

    db_uri = 'sqlite:///{}'.format(tempfile.NamedTemporaryFile().name)
    engine = create_engine(db_uri)
    FooModel.metadata.create_all(engine)

    config = {
        ORM_DB_URIS_KEY: {
            'foo-service:foo_base': db_uri
        }
    }
    config.update(rabbit_config)

    container = container_factory(FooService, config)
    container.start()

    with wait_for_call(5, handle_spam_called) as handle_spam:
        handle_spam.assert_called_with('ham & eggs')

    with wait_for_call(5, handle_foo_called) as handle_foo:
        handle_foo.assert_called_with('message')

    entries = list(engine.execute('SELECT data FROM spam LIMIT 1'))
    assert entries == [('ham',)]

    container.stop()
Esempio n. 2
0
def test_rpc_container_being_killed_retries(container_factory, rabbit_config):

    container = container_factory(ExampleService, rabbit_config)
    container.start()

    def wait_for_result():
        with RpcProxy("exampleservice", rabbit_config) as proxy:
            return proxy.task_a()

    container._being_killed = True

    rpc_provider = get_dependency(container, RpcProvider, name='task_a')

    with patch.object(
            rpc_provider,
            'rpc_consumer',
            wraps=rpc_provider.rpc_consumer,
    ) as wrapped_consumer:
        waiter = eventlet.spawn(wait_for_result)
        with wait_for_call(1, wrapped_consumer.requeue_message):
            pass  # wait until at least one message has been requeued
        assert not waiter.dead

    container._being_killed = False
    assert waiter.wait() == 'result_a'  # now completed
Esempio n. 3
0
def test_consume_from_rabbit(rabbit_manager, rabbit_config):

    vhost = rabbit_config['vhost']

    container = Mock(spec=ServiceContainer)
    container.worker_ctx_cls = CustomWorkerContext
    container.service_name = "service"
    container.config = rabbit_config
    container.max_workers = 10

    def spawn_thread(method, protected):
        return eventlet.spawn(method)

    container.spawn_managed_thread = spawn_thread

    worker_ctx = CustomWorkerContext(container, None, None)

    factory = DependencyFactory(
        ConsumeProvider, queue=foobar_queue, requeue_on_error=False)
    consumer = factory.create_and_bind_instance("injection_name", container)

    # prepare and start dependencies
    consumer.prepare()
    consumer.queue_consumer.prepare()
    consumer.start()
    consumer.queue_consumer.start()

    # test queue, exchange and binding created in rabbit
    exchanges = rabbit_manager.get_exchanges(vhost)
    queues = rabbit_manager.get_queues(vhost)
    bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name)

    assert "foobar_ex" in [exchange['name'] for exchange in exchanges]
    assert "foobar_queue" in [queue['name'] for queue in queues]
    assert "foobar_ex" in [binding['source'] for binding in bindings]

    # test message consumed from queue
    container.spawn_worker.return_value = worker_ctx

    headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue'}
    rabbit_manager.publish(
        vhost, foobar_ex.name, '', 'msg', properties=dict(headers=headers))

    ctx_data = {
        'language': 'en',
        'customheader': 'customvalue',
    }
    with wait_for_call(CONSUME_TIMEOUT, container.spawn_worker) as method:
        method.assert_called_once_with(
            consumer, ('msg', ), {},
            context_data=ctx_data,
            handle_result=ANY_PARTIAL)
        handle_result = method.call_args[1]['handle_result']

    # ack message
    handle_result(worker_ctx, 'result')

    # stop will hang if the consumer hasn't acked or requeued messages
    with eventlet.timeout.Timeout(CONSUME_TIMEOUT):
        consumer.stop()
Esempio n. 4
0
def test_rpc_container_being_killed_retries(
        container_factory, rabbit_config):

    container = container_factory(ExampleService, rabbit_config)
    container.start()

    def wait_for_result():
        with ServiceRpcProxy("exampleservice", rabbit_config) as proxy:
            return proxy.task_a()

    container._being_killed = True

    rpc_provider = get_extension(container, Rpc, method_name='task_a')

    with patch.object(
        rpc_provider,
        'rpc_consumer',
        wraps=rpc_provider.rpc_consumer,
    ) as wrapped_consumer:
        waiter = eventlet.spawn(wait_for_result)
        with wait_for_call(1, wrapped_consumer.requeue_message):
            pass  # wait until at least one message has been requeued
        assert not waiter.dead

    container._being_killed = False
    assert waiter.wait() == 'result_a'  # now completed
Esempio n. 5
0
def test_call_id_over_events(rabbit_config, predictable_call_ids,
                             runner_factory):
    one_called = Mock()
    two_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class HelloEvent(NamekoEvent):
        type = "hello"

    class EventListeningServiceOne(object):
        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            one_called()

    class EventListeningServiceTwo(object):
        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            two_called()

    class EventRaisingService(object):
        name = "event_raiser"
        dispatch = event_dispatcher()

        @rpc
        def say_hello(self):
            self.dispatch(HelloEvent(self.name))

    runner = runner_factory(rabbit_config)
    runner.add_service(EventListeningServiceOne, LoggingWorkerContext)
    runner.add_service(EventListeningServiceTwo, LoggingWorkerContext)
    runner.add_service(EventRaisingService, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, EventRaisingService)
    with entrypoint_hook(container, "say_hello") as say_hello:
        say_hello()

    with wait_for_call(5, one_called), wait_for_call(5, two_called):

        assert predictable_call_ids.call_count == 3
        stack_request.assert_has_calls([
            call(None),
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0']),
        ])
Esempio n. 6
0
def test_wait_for_call():
    mock = Mock()

    def call_after(seconds):
        eventlet.sleep(seconds)
        mock.method()

    # should not raise
    eventlet.spawn(call_after, 0)
    with wait_for_call(1, mock.method):
        pass

    mock.reset_mock()

    with pytest.raises(eventlet.Timeout):
        eventlet.spawn(call_after, 1)
        with wait_for_call(0, mock.method):
            pass
Esempio n. 7
0
def test_consume_from_rabbit(container_factory, rabbit_manager, rabbit_config):

    vhost = rabbit_config["vhost"]

    container = Mock(spec=ServiceContainer)
    container.shared_extensions = {}
    container.worker_ctx_cls = CustomWorkerContext
    container.service_name = "service"
    container.config = rabbit_config
    container.max_workers = 10

    def spawn_thread(method, protected):
        return eventlet.spawn(method)

    container.spawn_managed_thread = spawn_thread

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

    consumer = Consumer(queue=foobar_queue, requeue_on_error=False).bind(container, "publish")

    # prepare and start extensions
    consumer.setup()
    consumer.queue_consumer.setup()
    consumer.start()
    consumer.queue_consumer.start()

    # test queue, exchange and binding created in rabbit
    exchanges = rabbit_manager.get_exchanges(vhost)
    queues = rabbit_manager.get_queues(vhost)
    bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name)

    assert "foobar_ex" in [exchange["name"] for exchange in exchanges]
    assert "foobar_queue" in [queue["name"] for queue in queues]
    assert "foobar_ex" in [binding["source"] for binding in bindings]

    # test message consumed from queue
    container.spawn_worker.return_value = worker_ctx

    headers = {"nameko.language": "en", "nameko.customheader": "customvalue"}
    rabbit_manager.publish(vhost, foobar_ex.name, "", "msg", properties=dict(headers=headers))

    ctx_data = {"language": "en", "customheader": "customvalue"}
    with wait_for_call(CONSUME_TIMEOUT, container.spawn_worker) as method:
        method.assert_called_once_with(consumer, ("msg",), {}, context_data=ctx_data, handle_result=ANY_PARTIAL)
        handle_result = method.call_args[1]["handle_result"]

    # ack message
    handle_result(worker_ctx, "result")

    # stop will hang if the consumer hasn't acked or requeued messages
    with eventlet.timeout.Timeout(CONSUME_TIMEOUT):
        consumer.stop()

    consumer.queue_consumer.kill()
Esempio n. 8
0
def test_restrict_entrypoints(container_factory, rabbit_config):

    method_called = Mock()

    class OnceProvider(EntrypointProvider):
        """ Entrypoint that spawns a worker exactly once, as soon as
        the service container started.
        """
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs

        def start(self):
            self.container.spawn_worker(self, self.args, self.kwargs)

    @entrypoint
    def once(*args, **kwargs):
        return DependencyFactory(OnceProvider, args, kwargs)

    class ExampleEvent(Event):
        type = "eventtype"

    class Service(object):

        @rpc
        @once("assert not seen")
        def handler_one(self, arg):
            method_called(arg)

        @event_handler('srcservice', 'eventtype')
        def handler_two(self, msg):
            method_called(msg)

    container = container_factory(Service, rabbit_config)

    # disable the entrypoints on handler_one
    restrict_entrypoints(container, "handler_two")
    container.start()

    # verify the rpc entrypoint on handler_one is disabled
    with RpcProxy("service", rabbit_config) as service_proxy:
        with pytest.raises(RemoteError) as exc_info:
            service_proxy.handler_one("msg")
        assert exc_info.value.exc_type == "MethodNotFound"

    # dispatch an event to handler_two
    msg = "msg"
    with event_dispatcher('srcservice', rabbit_config) as dispatch:
        dispatch(ExampleEvent(msg))

    # method_called should have exactly one call, derived from the event
    # handler and not from the disabled @once entrypoint
    with wait_for_call(1, method_called):
        method_called.assert_called_once_with(msg)
Esempio n. 9
0
def test_dispatch(container_factory, rabbit_config):
    config = rabbit_config

    container = container_factory(Service, config)
    container.start()

    msg = "msg"

    with event_dispatcher('srcservice', config) as dispatch:
        dispatch(TestEvent(msg))

        with wait_for_call(1, handler_called):
            handler_called.assert_called_once_with(msg)
Esempio n. 10
0
def test_entrypoint_hook(runner_factory, rabbit_config):

    service_classes = (Service, ServiceA, ServiceB, ServiceC)
    runner = runner_factory(rabbit_config, *service_classes)
    runner.start()

    service_container = get_container(runner, Service)

    event_payload = "msg"
    with entrypoint_hook(service_container, 'handle') as handle:
        handle(event_payload)

        with wait_for_call(1, handle_event):
            handle_event.assert_called_once_with(event_payload)
Esempio n. 11
0
def test_kill_stops_cron(container_factory, tracker):
    class Service(object):
        name = "service"

        @cron('* * * * * *')
        def tick(self):
            tracker()

    container = container_factory(Service, {})
    container.start()

    with wait_for_call(2.0, tracker):
        container.kill()

    eventlet.sleep(2.0)
    assert tracker.call_count == 1
Esempio n. 12
0
def test_busy_check_on_teardown():
    # max_workers needs to be provided, as it's used in a semaphore count
    config = {'max_workers': 4}
    kill_called = Mock()

    class MockedContainer(ServiceContainer):
        def kill(self):
            kill_called()
            super(MockedContainer, self).kill()

    sr = ServiceRunner(config, container_cls=MockedContainer)
    sr.add_service(ExampleService)
    sr.start()
    sr.kill()
    with wait_for_call(5, kill_called) as kill_called_waited:
        assert kill_called_waited.call_count == 1
Esempio n. 13
0
def test_busy_check_on_teardown():
    # max_workers needs to be provided, as it's used in a semaphore count
    config = {'max_workers': 4}
    kill_called = Mock()

    class MockedContainer(ServiceContainer):
        def kill(self):
            kill_called()
            super(MockedContainer, self).kill()

    sr = ServiceRunner(config, container_cls=MockedContainer)
    sr.add_service(ExampleService)
    sr.start()
    sr.kill()
    with wait_for_call(5, kill_called) as kill_called_waited:
        assert kill_called_waited.call_count == 1
Esempio n. 14
0
def test_busy_check_on_teardown():
    # max_workers needs to be provided, as it's used in a semaphore count
    config = MagicMock({'max_workers': 4})
    kill_called = Mock()

    class MockedContainer(ServiceContainer):
        def kill(self, exc):
            kill_called(type(exc))
            super(MockedContainer, self).kill(exc)

    sr = ServiceRunner(config, container_cls=MockedContainer)
    sr.add_service(ExampleService)
    sr.start()
    sr.kill(Exception())
    with wait_for_call(5, kill_called) as kill_called_waited:
        kill_called_waited.assert_called_with(Exception)
Esempio n. 15
0
def test_kill_stops_timer():
    container = create_autospec(ServiceContainer)
    container.service_name = "service"
    container.spawn_managed_thread = spawn_managed_thread

    timer = Timer(interval=0).bind(container, "method")
    timer.setup()
    timer.start()

    with wait_for_call(1, container.spawn_worker):
        timer.kill()

    # unless the timer is dead, the following nap would cause a timer
    # to trigger
    eventlet.sleep(0.1)
    assert container.spawn_worker.call_count == 1
Esempio n. 16
0
def test_kill_stops_timer():
    container = Mock(spec=ServiceContainer)
    container.service_name = "service"
    container.spawn_managed_thread = eventlet.spawn

    timer = TimerProvider(interval=0, config_key=None)
    timer.bind('foobar', container)
    timer.prepare()
    timer.start()

    with wait_for_call(1, container.spawn_worker):
        timer.kill(Exception('time'))

    # unless the timer is dead, the following nap would cause a timer
    # to trigger
    eventlet.sleep(0.1)
    assert container.spawn_worker.call_count == 1
Esempio n. 17
0
def test_kill_stops_timer():
    container = Mock(spec=ServiceContainer)
    container.service_name = "service"
    container.spawn_managed_thread = eventlet.spawn

    timer = TimerProvider(interval=0, config_key=None)
    timer.bind('foobar', container)
    timer.prepare()
    timer.start()

    with wait_for_call(1, container.spawn_worker):
        timer.kill()

    # unless the timer is dead, the following nap would cause a timer
    # to trigger
    eventlet.sleep(0.1)
    assert container.spawn_worker.call_count == 1
Esempio n. 18
0
def test_kill_stops_timer(container_factory, tracker):
    class Service(object):
        name = "service"

        @timer(0)
        def tick(self):
            tracker()

    container = container_factory(Service, {})
    container.start()

    with wait_for_call(1, tracker):
        container.kill()

    # unless the timer is dead, the following nap would cause a timer
    # to trigger
    eventlet.sleep(0.1)
    assert tracker.call_count == 1
Esempio n. 19
0
def test_provider():
    container = create_autospec(ServiceContainer)
    container.service_name = "service"
    container.spawn_managed_thread = spawn_managed_thread

    timer = Timer(interval=0.1).bind(container, "method")
    timer.setup()
    timer.start()

    assert timer.interval == 0.1

    with wait_for_call(1, container.spawn_worker) as spawn_worker:
        with Timeout(1):
            timer.stop()

    # the timer should have stopped and should only have spawned
    # a single worker
    spawn_worker.assert_called_once_with(timer, (), {})
    assert timer.gt.dead
Esempio n. 20
0
def test_provider():
    container = Mock(spec=ServiceContainer)
    container.service_name = "service"
    container.config = Mock()
    container.spawn_managed_thread = eventlet.spawn

    timer = TimerProvider(interval=0, config_key=None)
    timer.bind('foobar', container)
    timer.prepare()

    assert timer.interval == 0

    timer.start()

    with wait_for_call(1, container.spawn_worker) as spawn_worker:
        with Timeout(1):
            timer.stop()

    # the timer should have stopped and should only have spawned
    # a single worker
    spawn_worker.assert_called_once_with(timer, (), {})

    assert timer.gt.dead
Esempio n. 21
0
def test_provider():
    container = Mock(spec=ServiceContainer)
    container.service_name = "service"
    container.config = Mock()
    container.spawn_managed_thread = eventlet.spawn

    timer = TimerProvider(interval=0, config_key=None)
    timer.bind('foobar', container)
    timer.prepare()

    assert timer.interval == 0

    timer.start()

    with wait_for_call(1, container.spawn_worker) as spawn_worker:
        with Timeout(1):
            timer.stop()

    # the timer should have stopped and should only have spawned
    # a single worker
    spawn_worker.assert_called_once_with(timer, (), {})

    assert timer.gt.dead
Esempio n. 22
0
def test_consume_from_rabbit(rabbit_manager, rabbit_config, mock_container):

    vhost = rabbit_config['vhost']

    container = mock_container
    container.shared_extensions = {}
    container.worker_ctx_cls = WorkerContext
    container.service_name = "service"
    container.config = rabbit_config
    container.max_workers = 10

    content_type = 'application/data'
    container.accept = [content_type]

    def spawn_managed_thread(method, identifier=None):
        return eventlet.spawn(method)

    container.spawn_managed_thread = spawn_managed_thread

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

    consumer = Consumer(
        queue=foobar_queue, requeue_on_error=False).bind(container, "publish")

    # prepare and start extensions
    consumer.setup()
    consumer.queue_consumer.setup()
    consumer.start()
    consumer.queue_consumer.start()

    # test queue, exchange and binding created in rabbit
    exchanges = rabbit_manager.get_exchanges(vhost)
    queues = rabbit_manager.get_queues(vhost)
    bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name)

    assert "foobar_ex" in [exchange['name'] for exchange in exchanges]
    assert "foobar_queue" in [queue['name'] for queue in queues]
    assert "foobar_ex" in [binding['source'] for binding in bindings]

    # test message consumed from queue
    container.spawn_worker.return_value = worker_ctx

    headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue'}

    rabbit_manager.publish(
        vhost, foobar_ex.name, '', 'msg',
        properties=dict(headers=headers, content_type=content_type))

    ctx_data = {
        'language': 'en',
        'customheader': 'customvalue',
    }
    with wait_for_call(CONSUME_TIMEOUT, container.spawn_worker) as method:
        method.assert_called_once_with(consumer, ('msg',), {},
                                       context_data=ctx_data,
                                       handle_result=ANY_PARTIAL)
        handle_result = method.call_args[1]['handle_result']

    # ack message
    handle_result(worker_ctx, 'result')

    # stop will hang if the consumer hasn't acked or requeued messages
    with eventlet.timeout.Timeout(CONSUME_TIMEOUT):
        consumer.stop()

    consumer.queue_consumer.kill()
Esempio n. 23
0
def test_consume_from_rabbit(rabbit_manager, rabbit_config, mock_container):

    vhost = rabbit_config['vhost']

    container = mock_container
    container.shared_extensions = {}
    container.worker_ctx_cls = WorkerContext
    container.service_name = "service"
    container.config = rabbit_config
    container.max_workers = 10

    content_type = 'application/data'
    container.accept = [content_type]

    def spawn_managed_thread(method, identifier=None):
        return eventlet.spawn(method)

    container.spawn_managed_thread = spawn_managed_thread

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

    consumer = Consumer(
        queue=foobar_queue, requeue_on_error=False).bind(container, "publish")

    # prepare and start extensions
    consumer.setup()
    consumer.queue_consumer.setup()
    consumer.start()
    consumer.queue_consumer.start()

    # test queue, exchange and binding created in rabbit
    exchanges = rabbit_manager.get_exchanges(vhost)
    queues = rabbit_manager.get_queues(vhost)
    bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name)

    assert "foobar_ex" in [exchange['name'] for exchange in exchanges]
    assert "foobar_queue" in [queue['name'] for queue in queues]
    assert "foobar_ex" in [binding['source'] for binding in bindings]

    # test message consumed from queue
    container.spawn_worker.return_value = worker_ctx

    headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue'}

    rabbit_manager.publish(
        vhost, foobar_ex.name, '', 'msg',
        properties=dict(headers=headers, content_type=content_type))

    ctx_data = {
        'language': 'en',
        'customheader': 'customvalue',
    }
    with wait_for_call(CONSUME_TIMEOUT, container.spawn_worker) as method:
        method.assert_called_once_with(consumer, ('msg',), {},
                                       context_data=ctx_data,
                                       handle_result=ANY_PARTIAL)
        handle_result = method.call_args[1]['handle_result']

    # ack message
    handle_result(worker_ctx, 'result')

    # stop will hang if the consumer hasn't acked or requeued messages
    with eventlet.timeout.Timeout(CONSUME_TIMEOUT):
        consumer.stop()

    consumer.queue_consumer.kill()
Esempio n. 24
0
def test_parallel_executor_submit_makes_call(container):
    to_call = Mock(return_value=99)
    future = ParallelExecutor(container).submit(to_call, 1)
    with wait_for_call(5, to_call) as to_call_waited:
        to_call_waited.assert_called_with(1)
        assert future.result() == 99
Esempio n. 25
0
def test_parallel_executor_submit_makes_call(container):
    to_call = Mock(return_value=99)
    future = ParallelExecutor(container).submit(to_call, 1)
    with wait_for_call(5, to_call) as to_call_waited:
        to_call_waited.assert_called_with(1)
        assert future.result() == 99
Esempio n. 26
0
def test_consume_from_rabbit(rabbit_manager, rabbit_config):

    vhost = rabbit_config['vhost']

    container = Mock(spec=ServiceContainer)
    container.worker_ctx_cls = CustomWorkerContext
    container.service_name = "service"
    container.config = rabbit_config
    container.max_workers = 10

    def spawn_thread(method, protected):
        return eventlet.spawn(method)

    container.spawn_managed_thread = spawn_thread

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

    factory = DependencyFactory(ConsumeProvider,
                                queue=foobar_queue,
                                requeue_on_error=False)
    consumer = factory.create_and_bind_instance("injection_name", container)

    # prepare and start dependencies
    consumer.prepare()
    consumer.queue_consumer.prepare()
    consumer.start()
    consumer.queue_consumer.start()

    # test queue, exchange and binding created in rabbit
    exchanges = rabbit_manager.get_exchanges(vhost)
    queues = rabbit_manager.get_queues(vhost)
    bindings = rabbit_manager.get_queue_bindings(vhost, foobar_queue.name)

    assert "foobar_ex" in [exchange['name'] for exchange in exchanges]
    assert "foobar_queue" in [queue['name'] for queue in queues]
    assert "foobar_ex" in [binding['source'] for binding in bindings]

    # test message consumed from queue
    container.spawn_worker.return_value = worker_ctx

    headers = {'nameko.language': 'en', 'nameko.customheader': 'customvalue'}
    rabbit_manager.publish(vhost,
                           foobar_ex.name,
                           '',
                           'msg',
                           properties=dict(headers=headers))

    ctx_data = {
        'language': 'en',
        'customheader': 'customvalue',
    }
    with wait_for_call(CONSUME_TIMEOUT, container.spawn_worker) as method:
        method.assert_called_once_with(consumer, ('msg', ), {},
                                       context_data=ctx_data,
                                       handle_result=ANY_PARTIAL)
        handle_result = method.call_args[1]['handle_result']

    # ack message
    handle_result(worker_ctx, 'result')

    # stop will hang if the consumer hasn't acked or requeued messages
    with eventlet.timeout.Timeout(CONSUME_TIMEOUT):
        consumer.stop()

    consumer.queue_consumer.kill()