示例#1
0
def entrypoint_waiter(container, entrypoint, timeout=30):
    """Helper to wait for entrypoints to fire (and complete)

    Usage::

        container = ServiceContainer(ExampleService, config)
        with entrypoint_waiter(container, 'example_handler'):
            ...  # e.g. rpc call that will result in handler being called
    """

    waiter = EntrypointWaiter(entrypoint)
    if not get_extension(container, Entrypoint, method_name=entrypoint):
        raise RuntimeError("{} has no entrypoint `{}`".format(
            container.service_name, entrypoint))
    if get_extension(container, EntrypointWaiter, entrypoint=entrypoint):
        raise RuntimeError(
            "Waiter already registered for {}".format(entrypoint))

    # can't mess with dependencies while container is running
    wait_for_worker_idle(container)
    container.dependencies.add(waiter)

    try:
        yield
        with eventlet.Timeout(timeout):
            waiter.wait()
    finally:
        wait_for_worker_idle(container)
        container.dependencies.remove(waiter)
示例#2
0
def entrypoint_waiter(container, entrypoint, timeout=30):
    """Helper to wait for entrypoints to fire (and complete)

    Usage::

        container = ServiceContainer(ExampleService, config)
        with entrypoint_waiter(container, 'example_handler'):
            ...  # e.g. rpc call that will result in handler being called
    """

    waiter = EntrypointWaiter(entrypoint)
    if not get_extension(container, Entrypoint, method_name=entrypoint):
        raise RuntimeError("{} has no entrypoint `{}`".format(
            container.service_name, entrypoint))
    if get_extension(container, EntrypointWaiter, entrypoint=entrypoint):
        raise RuntimeError("Waiter already registered for {}".format(
            entrypoint))

    # can't mess with dependencies while container is running
    wait_for_worker_idle(container)
    container.dependencies.add(waiter)

    try:
        yield
        exc = waiter.Timeout(
            "Entrypoint {}.{} failed to complete within {} seconds".format(
                container.service_name, entrypoint, timeout)
        )
        with eventlet.Timeout(timeout, exception=exc):
            waiter.wait()
    finally:
        wait_for_worker_idle(container)
        container.dependencies.remove(waiter)
示例#3
0
def test_expected_exceptions_integration(container_factory, rabbit_config):
    container = container_factory(ExampleService, rabbit_config)
    container.start()

    worker_logger = get_dependency(container, WorkerErrorLogger)

    with entrypoint_hook(container, 'broken') as broken:
        with pytest.raises(ExampleError):
            broken()

    with entrypoint_hook(container, 'very_broken') as very_broken:
        with pytest.raises(AttributeError):
            very_broken()

    wait_for_worker_idle(container)  # wait for worker lifecycle to complete
    assert worker_logger.expected == {'broken': ExampleError}
    assert worker_logger.unexpected == {'very_broken': AttributeError}
示例#4
0
文件: test_rpc.py 项目: gwongz/nameko
def test_expected_exceptions_integration(container_factory, rabbit_config):
    container = container_factory(ExampleService, rabbit_config)
    container.start()

    worker_logger = get_extension(container, WorkerErrorLogger)

    with entrypoint_hook(container, 'broken') as broken:
        with pytest.raises(ExampleError):
            broken()

    with entrypoint_hook(container, 'very_broken') as very_broken:
        with pytest.raises(AttributeError):
            very_broken()

    wait_for_worker_idle(container)  # wait for worker lifecycle to complete
    assert worker_logger.expected == {'broken': ExampleError}
    assert worker_logger.unexpected == {'very_broken': AttributeError}
示例#5
0
def test_handle_result(container_factory, rabbit_manager, rabbit_config):
    """ Verify that `handle_result` can modify the return values of the worker,
    such that other dependencies see the updated values.
    """
    container = container_factory(ExampleService, rabbit_config)
    container.start()

    with RpcProxy('exampleservice', rabbit_config) as proxy:

        assert proxy.echo("hello") == "hello"
        with pytest.raises(RemoteError) as exc:
            proxy.unserializable()
        assert "is not JSON serializable" in exc.value.message

    wait_for_worker_idle(container)

    # verify CollectorInjection sees values returned from `handle_result`
    assert worker_result_called == [
        ("hello", None),
        ("something went wrong", (TypeError, ANY, ANY)),
    ]
示例#6
0
def test_wait_for_worker_idle(container_factory, rabbit_config):

    event = Event()

    class Service(object):
        name = "service"

        @rpc
        def wait_for_event(self):
            event.wait()

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

    max_workers = DEFAULT_MAX_WORKERS

    # verify nothing running
    assert container._worker_pool.free() == max_workers
    with eventlet.Timeout(1):
        wait_for_worker_idle(container)

    # spawn a worker
    wait_for_event = get_extension(container, Rpc)
    container.spawn_worker(wait_for_event, [], {})

    # verify that wait_for_worker_idle does not return while worker active
    assert container._worker_pool.free() == max_workers - 1
    gt = eventlet.spawn(wait_for_worker_idle, container)
    assert not gt.dead  # still waiting

    # verify that wait_for_worker_idle raises when it times out
    with pytest.raises(eventlet.Timeout):
        wait_for_worker_idle(container, timeout=0)

    # complete the worker, verify previous wait_for_worker_idle completes
    event.send()
    with eventlet.Timeout(1):
        gt.wait()
    assert container._worker_pool.free() == max_workers
示例#7
0
def test_handle_result(container_factory, rabbit_manager, rabbit_config):
    """ Verify that `handle_result` can modify the return values of the worker,
    such that other dependencies see the updated values.
    """
    container = container_factory(ExampleService, rabbit_config)
    container.start()

    with ServiceRpcProxy('exampleservice', rabbit_config) as proxy:

        assert proxy.echo("hello") == "hello"

        with pytest.raises(RemoteError) as exc:
            proxy.unserializable()
        assert "is not JSON serializable" in str(exc.value)

    wait_for_worker_idle(container)

    # verify ResultCollector sees values returned from `handle_result`
    assert worker_result_called == [
        ("hello", None),
        ("something went wrong", (TypeError, ANY, ANY)),
    ]
示例#8
0
def test_wait_for_worker_idle(container_factory, rabbit_config):

    event = Event()

    class Service(object):
        name = "service"

        @rpc
        def wait_for_event(self):
            event.wait()

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

    max_workers = DEFAULT_MAX_WORKERS

    # TODO: pytest.warns is not supported until pytest >= 2.8.0, whose
    # `testdir` plugin is not compatible with eventlet on python3 --
    # see https://github.com/mattbennett/eventlet-pytest-bug
    with warnings.catch_warnings(record=True) as ws:
        wait_for_worker_idle(container)
        assert len(ws) == 1
        assert issubclass(ws[-1].category, DeprecationWarning)

    # verify nothing running
    assert container._worker_pool.free() == max_workers
    with eventlet.Timeout(1):
        wait_for_worker_idle(container)

    # spawn a worker
    wait_for_event = get_extension(container, Rpc)
    container.spawn_worker(wait_for_event, [], {})

    # verify that wait_for_worker_idle does not return while worker active
    assert container._worker_pool.free() == max_workers - 1
    gt = eventlet.spawn(wait_for_worker_idle, container)
    assert not gt.dead  # still waiting

    # verify that wait_for_worker_idle raises when it times out
    with pytest.raises(eventlet.Timeout):
        wait_for_worker_idle(container, timeout=0)

    # complete the worker, verify previous wait_for_worker_idle completes
    event.send()
    with eventlet.Timeout(1):
        gt.wait()
    assert container._worker_pool.free() == max_workers