Пример #1
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()
Пример #2
0
def test_nested_dependencies(rabbit_config):

    container = Mock()
    container.config = rabbit_config

    bar_factory = DependencyFactory(BarProvider)
    bar = bar_factory.create_and_bind_instance("bar", container)

    dependencies = list(bar.nested_dependencies)
    assert len(dependencies) == 2
    assert dependencies[0].container == dependencies[1].container == container
    assert set([type(dep) for dep in dependencies]) == set([SharedProvider, NestedProvider])
Пример #3
0
def test_nested_dependencies(rabbit_config):

    container = Mock()
    container.config = rabbit_config

    bar_factory = DependencyFactory(BarProvider)
    bar = bar_factory.create_and_bind_instance("bar", container)

    dependencies = list(bar.nested_dependencies)
    assert len(dependencies) == 2
    assert dependencies[0].container == dependencies[1].container == container
    assert set([type(dep) for dep in dependencies]) == set([SharedProvider,
                                                           NestedProvider])
Пример #4
0
def consume(queue, requeue_on_error=False):
    """
    Decorates a method as a message consumer.

    Messages from the queue will be deserialized depending on their content
    type and passed to the the decorated method.
    When the consumer method returns without raising any exceptions,
    the message will automatically be acknowledged.
    If any exceptions are raised during the consumption and
    `requeue_on_error` is True, the message will be requeued.

    Example::

        @consume(...)
        def handle_message(self, body):

            if not self.spam(body):
                raise Exception('message will be requeued')

            self.shrub(body)

    Args:
        queue: The queue to consume from.
    """
    return DependencyFactory(ConsumeProvider, queue, requeue_on_error)
Пример #5
0
def rpc(expected_exceptions=()):
    """ Mark a method to be exposed over rpc

    :Parameters:
        expected_exceptions : exception class or tuple of exception classes
            Stashed on the provider instance for later inspection by other
            dependencies in the worker lifecycle. Use for exceptions caused
            by the caller (e.g. bad arguments).
    """
    return DependencyFactory(RpcProvider, expected_exceptions)
Пример #6
0
def file_logger(path=None):
    """ User docs for file logger
    """
    if path is not None:
        check_path = path
        if not os.path.exists(check_path):
            check_path = os.path.dirname(path)
        if not os.access(check_path, os.W_OK):
            raise InvalidPath("File or dir not writable: {}".format(path))

    return DependencyFactory(LogFile, path)
Пример #7
0
def timer(interval=None, config_key=None):
    '''
    Decorates a method as a timer, which will be called every `interval` sec.

    Either the `interval` or the `config_key` have to be provided or both.
    If the `config_key` is given the value for that key in the config will be
    used as the interval otherwise the `interval` provided will be used.

    Example::

        class Foobar(object):

            @timer(interval=5, config_key='foobar_interval')
            def handle_timer(self):
                self.shrub(body)
    '''
    return DependencyFactory(TimerProvider, interval, config_key)
Пример #8
0
 def injection_provider():
     return DependencyFactory(ExampleProvider)
Пример #9
0
def shopping_basket():
    """ A shopping basket tied to the current user.
    """
    return DependencyFactory(ShoppingBasket)
Пример #10
0
def custom_value():
    return DependencyFactory(ContextDataProvider, CUSTOM_CONTEXT_KEY)
Пример #11
0
def stdout():
    return DependencyFactory(StdoutProvider)
Пример #12
0
def foobar(*args, **kwargs):
    """foobar-doc"""
    return DependencyFactory(FooProvider, *args, **kwargs)
Пример #13
0
def foobar():
    return DependencyFactory(CallCollectingEntrypointProvider)
Пример #14
0
def auth_token():
    return DependencyFactory(ContextDataProvider, AUTH_TOKEN_CONTEXT_KEY)
Пример #15
0
def context_reader():
    return DependencyFactory(ContextReader)
Пример #16
0
def user_id():
    return DependencyFactory(ContextDataProvider, USER_ID_CONTEXT_KEY)
Пример #17
0
def user_agent():
    return DependencyFactory(ContextDataProvider, USER_AGENT_CONTEXT_KEY)
Пример #18
0
def language():
    return DependencyFactory(ContextDataProvider, LANGUAGE_CONTEXT_KEY)
Пример #19
0
def rpc():
    return DependencyFactory(NovaRpcProvider)
Пример #20
0
def nova_rpc_consumer():
    return DependencyFactory(NovaRpcConsumer)
Пример #21
0
def shared_provider(*args, **kwargs):
    return DependencyFactory(SharedProvider, *args, **kwargs)
Пример #22
0
def translator():
    return DependencyFactory(Translator)
Пример #23
0
def nested_provider(*args, **kwargs):
    return DependencyFactory(NestedProvider, *args, **kwargs)
Пример #24
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()
Пример #25
0
def barfoo(*args, **kwargs):
    return DependencyFactory(BarProvider, *args, **kwargs)
Пример #26
0
def event_dispatcher():
    return DependencyFactory(EventDispatcher)
Пример #27
0
def call_collector():
    return DependencyFactory(CallCollectingInjectionProvider)
Пример #28
0
def event_handler(service_name, event_type, handler_type=SERVICE_POOL,
                  reliable_delivery=True, requeue_on_error=False,
                  event_handler_cls=EventHandler):
    r"""
    Decorate a method as a handler of ``event_type`` events on the service
    called ``service_name``. ``event_type`` must be either a subclass of
    :class:`~.Event` with a class attribute ``type`` or a string matching the
    value of this attribute.
    ``handler_type`` determines the behaviour of the handler:

        - ``events.SERVICE_POOL``:

            Event handlers will be pooled by service type and handler-method
            and one from each pool will receive the event. ::

                           .-[queue]- (service X handler-method-1)
                          /
                exchange o --[queue]- (service X handler-method-2)
                          \
                           \          (service Y(instance 1) hanlder-method)
                            \       /
                             [queue]
                                    \
                                      (service Y(instance 2) handler-method)


        - ``events.SINGLETON``:

            Events will be received by only one registered handler.
            If requeued on error, they may be given to a different
            handler. ::

                                       (service X handler-method)
                                     /
                exchange o -- [queue]
                                     \
                                       (service Y handler-method)

        - ``events.BROADCAST``:
            Events will be received by every handler. This  will broadcast
            to every service instance, not just every service type
            - use wisely! ::

                            [queue]- (service X(instance 1) handler-method)
                          /
                exchange o - [queue]- (service X(instance 2) handler-method)
                          \
                            [queue]- (service Y handler-method)

    If ``requeue_on_error``, handlers will return the event to the queue if an
    error occurs while handling it. Defaults to False.

    If ``reliable_delivery``, events will be kept in the queue until there is
    a handler to consume them. Defaults to ``True``.

    ``event_handler_cls`` may be specified to use a different EventHandler
        (sub)class for custom behaviour.

    Raises an ``EventHandlerConfigurationError`` if the ``handler_type``
    is set to ``BROADCAST`` and ``reliable_delivery`` is set to ``True``.
    """

    if reliable_delivery and handler_type is BROADCAST:
        raise EventHandlerConfigurationError(
            "Broadcast event handlers cannot be configured with reliable "
            "delivery.")

    if isinstance(event_type, type) and issubclass(event_type, Event):
        event_type = event_type.type
    elif not isinstance(event_type, basestring):
        raise TypeError(
            'event_type must be either a nameko.events.Event subclass or a '
            'string a string matching the Event.type value. '
            'Got {}'.format(type(event_type).__name__))

    return DependencyFactory(event_handler_cls, service_name, event_type,
                             handler_type, reliable_delivery, requeue_on_error)
Пример #29
0
def dummy():
    return DependencyFactory(DummyEntrypoint)
Пример #30
0
def once(*args, **kwargs):
    """ Fire the decorated entrypoint once, immediately.
    """
    return DependencyFactory(OnceProvider, args, kwargs)
Пример #31
0
def worker_logger():
    return DependencyFactory(WorkerErrorLogger)
Пример #32
0
def stdin():
    """ Receive messages from `sys.stdin`
    """
    return DependencyFactory(StdinProvider)