async def accepts_type_definition_with_async_subscribe_function():
        pubsub = SimplePubSub()

        async def get_subscriber(*_args):
            await asyncio.sleep(0)
            return pubsub.get_subscriber()

        schema = GraphQLSchema(
            query=QueryType,
            subscription=GraphQLObjectType(
                "Subscription",
                {
                    "importantEmail": GraphQLField(
                        GraphQLString, subscribe=get_subscriber
                    )
                },
            ),
        )

        subscription = await subscribe(
            schema,
            parse(
                """
            subscription {
              importantEmail
            }
            """
            ),
        )

        pubsub.emit({"importantEmail": {}})

        await anext(subscription)
    async def accepts_multiple_subscription_fields_defined_in_schema():
        pubsub = SimplePubSub()
        subscription_type_multiple = GraphQLObjectType(
            "Subscription",
            {
                "importantEmail": GraphQLField(EmailEventType),
                "nonImportantEmail": GraphQLField(EmailEventType),
            },
        )

        test_schema = GraphQLSchema(
            query=QueryType, subscription=subscription_type_multiple
        )

        subscription = await create_subscription(pubsub, test_schema)

        assert isinstance(subscription, MapAsyncIterator)

        pubsub.emit(
            {
                "from": "*****@*****.**",
                "subject": "Alright",
                "message": "Tests are good",
                "unread": True,
            }
        )

        await anext(subscription)
    async def event_order_is_correct_for_multiple_publishes():
        pubsub = SimplePubSub()
        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        payload = anext(subscription)

        # A new email arrives!
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Message",
            "message": "Tests are good",
            "unread": True,
        }) is True)

        # A new email arrives!
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Message 2",
            "message": "Tests are good 2",
            "unread": True,
        }) is True)

        assert await payload == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Message"
                    },
                    "inbox": {
                        "unread": 2,
                        "total": 3
                    },
                }
            },
            None,
        )

        payload = anext(subscription)

        assert await payload == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Message 2"
                    },
                    "inbox": {
                        "unread": 2,
                        "total": 3
                    },
                }
            },
            None,
        )
    async def produces_a_payload_when_there_are_multiple_events():
        pubsub = SimplePubSub()
        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        payload = anext(subscription)

        # A new email arrives!
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Alright",
            "message": "Tests are good",
            "unread": True,
        }) is True)

        assert await payload == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Alright"
                    },
                    "inbox": {
                        "unread": 1,
                        "total": 2
                    },
                }
            },
            None,
        )

        payload = anext(subscription)

        # A new email arrives!
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Alright 2",
            "message": "Tests are good 2",
            "unread": True,
        }) is True)

        assert await payload == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Alright 2"
                    },
                    "inbox": {
                        "unread": 2,
                        "total": 3
                    },
                }
            },
            None,
        )
    async def should_not_trigger_when_subscription_is_thrown():
        pubsub = SimplePubSub()
        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        payload = anext(subscription)

        # A new email arrives!
        assert (
            pubsub.emit(
                {
                    "from": "*****@*****.**",
                    "subject": "Alright",
                    "message": "Tests are good",
                    "unread": True,
                }
            )
            is True
        )

        assert await payload == (
            {
                "importantEmail": {
                    "email": {"from": "*****@*****.**", "subject": "Alright"},
                    "inbox": {"unread": 1, "total": 2},
                }
            },
            None,
        )

        payload = anext(subscription)

        # Throw error
        with raises(RuntimeError) as exc_info:
            await subscription.athrow(RuntimeError("ouch"))
        assert str(exc_info.value) == "ouch"

        # A new email arrives!
        assert (
            pubsub.emit(
                {
                    "from": "*****@*****.**",
                    "subject": "Alright 2",
                    "message": "Tests are good 2",
                    "unread": True,
                }
            )
            is False
        )

        with raises(StopAsyncIteration):
            await payload
    async def should_not_trigger_when_subscription_is_already_done():
        pubsub = SimplePubSub()
        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        payload = anext(subscription)

        # A new email arrives!
        assert (
            pubsub.emit(
                {
                    "from": "*****@*****.**",
                    "subject": "Alright",
                    "message": "Tests are good",
                    "unread": True,
                }
            )
            is True
        )

        assert await payload == (
            {
                "importantEmail": {
                    "email": {"from": "*****@*****.**", "subject": "Alright"},
                    "inbox": {"unread": 1, "total": 2},
                }
            },
            None,
        )

        payload = anext(subscription)
        await subscription.aclose()

        # A new email arrives!
        assert (
            pubsub.emit(
                {
                    "from": "*****@*****.**",
                    "subject": "Alright 2",
                    "message": "Tests are good 2",
                    "unread": True,
                }
            )
            is False
        )

        with raises(StopAsyncIteration):
            await payload
    async def produces_a_payload_for_multiple_subscribe_in_same_subscription():
        pubsub = SimplePubSub()

        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        second_subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        payload1 = anext(subscription)
        payload2 = anext(second_subscription)

        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Alright",
            "message": "Tests are good",
            "unread": True,
        }) is True)

        expected_payload = {
            "importantEmail": {
                "email": {
                    "from": "*****@*****.**",
                    "subject": "Alright"
                },
                "inbox": {
                    "unread": 1,
                    "total": 2
                },
            }
        }

        assert await payload1 == (expected_payload, None)
        assert await payload2 == (expected_payload, None)
Beispiel #8
0
 async def iterator_aclose_empties_push_queue():
     pubsub = SimplePubSub()
     assert not pubsub.subscribers
     iterator = pubsub.get_subscriber()
     assert len(pubsub.subscribers) == 1
     assert iterator.listening
     for value in range(3):
         pubsub.emit(value)
     await sleep(0)
     assert iterator.push_queue.qsize() == 3
     assert iterator.pull_queue.qsize() == 0
     await iterator.aclose()
     assert not pubsub.subscribers
     assert iterator.push_queue.qsize() == 0
     assert iterator.pull_queue.qsize() == 0
     assert not iterator.listening
Beispiel #9
0
    async def subscribe_async_iterator_mock():
        pubsub = SimplePubSub()
        iterator = pubsub.get_subscriber()

        # Queue up publishes
        assert pubsub.emit("Apple") is True
        assert pubsub.emit("Banana") is True

        # Read payloads
        assert await iterator.__anext__() == "Apple"
        assert await iterator.__anext__() == "Banana"

        # Read ahead
        i3 = await iterator.__anext__()
        assert isawaitable(i3)
        i4 = await iterator.__anext__()
        assert isawaitable(i4)

        # Publish
        assert pubsub.emit("Coconut") is True
        assert pubsub.emit("Durian") is True

        # Await out of order to get correct results
        assert await i4 == "Durian"
        assert await i3 == "Coconut"

        # Read ahead
        i5 = iterator.__anext__()

        # Terminate queue
        await iterator.aclose()

        # Publish is not caught after terminate
        assert pubsub.emit("Fig") is False

        # Find that cancelled read-ahead got a "done" result
        with raises(StopAsyncIteration):
            await i5

        # And next returns empty completion value
        with raises(StopAsyncIteration):
            await iterator.__anext__()
    async def produces_a_payload_per_subscription_event():
        pubsub = SimplePubSub()
        subscription = await create_subscription(pubsub)
        assert isinstance(subscription, MapAsyncIterator)

        # Wait for the next subscription payload.
        payload = anext(subscription)

        # A new email arrives!
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Alright",
            "message": "Tests are good",
            "unread": True,
        }) is True)

        # The previously waited on payload now has a value.
        assert await payload == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Alright"
                    },
                    "inbox": {
                        "unread": 1,
                        "total": 2
                    },
                }
            },
            None,
        )

        # Another new email arrives, before anext(subscription) is called.
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Tools",
            "message": "I <3 making things",
            "unread": True,
        }) is True)

        # The next waited on payload will have a value.
        assert await anext(subscription) == (
            {
                "importantEmail": {
                    "email": {
                        "from": "*****@*****.**",
                        "subject": "Tools"
                    },
                    "inbox": {
                        "unread": 2,
                        "total": 3
                    },
                }
            },
            None,
        )

        # The client decides to disconnect.
        # noinspection PyUnresolvedReferences
        await subscription.aclose()

        # Which may result in disconnecting upstream services as well.
        assert (pubsub.emit({
            "from": "*****@*****.**",
            "subject": "Important",
            "message": "Read me please",
            "unread": True,
        }) is False)  # No more listeners.

        # Awaiting subscription after closing it results in completed results.
        with raises(StopAsyncIteration):
            assert await anext(subscription)