async def test_single_node_mark_failed():
    """
    The SingleNodeDiscovery should raise DiscoveryFailed if we ask for a node
    after calling mark_failed.
    """

    node = NodeService("2.3.4.5", 1234, None)
    discoverer = SingleNodeDiscovery(node)

    assert await discoverer.discover() == node

    discoverer.mark_failed(node)

    with pytest.raises(DiscoveryFailed):
        await discoverer.discover()
Beispiel #2
0
async def test_when_connecting_to_a_server(event_loop):
    """
    When we connect to a server, the protocol should begin sending the
    pending messages held by the dispatcher.

    When it receives an InboundMessage from the MessageReader, it should call
    the "dispatch" method of the Dispatcher.
    """

    addr = NodeService("localhost", 8338, None)

    async with EchoServer(addr, event_loop):

        dispatcher = SpyDispatcher()
        connector = Connector(SingleNodeDiscovery(addr),
                              dispatcher,
                              loop=event_loop)

        ping = Ping()

        await dispatcher.start_conversation(ping)

        await connector.start()
        await connector_event(connector.connected)
        roundtripped_message = await dispatcher.received.get()

        assert roundtripped_message.conversation_id == ping.conversation_id

        await connector.stop()
Beispiel #3
0
async def test_when_three_heartbeats_fail_in_a_row(event_loop):
    """
    We're going to set up a separate heartbeat loop to send heartbeat requests
    to the server. If three of those heartbeats timeout in a row, we'll put a
    reconnection request on the queue.
    """

    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    dispatcher = SpyDispatcher()
    connector = Connector(SingleNodeDiscovery(addr),
                          dispatcher,
                          loop=event_loop,
                          ctrl_queue=queue)

    async with EchoServer(addr, event_loop):
        await connector.start()
        [connect, connected] = await queue.next_event(count=2)
        assert connect.command == ConnectorCommand.Connect
        assert connected.command == ConnectorCommand.HandleConnectionOpened

        connector.heartbeat_failed()
        connector.heartbeat_failed()
        connector.heartbeat_failed()

        [hb1, hb2, hb3, connection_closed,
         reconnect] = await queue.next_event(count=5)

        assert connection_closed.command == ConnectorCommand.HandleConnectionClosed
        assert reconnect.command == ConnectorCommand.Connect

    await connector.stop()
Beispiel #4
0
async def test_when_restarting_a_running_connector(event_loop):
    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    dispatcher = SpyDispatcher()
    connector = Connector(
        SingleNodeDiscovery(addr, DiscoveryRetryPolicy()),
        dispatcher,
        loop=event_loop,
        ctrl_queue=queue,
    )

    async with EchoServer(addr, event_loop):
        await connector.start()

        [connect, connected] = await queue.next_event(count=2)

        assert connected.command == ConnectorCommand.HandleConnectionOpened
        await connector_event(connector.connected)

        await connector.reconnect(connector.target_node)

        [connect, closed, b, c, d, connected] = await queue.next_event(count=6)

        assert closed.command == ConnectorCommand.HandleConnectionClosed
        assert connect.command == ConnectorCommand.Connect
        assert connected.command == ConnectorCommand.HandleConnectionOpened

        await connector.stop()
Beispiel #5
0
async def test_when_the_connection_fails_with_an_error(event_loop):
    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    dispatcher = SpyDispatcher()
    connector = Connector(
        SingleNodeDiscovery(addr, DiscoveryRetryPolicy()),
        dispatcher,
        loop=event_loop,
        ctrl_queue=queue,
    )

    async with EchoServer(addr, event_loop):

        await connector.start()
        [connect, connected] = await queue.next_event(count=2)

        exn = ValueError()
        connector.connection_lost(exn)

        [connection_failed] = await queue.next_event(count=1)

        assert connection_failed.command == ConnectorCommand.HandleConnectionFailed
        assert connection_failed.data is exn

        await connector.stop()
Beispiel #6
0
async def test_when_restarting_a_stopped_connector(event_loop):
    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    dispatcher = SpyDispatcher()
    connector = Connector(SingleNodeDiscovery(addr),
                          dispatcher,
                          loop=event_loop,
                          ctrl_queue=queue)

    async with EchoServer(addr, event_loop):
        await connector.reconnect()
        [connect, connected] = await queue.next_event(count=2)

        assert connect.command == ConnectorCommand.Connect
        assert connected.command == ConnectorCommand.HandleConnectionOpened
        await connector_event(connector.connected)

        await connector.stop()
Beispiel #7
0
async def test_when_a_server_disconnects(event_loop):
    """
    Usually, when eventstore goes away, we'll get an EOF on the transport.
    If that happens, we should raise a disconnected event.

    We should also place a reconnection message on the control queue.
    """

    addr = NodeService("localhost", 8338, None)
    queue = TeeQueue()

    dispatcher = SpyDispatcher()
    connector = Connector(
        SingleNodeDiscovery(addr, DiscoveryRetryPolicy()),
        dispatcher,
        loop=event_loop,
        ctrl_queue=queue,
    )
    raised_disconnected_event = asyncio.Future(loop=event_loop)

    def on_disconnected():
        raised_disconnected_event.set_result(True)

    connector.disconnected.append(on_disconnected)

    async with EchoServer(addr, event_loop) as server:

        await connector.start()
        connect = await queue.next_event()
        assert connect.command == ConnectorCommand.Connect

        connected = await queue.next_event()
        assert connected.command == ConnectorCommand.HandleConnectionOpened

        server.stop()

        disconnect = await queue.next_event()
        assert disconnect.command == ConnectorCommand.HandleConnectionFailed

        reconnect = await queue.next_event()
        assert reconnect.command == ConnectorCommand.Connect

    assert raised_disconnected_event.result() is True
    await connector.stop()
Beispiel #8
0
async def test_when_a_heartbeat_succeeds(event_loop):
    """
    If one of our heartbeats succeeds, we should reset our counter.
    Ergo, if we have two failures, followed by a success, followed
    by two failures, we should not reset the connection.
    """

    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    dispatcher = SpyDispatcher()
    connector = Connector(
        SingleNodeDiscovery(addr, DiscoveryRetryPolicy()),
        dispatcher,
        loop=event_loop,
        ctrl_queue=queue,
    )

    async with EchoServer(addr, event_loop):
        await connector.start()
        [connect, connected] = await queue.next_event(count=2)
        assert connect.command == ConnectorCommand.Connect
        assert connected.command == ConnectorCommand.HandleConnectionOpened

        connector.heartbeat_failed()
        connector.heartbeat_failed()

        [hb1, hb2] = await queue.next_event(count=2)
        assert connector.heartbeat_failures == 2

        connector.heartbeat_received("Foo")

        connector.heartbeat_failed()
        connector.heartbeat_failed()

        [success, hb3, hb4] = await queue.next_event(count=3)

        assert connector.heartbeat_failures == 2
        assert success.command == ConnectorCommand.HandleHeartbeatSuccess
        assert hb3.command == ConnectorCommand.HandleHeartbeatFailed
        assert hb4.command == ConnectorCommand.HandleHeartbeatFailed

        await connector.stop()
Beispiel #9
0
async def test_when_discovery_fails_on_reconnection(event_loop):
    """
    If we can't retry our current node any more, and we can't discover a new one
    then it's game over and we should raise the stopped event.
    """
    class never_retry:
        def __init__(self):
            self.recorded = None

        def should_retry(self, _):
            return self.recorded is None

        def record_failure(self, node):
            self.recorded = node

        async def wait(self, node):
            ...

    wait_for_stopped = asyncio.Future()

    def on_stopped(exn):
        wait_for_stopped.set_result(exn)

    queue = TeeQueue()
    addr = NodeService("localhost", 8338, None)
    policy = never_retry()
    dispatcher = SpyDispatcher()
    connector = Connector(SingleNodeDiscovery(addr, policy),
                          dispatcher,
                          loop=event_loop,
                          ctrl_queue=queue)

    connector.stopped.append(on_stopped)

    await connector.start()
    [connect, connection_failed] = await queue.next_event(count=2)

    [failed] = await asyncio.wait_for(queue.next_event(count=1), 2)
    assert failed.command == ConnectorCommand.HandleConnectorFailed
    assert policy.recorded == addr
    assert isinstance(await wait_for_stopped, DiscoveryFailed)