Example #1
0
async def test_use_new_output_when_reconnected():
    first_output = TeeQueue()
    second_output = TeeQueue()

    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)

    await confirm_subscription(convo,
                               subscription_id=convo.name,
                               queue=first_output)
    event_id = uuid4()

    subscription = await convo.result

    await confirm_subscription(convo,
                               subscription_id=convo.name,
                               queue=second_output)
    await subscription.ack(stub_event(event_id))

    ack = await second_output.get()

    assert ack.command == TcpCommand.PersistentSubscriptionAckEvents
    assert ack.conversation_id == convo.conversation_id

    assert not first_output.items
Example #2
0
async def test_dropped_on_connect():
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)

    with pytest.raises(exn.SubscriptionCreationFailed):
        await drop_subscription(convo, SubscriptionDropReason.Unsubscribed)
        await convo.result
Example #3
0
async def test_subscription_unsubscribed_midway():
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)
    await confirm_subscription(convo)
    subscription = await convo.result

    await drop_subscription(convo, SubscriptionDropReason.Unsubscribed)
    with pytest.raises(StopAsyncIteration):
        await subscription.events.anext()
Example #4
0
async def test_subscription_failed_midway():
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)
    await confirm_subscription(convo)
    subscription = await convo.result

    await drop_subscription(convo, SubscriptionDropReason.AccessDenied)
    with pytest.raises(exn.SubscriptionFailed):
        await subscription.events.anext()
Example #5
0
async def test_confirmation():
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)

    await confirm_subscription(convo,
                               subscription_id="my-subscription",
                               event_number=10)

    subscription = convo.result.result()

    assert subscription.name == "my-subscription"
    assert subscription.stream == "my-stream"
    assert subscription.last_event_number == 10
Example #6
0
async def test_connect_request():

    output = TeeQueue()
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)
    await convo.start(output)
    [request] = output.items

    payload = proto.ConnectToPersistentSubscription()
    payload.ParseFromString(request.payload)

    assert request.command == TcpCommand.ConnectToPersistentSubscription
    assert payload.subscription_id == "my-subscription"
    assert payload.event_stream_id == "my-stream"
    assert payload.allowed_in_flight_messages == 57
Example #7
0
async def test_when_connector_reconnected_retry_active_conversations():
    """

    if we give the dispatcher a new output queue, he should restart his active
    conversations.
    """

    dispatcher = MessageDispatcher()
    out_queue = TeeQueue()
    conversation = ConnectPersistentSubscription("my-sub", "my-stream")
    await dispatcher.start_conversation(conversation)

    await dispatcher.write_to(out_queue)

    message = await out_queue.get()

    assert message.command == TcpCommand.ConnectToPersistentSubscription
Example #8
0
async def test_when_running_a_persistent_subscription():
    """
    We ought to be able to connect a persistent subscription, and receive
    some events.
    """
    dispatcher = MessageDispatcher()
    out_queue = TeeQueue()
    conversation = ConnectPersistentSubscription("my-sub", "my-stream")
    first_msg = persistent_subscription_confirmed(conversation.conversation_id,
                                                  "my-sub")

    # The subscription confirmed message should result in our having a
    # PersistentSubscription to play with.

    future = await dispatcher.start_conversation(conversation)
    await dispatcher.dispatch(first_msg, out_queue)
    subscription = await asyncio.wait_for(future, 1)

    # A subsequent PersistentSubscriptionStreamEventAppeared message should
    # enqueue the event onto our iterator
    await dispatcher.dispatch(
        subscription_event_appeared(conversation.conversation_id,
                                    NewEvent("event", data={"x": 2})),
        out_queue,
    )

    event = await anext(subscription.events)
    assert event.json()["x"] == 2

    # Acknowledging the event should place an Ack message on the out_queue

    await subscription.ack(event)

    expected_payload = proto.PersistentSubscriptionAckEvents()
    expected_payload.subscription_id = "my-sub"
    expected_payload.processed_event_ids.append(event.event.id.bytes_le)
    expected_message = OutboundMessage(
        conversation.conversation_id,
        TcpCommand.PersistentSubscriptionAckEvents,
        expected_payload.SerializeToString(),
    )

    ack = await out_queue.get()

    assert ack == expected_message
Example #9
0
async def test_when_a_persistent_subscription_fails_on_connection():
    """
    If a persistent subscription fails to connect we should raise the error
    to the caller. We're going to use an authentication error here and leave
    the vexing issue of NotHandled for another day.
    """
    dispatcher = MessageDispatcher()
    conversation = ConnectPersistentSubscription("my-sub", "my-stream")
    future = await dispatcher.start_conversation(conversation)

    await dispatcher.dispatch(
        persistent_subscription_dropped(conversation.conversation_id,
                                        SubscriptionDropReason.AccessDenied),
        None,
    )

    with pytest.raises(SubscriptionCreationFailed):
        await asyncio.wait_for(future, 1)
Example #10
0
async def test_stream_event_appeared():
    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)

    event_id = uuid4()
    await confirm_subscription(convo)
    response = event_appeared(event_id)

    await convo.respond_to(
        InboundMessage(
            uuid4(),
            TcpCommand.PersistentSubscriptionStreamEventAppeared,
            response.SerializeToString(),
        ),
        None,
    )

    subscription = await convo.result
    event = await subscription.events.anext()

    assert event.event.id == event_id
Example #11
0
async def test_when_a_persistent_subscription_is_unsubscribed():
    """
    If a persistent subscription gets unsubscribed while processing
    we should log an info and exit gracefully
    """
    dispatcher = MessageDispatcher()
    conversation = ConnectPersistentSubscription("my-sub", "my-stream")
    future = await dispatcher.start_conversation(conversation)

    await dispatcher.dispatch(
        persistent_subscription_confirmed(conversation.conversation_id,
                                          "my-sub"), None)

    subscription = await asyncio.wait_for(future, 1)

    await dispatcher.dispatch(
        persistent_subscription_dropped(conversation.conversation_id,
                                        SubscriptionDropReason.Unsubscribed),
        None,
    )

    [] = [e async for e in subscription.events]
Example #12
0
async def test_acknowledge_event():
    output = TeeQueue()

    convo = ConnectPersistentSubscription("my-subscription",
                                          "my-stream",
                                          max_in_flight=57)

    await confirm_subscription(convo, subscription_id=convo.name, queue=output)
    event_id = uuid4()

    subscription = await convo.result
    await subscription.ack(stub_event(event_id))

    ack = await output.get()

    assert ack.command == TcpCommand.PersistentSubscriptionAckEvents
    assert ack.conversation_id == convo.conversation_id

    expected_payload = proto.PersistentSubscriptionAckEvents()
    expected_payload.subscription_id = convo.name
    expected_payload.processed_event_ids.append(event_id.bytes_le)

    assert expected_payload.SerializeToString() == ack.payload
Example #13
0
async def test_when_a_persistent_subscription_fails():
    """
    If a persistent subscription fails with something non-recoverable then
    we should raise the error to the caller
    """
    dispatcher = MessageDispatcher()
    conversation = ConnectPersistentSubscription("my-sub", "my-stream")
    future = await dispatcher.start_conversation(conversation)

    await dispatcher.dispatch(
        persistent_subscription_confirmed(conversation.conversation_id,
                                          "my-sub"), None)

    subscription = await asyncio.wait_for(future, 1)

    await dispatcher.dispatch(
        persistent_subscription_dropped(conversation.conversation_id,
                                        SubscriptionDropReason.AccessDenied),
        None,
    )

    with pytest.raises(SubscriptionFailed):
        await anext(subscription.events)
async def test_read_deleted_event_processing():
    """
    When a stream with events is deleted from evenstore,
    the events don"t disappear from projections.
    Projections hold a link to a deleted event and eventstore would
    return object with a link a but no event data.

    This test case check when such deleted event is given to
    persistent subscription, subscription will be able to build an
    event object, which then could be acknowledged by the client service.
    """

    async with message_reader() as (stream, messages, _):

        stream.feed_data(deleted_event)
        received = await messages.get()

        assert received.command == TcpCommand.PersistentSubscriptionStreamEventAppeared
        assert received.length == 185

        convo = ConnectPersistentSubscription("random-subscription",
                                              "random-stream",
                                              max_in_flight=57)

        await confirm_subscription(convo)
        await convo.respond_to(received, None)

        subscription = await convo.result
        event = await subscription.events.anext()

        assert event.id == uuid.UUID("7a8c472c-c92e-4520-990d-a749f6020ba1")
        assert event.data == b"0@some"
        assert event.event_number == 0
        assert event.link == None
        assert event.event != None
        assert event.stream == "$et-turtle"