Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix UnaryStreamMultiCallable and StreamStreamMultiCallable Future/Call #42

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

shabbyrobe
Copy link
Owner

See #41

@@ -669,7 +669,7 @@ class UnaryUnaryMultiCallable(typing.Generic[TRequest, TResponse]):
...


class UnaryStreamMultiCallable(typing.Generic[TRequest, TResponse]):
class UnaryStreamMultiCallable(CallFuture[TResponse], typing.Generic[TRequest, TResponse]):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not quite it. The UnaryStreamMultiCallable is not itself the stream. Calling the UnaryStreamMultiCallable (i.e. the __call__ method) returns the stream.

CallIterator[TResponse] currently inherits from Call. I think it should inherit from CallFuture[TResponse].

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: CallFuture[TResponse] implies that stream.result() returns a TResponse, but that doesn't seem to be the case.

The behavior of stream.result() doesn't seem to be documented, but as far as I can tell from testing: for server-streaming RPCs, result() waits for the RPC to complete (stream closed, canceled, or error). When the stream is closed, it returns None.

Tested with a modified version of https://github.com/grpc/grpc/blob/master/examples/python/hellostreamingworld/async_greeter_client.py:

import logging

import grpc
import hellostreamingworld_pb2
import hellostreamingworld_pb2_grpc


def run() -> None:
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = hellostreamingworld_pb2_grpc.MultiGreeterStub(channel)

        hello_stream = stub.sayHello(
            hellostreamingworld_pb2.HelloRequest(name="you"))
        while True:
            try:
                response = hello_stream.result(timeout=0.1)
                print(f"result() returned {type(response)}: {repr(response)}")
                if response is None:
                    break
            except grpc.FutureTimeoutError:
                response = next(hello_stream, None)
                print(f"next() returned {type(response)}: {repr(response)}")
                if response is None: 
                    break

if __name__ == "__main__":
    logging.basicConfig()
    run()
python greeter_client.py
next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 0, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 1, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 2, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 3, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 4, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 5, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 6, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 7, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 8, you!"

next() returned <class 'hellostreamingworld_pb2.HelloReply'>: message: "Hello number 9, you!"

result() returned <class 'NoneType'>: None

Comment on lines +229 to +232
def unary_stream() -> grpc.UnaryStreamMultiCallable[int, int]:
return typing.cast(grpc.UnaryStreamMultiCallable[int, int], None)

stream = unary_stream()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function returns the multi-callable object, not the stream. Call the multi-callable to get the stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants