diff options
author | Xuan Wang <xuanwn@google.com> | 2023-02-03 14:11:27 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-03 14:11:27 -0800 |
commit | a190831789b514e9f740a78b0dcd03fe79bfdd50 (patch) | |
tree | e02423b2072ead564e7ba88d3ee51de3d88d8a10 /examples | |
parent | 1f960697c5020db85743a68b3533b8ef45a9629e (diff) | |
download | grpc-grpc-a190831789b514e9f740a78b0dcd03fe79bfdd50.tar.gz |
Add examples for timeout, kepp_alive, reflection and health_checking (#32243)
* Add timeout example
* Add pb2 file to example
* Remove .proto file
* Add keep_alive example
* Add refelction client
* fixes
* Add example for health_check
* Changes based on comments
* Fix pylint
Diffstat (limited to 'examples')
-rw-r--r-- | examples/python/Makefile | 21 | ||||
-rw-r--r-- | examples/python/health_checking/greeter_client.py | 56 | ||||
-rw-r--r-- | examples/python/health_checking/greeter_server.py | 74 | ||||
-rw-r--r-- | examples/python/health_checking/helloworld_pb2.py | 30 | ||||
-rw-r--r-- | examples/python/health_checking/helloworld_pb2.pyi | 17 | ||||
-rw-r--r-- | examples/python/health_checking/helloworld_pb2_grpc.py | 70 | ||||
-rw-r--r-- | examples/python/helloworld/greeter_client_reflection.py | 46 | ||||
-rw-r--r-- | examples/python/keep_alive/greeter_client.py | 67 | ||||
-rw-r--r-- | examples/python/keep_alive/greeter_server.py | 74 | ||||
-rw-r--r-- | examples/python/keep_alive/helloworld_pb2.py | 30 | ||||
-rw-r--r-- | examples/python/keep_alive/helloworld_pb2.pyi | 17 | ||||
-rw-r--r-- | examples/python/keep_alive/helloworld_pb2_grpc.py | 70 | ||||
-rw-r--r-- | examples/python/timeout/greeter_client.py | 45 | ||||
-rw-r--r-- | examples/python/timeout/greeter_server.py | 46 | ||||
-rw-r--r-- | examples/python/timeout/helloworld_pb2.py | 30 | ||||
-rw-r--r-- | examples/python/timeout/helloworld_pb2.pyi | 17 | ||||
-rw-r--r-- | examples/python/timeout/helloworld_pb2_grpc.py | 70 |
17 files changed, 780 insertions, 0 deletions
diff --git a/examples/python/Makefile b/examples/python/Makefile index 8f41590ffd..323e6b6bfb 100644 --- a/examples/python/Makefile +++ b/examples/python/Makefile @@ -20,6 +20,18 @@ ARTIFACTS += helloworld/helloworld_pb2.py ARTIFACTS += helloworld/helloworld_pb2_grpc.py ARTIFACTS += helloworld/helloworld_pb2.pyi +ARTIFACTS += timeout/helloworld_pb2.py +ARTIFACTS += timeout/helloworld_pb2_grpc.py +ARTIFACTS += timeout/helloworld_pb2.pyi + +ARTIFACTS += keep_alive/helloworld_pb2.py +ARTIFACTS += keep_alive/helloworld_pb2_grpc.py +ARTIFACTS += keep_alive/helloworld_pb2.pyi + +ARTIFACTS += health_checking/helloworld_pb2.py +ARTIFACTS += health_checking/helloworld_pb2_grpc.py +ARTIFACTS += health_checking/helloworld_pb2.pyi + ARTIFACTS += async_streaming/phone_pb2.py ARTIFACTS += async_streaming/phone_pb2_grpc.py ARTIFACTS += async_streaming/phone_pb2.pyi @@ -74,6 +86,15 @@ all: ${ARTIFACTS} helloworld/helloworld_pb2.py helloworld/helloworld_pb2_grpc.py helloworld/helloworld_pb2.pyi: ../protos/helloworld.proto python3 -m grpc_tools.protoc --python_out=helloworld --grpc_python_out=helloworld --pyi_out=helloworld -I ../protos ../protos/helloworld.proto +timeout/helloworld_pb2.py timeout/helloworld_pb2_grpc.py timeout/helloworld_pb2.pyi: ../protos/helloworld.proto + python3 -m grpc_tools.protoc --python_out=timeout --grpc_python_out=timeout --pyi_out=timeout -I ../protos ../protos/helloworld.proto + +keep_alive/helloworld_pb2.py keep_alive/helloworld_pb2_grpc.py keep_alive/helloworld_pb2.pyi: ../protos/helloworld.proto + python3 -m grpc_tools.protoc --python_out=keep_alive --grpc_python_out=keep_alive --pyi_out=keep_alive -I ../protos ../protos/helloworld.proto + +health_checking/helloworld_pb2.py health_checking/helloworld_pb2_grpc.py health_checking/helloworld_pb2.pyi: ../protos/helloworld.proto + python3 -m grpc_tools.protoc --python_out=health_checking --grpc_python_out=health_checking --pyi_out=health_checking -I ../protos ../protos/helloworld.proto + async_streaming/phone_pb2.py async_streaming/phone_pb2_grpc.py async_streaming/phone_pb2.pyi: async_streaming/phone.proto python3 -m grpc_tools.protoc --python_out=async_streaming --grpc_python_out=async_streaming --pyi_out=async_streaming -I async_streaming async_streaming/phone.proto diff --git a/examples/python/health_checking/greeter_client.py b/examples/python/health_checking/greeter_client.py new file mode 100644 index 0000000000..9405c1ef5b --- /dev/null +++ b/examples/python/health_checking/greeter_client.py @@ -0,0 +1,56 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gRPC Python helloworld.Greeter client with health checking.""" + +import logging +from time import sleep + +import grpc +from grpc_health.v1 import health_pb2 +from grpc_health.v1 import health_pb2_grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +def unary_call(stub: helloworld_pb2_grpc.GreeterStub, message: str): + response = stub.SayHello(helloworld_pb2.HelloRequest(name=message), + timeout=3) + print(f"Greeter client received: {response.message}") + + +def health_check_call(stub: health_pb2_grpc.HealthStub): + request = health_pb2.HealthCheckRequest(service="helloworld.Greeter") + resp = stub.Check(request) + if resp.status == health_pb2.HealthCheckResponse.SERVING: + print("server is serving") + elif resp.status == health_pb2.HealthCheckResponse.NOT_SERVING: + print("server stopped serving") + + +def run(): + with grpc.insecure_channel('localhost:50051') as channel: + stub = helloworld_pb2_grpc.GreeterStub(channel) + health_stub = health_pb2_grpc.HealthStub(channel) + # Should succeed + unary_call(stub, 'you') + + # Check health status every 1 second for 30 seconds + for _ in range(30): + health_check_call(health_stub) + sleep(1) + + +if __name__ == '__main__': + logging.basicConfig() + run() diff --git a/examples/python/health_checking/greeter_server.py b/examples/python/health_checking/greeter_server.py new file mode 100644 index 0000000000..d10fd87adc --- /dev/null +++ b/examples/python/health_checking/greeter_server.py @@ -0,0 +1,74 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""The Python implementation of the GRPC helloworld.Greeter server with health checking.""" + +from concurrent import futures +import logging +import threading +from time import sleep + +import grpc +from grpc_health.v1 import health +from grpc_health.v1 import health_pb2 +from grpc_health.v1 import health_pb2_grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +class Greeter(helloworld_pb2_grpc.GreeterServicer): + + def SayHello(self, request, context): + return helloworld_pb2.HelloReply(message=request.name) + + +def _toggle_health(health_servicer: health.HealthServicer, service: str): + next_status = health_pb2.HealthCheckResponse.SERVING + while True: + if next_status == health_pb2.HealthCheckResponse.SERVING: + next_status = health_pb2.HealthCheckResponse.NOT_SERVING + else: + next_status = health_pb2.HealthCheckResponse.SERVING + + health_servicer.set(service, next_status) + sleep(5) + + +def _configure_health_server(server: grpc.Server): + health_servicer = health.HealthServicer( + experimental_non_blocking=True, + experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=10)) + health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server) + + # Use a daemon thread to toggle health status + toggle_health_status_thread = threading.Thread(target=_toggle_health, + args=(health_servicer, + "helloworld.Greeter"), + daemon=True) + toggle_health_status_thread.start() + + +def serve(): + port = '50051' + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port('[::]:' + port) + _configure_health_server(server) + server.start() + print("Server started, listening on " + port) + server.wait_for_termination() + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/examples/python/health_checking/helloworld_pb2.py b/examples/python/health_checking/helloworld_pb2.py new file mode 100644 index 0000000000..f5b4f2d27d --- /dev/null +++ b/examples/python/health_checking/helloworld_pb2.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: helloworld.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW' + _HELLOREQUEST._serialized_start=32 + _HELLOREQUEST._serialized_end=60 + _HELLOREPLY._serialized_start=62 + _HELLOREPLY._serialized_end=91 + _GREETER._serialized_start=93 + _GREETER._serialized_end=166 +# @@protoc_insertion_point(module_scope) diff --git a/examples/python/health_checking/helloworld_pb2.pyi b/examples/python/health_checking/helloworld_pb2.pyi new file mode 100644 index 0000000000..8c4b5b2280 --- /dev/null +++ b/examples/python/health_checking/helloworld_pb2.pyi @@ -0,0 +1,17 @@ +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Optional as _Optional + +DESCRIPTOR: _descriptor.FileDescriptor + +class HelloReply(_message.Message): + __slots__ = ["message"] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + message: str + def __init__(self, message: _Optional[str] = ...) -> None: ... + +class HelloRequest(_message.Message): + __slots__ = ["name"] + NAME_FIELD_NUMBER: _ClassVar[int] + name: str + def __init__(self, name: _Optional[str] = ...) -> None: ... diff --git a/examples/python/health_checking/helloworld_pb2_grpc.py b/examples/python/health_checking/helloworld_pb2_grpc.py new file mode 100644 index 0000000000..47c186976e --- /dev/null +++ b/examples/python/health_checking/helloworld_pb2_grpc.py @@ -0,0 +1,70 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import helloworld_pb2 as helloworld__pb2 + + +class GreeterStub(object): + """The greeting service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=helloworld__pb2.HelloRequest.SerializeToString, + response_deserializer=helloworld__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The greeting service definition. + """ + + def SayHello(self, request, context): + """Sends a greeting + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=helloworld__pb2.HelloRequest.FromString, + response_serializer=helloworld__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class Greeter(object): + """The greeting service definition. + """ + + @staticmethod + def SayHello(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello', + helloworld__pb2.HelloRequest.SerializeToString, + helloworld__pb2.HelloReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/examples/python/helloworld/greeter_client_reflection.py b/examples/python/helloworld/greeter_client_reflection.py new file mode 100644 index 0000000000..77e32930b7 --- /dev/null +++ b/examples/python/helloworld/greeter_client_reflection.py @@ -0,0 +1,46 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""The Python implementation of the GRPC helloworld.Greeter client with reflection.""" + +import logging + +from google.protobuf.descriptor_pool import DescriptorPool +import grpc +from grpc_reflection.v1alpha.proto_reflection_descriptor_database import \ + ProtoReflectionDescriptorDatabase + + +def run(): + print("Will try to greet world ...") + with grpc.insecure_channel('localhost:50051') as channel: + reflection_db = ProtoReflectionDescriptorDatabase(channel) + services = reflection_db.get_services() + print(f"found services: {services}") + + desc_pool = DescriptorPool(reflection_db) + service_desc = desc_pool.FindServiceByName("helloworld.Greeter") + print(f"found Greeter service with name: {service_desc.full_name}") + for methods in service_desc.methods: + print(f"found method name: {methods.full_name}") + input_type = methods.input_type + print(f"input type for this method: {input_type.full_name}") + + request_desc = desc_pool.FindMessageTypeByName( + "helloworld.HelloRequest") + print(f"found request name: {request_desc.full_name}") + + +if __name__ == '__main__': + logging.basicConfig() + run() diff --git a/examples/python/keep_alive/greeter_client.py b/examples/python/keep_alive/greeter_client.py new file mode 100644 index 0000000000..c5d03cb0d7 --- /dev/null +++ b/examples/python/keep_alive/greeter_client.py @@ -0,0 +1,67 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gRPC Python helloworld.Greeter client with keepAlive channel options.""" + +import logging +from time import sleep + +import grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int, + message: str): + print("call:", request_id) + try: + response = stub.SayHello(helloworld_pb2.HelloRequest(name=message)) + print(f"Greeter client received: {response.message}") + except grpc.RpcError as rpc_error: + print('Call failed with code: ', rpc_error.code()) + + +def run(): + """ + grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is + sent on the transport. + grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive + ping waits for an acknowledgement. If it does not receive an acknowledgment within this + time, it will close the connection. + grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive + pings to be sent even if there are no calls in flight. + grpc.http2.max_pings_without_data: How many pings can the client send before needing to + send a data/header frame. + For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md + """ + channel_options = [('grpc.keepalive_time_ms', 8000), + ('grpc.keepalive_timeout_ms', 5000), + ('grpc.http2.max_pings_without_data', 5), + ('grpc.keepalive_permit_without_calls', 1)] + + with grpc.insecure_channel(target='localhost:50051', + options=channel_options) as channel: + stub = helloworld_pb2_grpc.GreeterStub(channel) + # Should succeed + unary_call(stub, 1, 'you') + + # Run 30s, run this with GRPC_VERBOSITY=DEBUG GRPC_TRACE=http_keepalive to observe logs. + # Client will be closed after receveing GOAWAY from server. + for i in range(30): + print(f"{i} seconds paased.") + sleep(1) + + +if __name__ == '__main__': + logging.basicConfig() + run() diff --git a/examples/python/keep_alive/greeter_server.py b/examples/python/keep_alive/greeter_server.py new file mode 100644 index 0000000000..db01ab3f5e --- /dev/null +++ b/examples/python/keep_alive/greeter_server.py @@ -0,0 +1,74 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""The Python implementation of the GRPC helloworld.Greeter server with keepAlive options.""" + +from concurrent import futures +import logging +from time import sleep + +import grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +class Greeter(helloworld_pb2_grpc.GreeterServicer): + + def SayHello(self, request, context): + message = request.name + if message.startswith("[delay]"): + sleep(5) + return helloworld_pb2.HelloReply(message=message) + + +def serve(): + """ + grpc.keepalive_time_ms: The period (in milliseconds) after which a keepalive ping is + sent on the transport. + grpc.keepalive_timeout_ms: The amount of time (in milliseconds) the sender of the keepalive + ping waits for an acknowledgement. If it does not receive an acknowledgment within + this time, it will close the connection. + grpc.http2.min_ping_interval_without_data_ms: Minimum allowed time (in milliseconds) + between a server receiving successive ping frames without sending any data/header frame. + grpc.max_connection_idle_ms: Maximum time (in milliseconds) that a channel may have no + outstanding rpcs, after which the server will close the connection. + grpc.max_connection_age_ms: Maximum time (in milliseconds) that a channel may exist. + grpc.max_connection_age_grace_ms: Grace period (in milliseconds) after the channel + reaches its max age. + grpc.http2.max_pings_without_data: How many pings can the client send before needing to + send a data/header frame. + grpc.keepalive_permit_without_calls: If set to 1 (0 : false; 1 : true), allows keepalive + pings to be sent even if there are no calls in flight. + For more details, check: https://github.com/grpc/grpc/blob/master/doc/keepalive.md + """ + server_options = [('grpc.keepalive_time_ms', 20000), + ('grpc.keepalive_timeout_ms', 10000), + ('grpc.http2.min_ping_interval_without_data_ms', 5000), + ('grpc.max_connection_idle_ms', 10000), + ('grpc.max_connection_age_ms', 30000), + ('grpc.max_connection_age_grace_ms', 5000), + ('grpc.http2.max_pings_without_data', 5), + ('grpc.keepalive_permit_without_calls', 1)] + port = '50051' + server = grpc.server(thread_pool=futures.ThreadPoolExecutor(max_workers=10), + options=server_options) + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port('[::]:' + port) + server.start() + print("Server started, listening on " + port) + server.wait_for_termination() + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/examples/python/keep_alive/helloworld_pb2.py b/examples/python/keep_alive/helloworld_pb2.py new file mode 100644 index 0000000000..f5b4f2d27d --- /dev/null +++ b/examples/python/keep_alive/helloworld_pb2.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: helloworld.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW' + _HELLOREQUEST._serialized_start=32 + _HELLOREQUEST._serialized_end=60 + _HELLOREPLY._serialized_start=62 + _HELLOREPLY._serialized_end=91 + _GREETER._serialized_start=93 + _GREETER._serialized_end=166 +# @@protoc_insertion_point(module_scope) diff --git a/examples/python/keep_alive/helloworld_pb2.pyi b/examples/python/keep_alive/helloworld_pb2.pyi new file mode 100644 index 0000000000..8c4b5b2280 --- /dev/null +++ b/examples/python/keep_alive/helloworld_pb2.pyi @@ -0,0 +1,17 @@ +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Optional as _Optional + +DESCRIPTOR: _descriptor.FileDescriptor + +class HelloReply(_message.Message): + __slots__ = ["message"] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + message: str + def __init__(self, message: _Optional[str] = ...) -> None: ... + +class HelloRequest(_message.Message): + __slots__ = ["name"] + NAME_FIELD_NUMBER: _ClassVar[int] + name: str + def __init__(self, name: _Optional[str] = ...) -> None: ... diff --git a/examples/python/keep_alive/helloworld_pb2_grpc.py b/examples/python/keep_alive/helloworld_pb2_grpc.py new file mode 100644 index 0000000000..47c186976e --- /dev/null +++ b/examples/python/keep_alive/helloworld_pb2_grpc.py @@ -0,0 +1,70 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import helloworld_pb2 as helloworld__pb2 + + +class GreeterStub(object): + """The greeting service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=helloworld__pb2.HelloRequest.SerializeToString, + response_deserializer=helloworld__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The greeting service definition. + """ + + def SayHello(self, request, context): + """Sends a greeting + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=helloworld__pb2.HelloRequest.FromString, + response_serializer=helloworld__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class Greeter(object): + """The greeting service definition. + """ + + @staticmethod + def SayHello(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello', + helloworld__pb2.HelloRequest.SerializeToString, + helloworld__pb2.HelloReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/examples/python/timeout/greeter_client.py b/examples/python/timeout/greeter_client.py new file mode 100644 index 0000000000..d1487994ac --- /dev/null +++ b/examples/python/timeout/greeter_client.py @@ -0,0 +1,45 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gRPC Python helloworld.Greeter client with call timeout parameters.""" + +import logging + +import grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +def unary_call(stub: helloworld_pb2_grpc.GreeterStub, request_id: int, + message: str): + print("call:", request_id) + try: + response = stub.SayHello(helloworld_pb2.HelloRequest(name=message), + timeout=3) + print(f"Greeter client received: {response.message}") + except grpc.RpcError as rpc_error: + print(f"Call failed with code: {rpc_error.code()}") + + +def run(): + with grpc.insecure_channel('localhost:50051') as channel: + stub = helloworld_pb2_grpc.GreeterStub(channel) + # Should success + unary_call(stub, 1, 'you') + # Should fail with DEADLINE_EXCEEDED + unary_call(stub, 2, '[delay] you') + + +if __name__ == '__main__': + logging.basicConfig() + run() diff --git a/examples/python/timeout/greeter_server.py b/examples/python/timeout/greeter_server.py new file mode 100644 index 0000000000..14b050b926 --- /dev/null +++ b/examples/python/timeout/greeter_server.py @@ -0,0 +1,46 @@ +# Copyright 2023 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""The Python implementation of the GRPC helloworld.Greeter server.""" + +from concurrent import futures +import logging +from time import sleep + +import grpc +import helloworld_pb2 +import helloworld_pb2_grpc + + +class Greeter(helloworld_pb2_grpc.GreeterServicer): + + def SayHello(self, request, context): + message = request.name + if message.startswith("[delay]"): + sleep(5) + return helloworld_pb2.HelloReply(message=message) + + +def serve(): + port = '50051' + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) + server.add_insecure_port('[::]:' + port) + server.start() + print("Server started, listening on " + port) + server.wait_for_termination() + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/examples/python/timeout/helloworld_pb2.py b/examples/python/timeout/helloworld_pb2.py new file mode 100644 index 0000000000..f5b4f2d27d --- /dev/null +++ b/examples/python/timeout/helloworld_pb2.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: helloworld.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10helloworld.proto\x12\nhelloworld\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2I\n\x07Greeter\x12>\n\x08SayHello\x12\x18.helloworld.HelloRequest\x1a\x16.helloworld.HelloReply\"\x00\x42\x36\n\x1bio.grpc.examples.helloworldB\x0fHelloWorldProtoP\x01\xa2\x02\x03HLWb\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'helloworld_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\033io.grpc.examples.helloworldB\017HelloWorldProtoP\001\242\002\003HLW' + _HELLOREQUEST._serialized_start=32 + _HELLOREQUEST._serialized_end=60 + _HELLOREPLY._serialized_start=62 + _HELLOREPLY._serialized_end=91 + _GREETER._serialized_start=93 + _GREETER._serialized_end=166 +# @@protoc_insertion_point(module_scope) diff --git a/examples/python/timeout/helloworld_pb2.pyi b/examples/python/timeout/helloworld_pb2.pyi new file mode 100644 index 0000000000..8c4b5b2280 --- /dev/null +++ b/examples/python/timeout/helloworld_pb2.pyi @@ -0,0 +1,17 @@ +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from typing import ClassVar as _ClassVar, Optional as _Optional + +DESCRIPTOR: _descriptor.FileDescriptor + +class HelloReply(_message.Message): + __slots__ = ["message"] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + message: str + def __init__(self, message: _Optional[str] = ...) -> None: ... + +class HelloRequest(_message.Message): + __slots__ = ["name"] + NAME_FIELD_NUMBER: _ClassVar[int] + name: str + def __init__(self, name: _Optional[str] = ...) -> None: ... diff --git a/examples/python/timeout/helloworld_pb2_grpc.py b/examples/python/timeout/helloworld_pb2_grpc.py new file mode 100644 index 0000000000..47c186976e --- /dev/null +++ b/examples/python/timeout/helloworld_pb2_grpc.py @@ -0,0 +1,70 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import helloworld_pb2 as helloworld__pb2 + + +class GreeterStub(object): + """The greeting service definition. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.SayHello = channel.unary_unary( + '/helloworld.Greeter/SayHello', + request_serializer=helloworld__pb2.HelloRequest.SerializeToString, + response_deserializer=helloworld__pb2.HelloReply.FromString, + ) + + +class GreeterServicer(object): + """The greeting service definition. + """ + + def SayHello(self, request, context): + """Sends a greeting + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_GreeterServicer_to_server(servicer, server): + rpc_method_handlers = { + 'SayHello': grpc.unary_unary_rpc_method_handler( + servicer.SayHello, + request_deserializer=helloworld__pb2.HelloRequest.FromString, + response_serializer=helloworld__pb2.HelloReply.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'helloworld.Greeter', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class Greeter(object): + """The greeting service definition. + """ + + @staticmethod + def SayHello(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/helloworld.Greeter/SayHello', + helloworld__pb2.HelloRequest.SerializeToString, + helloworld__pb2.HelloReply.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) |