commit
afd602ccba
915 changed files with 52048 additions and 28117 deletions
@ -1,14 +1,18 @@ |
||||
mergeable: |
||||
pull_requests: |
||||
label: |
||||
or: |
||||
- and: |
||||
and: |
||||
- must_exclude: |
||||
regex: '^disposition/DO NOT MERGE' |
||||
message: 'Pull request marked not mergeable' |
||||
- or: |
||||
- and: |
||||
- must_include: |
||||
regex: 'release notes: yes' |
||||
message: 'Please include release note: yes' |
||||
- must_include: |
||||
regex: '^lang\/' |
||||
message: 'Please include a language label' |
||||
- must_include: |
||||
regex: 'release notes: yes' |
||||
message: 'Please include release note: yes' |
||||
- must_include: |
||||
regex: '^lang\/' |
||||
message: 'Please include a language label' |
||||
- must_include: |
||||
regex: 'release notes: no' |
||||
message: 'Please include release note: no' |
||||
regex: 'release notes: no' |
||||
message: 'Please include release note: no' |
||||
|
@ -0,0 +1,16 @@ |
||||
load("//third_party/py:python_configure.bzl", "python_configure") |
||||
load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories") |
||||
load("@grpc_python_dependencies//:requirements.bzl", "pip_install") |
||||
load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") |
||||
|
||||
def grpc_python_deps(): |
||||
# TODO(https://github.com/grpc/grpc/issues/18256): Remove conditional. |
||||
if hasattr(native, "http_archive"): |
||||
python_configure(name = "local_config_python") |
||||
pip_repositories() |
||||
pip_install() |
||||
py_proto_repositories() |
||||
else: |
||||
print("Building Python gRPC with bazel 23.0+ is disabled pending " + |
||||
"resolution of https://github.com/grpc/grpc/issues/18256.") |
||||
|
@ -0,0 +1,7 @@ |
||||
gRPC Status |
||||
==================== |
||||
|
||||
Module Contents |
||||
--------------- |
||||
|
||||
.. automodule:: grpc_status.rpc_status |
@ -0,0 +1,56 @@ |
||||
# Copyright 2019 The 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. |
||||
|
||||
load("@grpc_python_dependencies//:requirements.bzl", "requirement") |
||||
|
||||
py_library( |
||||
name = "client", |
||||
testonly = 1, |
||||
srcs = ["client.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
"//src/python/grpcio_status/grpc_status:grpc_status", |
||||
"//examples:py_helloworld", |
||||
requirement('googleapis-common-protos'), |
||||
], |
||||
) |
||||
|
||||
py_library( |
||||
name = "server", |
||||
testonly = 1, |
||||
srcs = ["server.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
"//src/python/grpcio_status/grpc_status:grpc_status", |
||||
"//examples:py_helloworld", |
||||
] + select({ |
||||
"//conditions:default": [requirement("futures")], |
||||
"//:python3": [], |
||||
}), |
||||
) |
||||
|
||||
py_test( |
||||
name = "test/_error_handling_example_test", |
||||
srcs = ["test/_error_handling_example_test.py"], |
||||
deps = [ |
||||
":client", |
||||
":server", |
||||
"//src/python/grpcio_tests/tests:bazel_namespace_package_hack", |
||||
], |
||||
size = "small", |
||||
imports = [ |
||||
"../../../src/python/grpcio_status", |
||||
"../../../src/python/grpcio_tests", |
||||
], |
||||
) |
@ -0,0 +1,107 @@ |
||||
# gRPC Python Error Handling Example |
||||
|
||||
The goal of this example is sending error status from server that is more complicated than a code and detail string. |
||||
|
||||
The definition for an RPC method in proto files contains request message and response message. There are many error states that can be shared across RPC methods (e.g. stack trace, insufficient quota). Using a different path to handle error will make the code more maintainable. |
||||
|
||||
Ideally, the final status of an RPC should be described in the trailing headers of HTTP2, and gRPC Python provides helper functions in `grpcio-status` package to assist the packing and unpacking of error status. |
||||
|
||||
|
||||
### Requirement |
||||
``` |
||||
grpcio>=1.18.0 |
||||
grpcio-status>=1.18.0 |
||||
googleapis-common-protos>=1.5.5 |
||||
``` |
||||
|
||||
|
||||
### Error Detail Proto |
||||
|
||||
You may provide any custom proto message as error detail in your implementation. Here are protos are defined by Google Cloud Library Team: |
||||
|
||||
* [code.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/code.proto)) contains definition of RPC error codes. |
||||
* [error_details.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/error_details.proto)) contains definitions of common error details. |
||||
|
||||
|
||||
### Definition of Status Proto |
||||
|
||||
Here is the definition of Status proto. For full text, please see [status.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/status.proto). |
||||
|
||||
```proto |
||||
// The `Status` type defines a logical error model that is suitable for different |
||||
// programming environments, including REST APIs and RPC APIs. It is used by |
||||
// [gRPC](https://github.com/grpc). The error model is designed to be: |
||||
// |
||||
// - Simple to use and understand for most users |
||||
// - Flexible enough to meet unexpected needs |
||||
// |
||||
// # Overview |
||||
// |
||||
// The `Status` message contains three pieces of data: error code, error message, |
||||
// and error details. The error code should be an enum value of |
||||
// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The |
||||
// error message should be a developer-facing English message that helps |
||||
// developers *understand* and *resolve* the error. If a localized user-facing |
||||
// error message is needed, put the localized message in the error details or |
||||
// localize it in the client. The optional error details may contain arbitrary |
||||
// information about the error. There is a predefined set of error detail types |
||||
// in the package `google.rpc` that can be used for common error conditions. |
||||
// |
||||
// # Language mapping |
||||
// |
||||
// The `Status` message is the logical representation of the error model, but it |
||||
// is not necessarily the actual wire format. When the `Status` message is |
||||
// exposed in different client libraries and different wire protocols, it can be |
||||
// mapped differently. For example, it will likely be mapped to some exceptions |
||||
// in Java, but more likely mapped to some error codes in C. |
||||
// |
||||
// # Other uses |
||||
// |
||||
// The error model and the `Status` message can be used in a variety of |
||||
// environments, either with or without APIs, to provide a |
||||
// consistent developer experience across different environments. |
||||
// |
||||
// Example uses of this error model include: |
||||
// |
||||
// - Partial errors. If a service needs to return partial errors to the client, |
||||
// it may embed the `Status` in the normal response to indicate the partial |
||||
// errors. |
||||
// |
||||
// - Workflow errors. A typical workflow has multiple steps. Each step may |
||||
// have a `Status` message for error reporting. |
||||
// |
||||
// - Batch operations. If a client uses batch request and batch response, the |
||||
// `Status` message should be used directly inside batch response, one for |
||||
// each error sub-response. |
||||
// |
||||
// - Asynchronous operations. If an API call embeds asynchronous operation |
||||
// results in its response, the status of those operations should be |
||||
// represented directly using the `Status` message. |
||||
// |
||||
// - Logging. If some API errors are stored in logs, the message `Status` could |
||||
// be used directly after any stripping needed for security/privacy reasons. |
||||
message Status { |
||||
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. |
||||
int32 code = 1; |
||||
|
||||
// A developer-facing error message, which should be in English. Any |
||||
// user-facing error message should be localized and sent in the |
||||
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. |
||||
string message = 2; |
||||
|
||||
// A list of messages that carry the error details. There is a common set of |
||||
// message types for APIs to use. |
||||
repeated google.protobuf.Any details = 3; |
||||
} |
||||
``` |
||||
|
||||
|
||||
### Usage of Well-Known-Proto `Any` |
||||
|
||||
Please check [ProtoBuf Document: Any](https://developers.google.com/protocol-buffers/docs/reference/python-generated#any) |
||||
|
||||
```Python |
||||
any_message.Pack(message) |
||||
any_message.Unpack(message) |
||||
assert any_message.Is(message.DESCRIPTOR) |
||||
``` |
@ -0,0 +1,56 @@ |
||||
# Copyright 2019 The 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. |
||||
"""This example handles rich error status in client-side.""" |
||||
|
||||
from __future__ import print_function |
||||
import logging |
||||
|
||||
import grpc |
||||
from grpc_status import rpc_status |
||||
from google.rpc import error_details_pb2 |
||||
|
||||
from examples.protos import helloworld_pb2 |
||||
from examples.protos import helloworld_pb2_grpc |
||||
|
||||
_LOGGER = logging.getLogger(__name__) |
||||
|
||||
|
||||
def process(stub): |
||||
try: |
||||
response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) |
||||
_LOGGER.info('Call success: %s', response.message) |
||||
except grpc.RpcError as rpc_error: |
||||
_LOGGER.error('Call failure: %s', rpc_error) |
||||
status = rpc_status.from_call(rpc_error) |
||||
for detail in status.details: |
||||
if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR): |
||||
info = error_details_pb2.QuotaFailure() |
||||
detail.Unpack(info) |
||||
_LOGGER.error('Quota failure: %s', info) |
||||
else: |
||||
raise RuntimeError('Unexpected failure: %s' % detail) |
||||
|
||||
|
||||
def main(): |
||||
# NOTE(gRPC Python Team): .close() is possible on a channel and should be |
||||
# used in circumstances in which the with statement does not fit the needs |
||||
# of the code. |
||||
with grpc.insecure_channel('localhost:50051') as channel: |
||||
stub = helloworld_pb2_grpc.GreeterStub(channel) |
||||
process(stub) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig() |
||||
main() |
@ -0,0 +1,90 @@ |
||||
# Copyright 2019 The 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. |
||||
"""This example sends out rich error status from server-side.""" |
||||
|
||||
from concurrent import futures |
||||
import time |
||||
import logging |
||||
import threading |
||||
|
||||
import grpc |
||||
from grpc_status import rpc_status |
||||
|
||||
from google.protobuf import any_pb2 |
||||
from google.rpc import code_pb2, status_pb2, error_details_pb2 |
||||
|
||||
from examples.protos import helloworld_pb2 |
||||
from examples.protos import helloworld_pb2_grpc |
||||
|
||||
_ONE_DAY_IN_SECONDS = 60 * 60 * 24 |
||||
|
||||
|
||||
def create_greet_limit_exceed_error_status(name): |
||||
detail = any_pb2.Any() |
||||
detail.Pack( |
||||
error_details_pb2.QuotaFailure( |
||||
violations=[ |
||||
error_details_pb2.QuotaFailure.Violation( |
||||
subject="name: %s" % name, |
||||
description="Limit one greeting per person", |
||||
) |
||||
],)) |
||||
return status_pb2.Status( |
||||
code=code_pb2.RESOURCE_EXHAUSTED, |
||||
message='Request limit exceeded.', |
||||
details=[detail], |
||||
) |
||||
|
||||
|
||||
class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer): |
||||
|
||||
def __init__(self): |
||||
self._lock = threading.RLock() |
||||
self._greeted = set() |
||||
|
||||
def SayHello(self, request, context): |
||||
with self._lock: |
||||
if request.name in self._greeted: |
||||
rich_status = create_greet_limit_exceed_error_status( |
||||
request.name) |
||||
context.abort_with_status(rpc_status.to_status(rich_status)) |
||||
else: |
||||
self._greeted.add(request.name) |
||||
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) |
||||
|
||||
|
||||
def create_server(server_address): |
||||
server = grpc.server(futures.ThreadPoolExecutor()) |
||||
helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server) |
||||
port = server.add_insecure_port(server_address) |
||||
return server, port |
||||
|
||||
|
||||
def serve(server): |
||||
server.start() |
||||
try: |
||||
while True: |
||||
time.sleep(_ONE_DAY_IN_SECONDS) |
||||
except KeyboardInterrupt: |
||||
server.stop(None) |
||||
|
||||
|
||||
def main(): |
||||
server, unused_port = create_server('[::]:50051') |
||||
serve(server) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig() |
||||
main() |
@ -0,0 +1,54 @@ |
||||
# Copyright 2019 The 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. |
||||
"""Tests of the error handling example.""" |
||||
|
||||
# NOTE(lidiz) This module only exists in Bazel BUILD file, for more details |
||||
# please refer to comments in the "bazel_namespace_package_hack" module. |
||||
try: |
||||
from tests import bazel_namespace_package_hack |
||||
bazel_namespace_package_hack.sys_path_to_site_dir_hack() |
||||
except ImportError: |
||||
pass |
||||
|
||||
import unittest |
||||
import logging |
||||
|
||||
import grpc |
||||
|
||||
from examples.protos import helloworld_pb2_grpc |
||||
from examples.python.errors import client as error_handling_client |
||||
from examples.python.errors import server as error_handling_server |
||||
|
||||
|
||||
class ErrorHandlingExampleTest(unittest.TestCase): |
||||
|
||||
def setUp(self): |
||||
self._server, port = error_handling_server.create_server('[::]:0') |
||||
self._server.start() |
||||
self._channel = grpc.insecure_channel('localhost:%d' % port) |
||||
|
||||
def tearDown(self): |
||||
self._channel.close() |
||||
self._server.stop(None) |
||||
|
||||
def test_error_handling_example(self): |
||||
stub = helloworld_pb2_grpc.GreeterStub(self._channel) |
||||
error_handling_client.process(stub) |
||||
error_handling_client.process(stub) |
||||
# No unhandled exception raised, test passed! |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig() |
||||
unittest.main(verbosity=2) |
@ -0,0 +1,59 @@ |
||||
# gRPC Bazel BUILD file. |
||||
# |
||||
# Copyright 2019 The 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. |
||||
|
||||
load("@grpc_python_dependencies//:requirements.bzl", "requirement") |
||||
load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") |
||||
|
||||
py_proto_library( |
||||
name = "prime_proto", |
||||
protos = ["prime.proto",], |
||||
deps = [requirement("protobuf")], |
||||
) |
||||
|
||||
py_binary( |
||||
name = "client", |
||||
testonly = 1, |
||||
srcs = ["client.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
":prime_proto", |
||||
], |
||||
default_python_version = "PY3", |
||||
) |
||||
|
||||
py_binary( |
||||
name = "server", |
||||
testonly = 1, |
||||
srcs = ["server.py"], |
||||
deps = [ |
||||
"//src/python/grpcio/grpc:grpcio", |
||||
":prime_proto" |
||||
] + select({ |
||||
"//conditions:default": [requirement("futures")], |
||||
"//:python3": [], |
||||
}), |
||||
default_python_version = "PY3", |
||||
) |
||||
|
||||
py_test( |
||||
name = "test/_multiprocessing_example_test", |
||||
srcs = ["test/_multiprocessing_example_test.py"], |
||||
data = [ |
||||
":client", |
||||
":server" |
||||
], |
||||
size = "small", |
||||
) |
@ -0,0 +1,67 @@ |
||||
## Multiprocessing with gRPC Python |
||||
|
||||
Multiprocessing allows application developers to sidestep the Python global |
||||
interpreter lock and achieve true concurrency on multicore systems. |
||||
Unfortunately, using multiprocessing and gRPC Python is not yet as simple as |
||||
instantiating your server with a `futures.ProcessPoolExecutor`. |
||||
|
||||
The library is implemented as a C extension, maintaining much of the state that |
||||
drives the system in native code. As such, upon calling |
||||
[`fork`](http://man7.org/linux/man-pages/man2/fork.2.html), much of the |
||||
state copied into the child process is invalid, leading to hangs and crashes. |
||||
|
||||
However, calling `fork` without `exec` in your python process is supported |
||||
*before* any gRPC servers have been instantiated. Application developers can |
||||
take advantage of this to parallelize their CPU-intensive operations. |
||||
|
||||
## Calculating Prime Numbers with Multiple Processes |
||||
|
||||
This example calculates the first 10,000 prime numbers as an RPC. We instantiate |
||||
one server per subprocess, balancing requests between the servers using the |
||||
[`SO_REUSEPORT`](https://lwn.net/Articles/542629/) socket option. Note that this |
||||
option is not available in `manylinux1` distributions, which are, as of the time |
||||
of writing, the only gRPC Python wheels available on PyPI. To take advantage of this |
||||
feature, you'll need to build from source, either using bazel (as we do for |
||||
these examples) or via pip, using `pip install grpcio --no-binary grpcio`. |
||||
|
||||
```python |
||||
_PROCESS_COUNT = multiprocessing.cpu_count() |
||||
``` |
||||
|
||||
On the server side, we detect the number of CPUs available on the system and |
||||
spawn exactly that many child processes. If we spin up fewer, we won't be taking |
||||
full advantage of the hardware resources available. |
||||
|
||||
## Running the Example |
||||
|
||||
To run the server, |
||||
[ensure `bazel` is installed](https://docs.bazel.build/versions/master/install.html) |
||||
and run: |
||||
|
||||
``` |
||||
bazel run //examples/python/multiprocessing:server & |
||||
``` |
||||
|
||||
Note the address at which the server is running. For example, |
||||
|
||||
``` |
||||
... |
||||
[PID 107153] Binding to '[::]:33915' |
||||
[PID 107507] Starting new server. |
||||
[PID 107508] Starting new server. |
||||
... |
||||
``` |
||||
|
||||
Note that several servers have been started, each with its own PID. |
||||
|
||||
Now, start the client by running |
||||
|
||||
``` |
||||
bazel run //examples/python/multiprocessing:client -- [SERVER_ADDRESS] |
||||
``` |
||||
|
||||
For example, |
||||
|
||||
``` |
||||
bazel run //examples/python/multiprocessing:client -- [::]:33915 |
||||
``` |
@ -0,0 +1,95 @@ |
||||
# Copyright 2019 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. |
||||
"""An example of multiprocessing concurrency with gRPC.""" |
||||
|
||||
from __future__ import absolute_import |
||||
from __future__ import division |
||||
from __future__ import print_function |
||||
|
||||
import argparse |
||||
import atexit |
||||
import logging |
||||
import multiprocessing |
||||
import operator |
||||
import sys |
||||
|
||||
import grpc |
||||
|
||||
from examples.python.multiprocessing import prime_pb2 |
||||
from examples.python.multiprocessing import prime_pb2_grpc |
||||
|
||||
_PROCESS_COUNT = 8 |
||||
_MAXIMUM_CANDIDATE = 10000 |
||||
|
||||
# Each worker process initializes a single channel after forking. |
||||
# It's regrettable, but to ensure that each subprocess only has to instantiate |
||||
# a single channel to be reused across all RPCs, we use globals. |
||||
_worker_channel_singleton = None |
||||
_worker_stub_singleton = None |
||||
|
||||
_LOGGER = logging.getLogger(__name__) |
||||
|
||||
|
||||
def _shutdown_worker(): |
||||
_LOGGER.info('Shutting worker process down.') |
||||
if _worker_channel_singleton is not None: |
||||
_worker_channel_singleton.stop() |
||||
|
||||
|
||||
def _initialize_worker(server_address): |
||||
global _worker_channel_singleton # pylint: disable=global-statement |
||||
global _worker_stub_singleton # pylint: disable=global-statement |
||||
_LOGGER.info('Initializing worker process.') |
||||
_worker_channel_singleton = grpc.insecure_channel(server_address) |
||||
_worker_stub_singleton = prime_pb2_grpc.PrimeCheckerStub( |
||||
_worker_channel_singleton) |
||||
atexit.register(_shutdown_worker) |
||||
|
||||
|
||||
def _run_worker_query(primality_candidate): |
||||
_LOGGER.info('Checking primality of %s.', primality_candidate) |
||||
return _worker_stub_singleton.check( |
||||
prime_pb2.PrimeCandidate(candidate=primality_candidate)) |
||||
|
||||
|
||||
def _calculate_primes(server_address): |
||||
worker_pool = multiprocessing.Pool( |
||||
processes=_PROCESS_COUNT, |
||||
initializer=_initialize_worker, |
||||
initargs=(server_address,)) |
||||
check_range = range(2, _MAXIMUM_CANDIDATE) |
||||
primality = worker_pool.map(_run_worker_query, check_range) |
||||
primes = zip(check_range, map(operator.attrgetter('isPrime'), primality)) |
||||
return tuple(primes) |
||||
|
||||
|
||||
def main(): |
||||
msg = 'Determine the primality of the first {} integers.'.format( |
||||
_MAXIMUM_CANDIDATE) |
||||
parser = argparse.ArgumentParser(description=msg) |
||||
parser.add_argument( |
||||
'server_address', |
||||
help='The address of the server (e.g. localhost:50051)') |
||||
args = parser.parse_args() |
||||
primes = _calculate_primes(args.server_address) |
||||
print(primes) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
handler = logging.StreamHandler(sys.stdout) |
||||
formatter = logging.Formatter('[PID %(process)d] %(message)s') |
||||
handler.setFormatter(formatter) |
||||
_LOGGER.addHandler(handler) |
||||
_LOGGER.setLevel(logging.INFO) |
||||
main() |
@ -0,0 +1,35 @@ |
||||
// Copyright 2019 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. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package prime; |
||||
|
||||
// A candidate integer for primality testing. |
||||
message PrimeCandidate { |
||||
// The candidate. |
||||
int64 candidate = 1; |
||||
} |
||||
|
||||
// The primality of the requested integer candidate. |
||||
message Primality { |
||||
// Is the candidate prime? |
||||
bool isPrime = 1; |
||||
} |
||||
|
||||
// Service to check primality. |
||||
service PrimeChecker { |
||||
// Determines the primality of an integer. |
||||
rpc check (PrimeCandidate) returns (Primality) {} |
||||
} |
@ -0,0 +1,123 @@ |
||||
# Copyright 2019 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. |
||||
"""An example of multiprocess concurrency with gRPC.""" |
||||
|
||||
from __future__ import absolute_import |
||||
from __future__ import division |
||||
from __future__ import print_function |
||||
|
||||
from concurrent import futures |
||||
import contextlib |
||||
import datetime |
||||
import logging |
||||
import math |
||||
import multiprocessing |
||||
import time |
||||
import socket |
||||
import sys |
||||
|
||||
import grpc |
||||
|
||||
from examples.python.multiprocessing import prime_pb2 |
||||
from examples.python.multiprocessing import prime_pb2_grpc |
||||
|
||||
_LOGGER = logging.getLogger(__name__) |
||||
|
||||
_ONE_DAY = datetime.timedelta(days=1) |
||||
_PROCESS_COUNT = multiprocessing.cpu_count() |
||||
_THREAD_CONCURRENCY = _PROCESS_COUNT |
||||
|
||||
|
||||
def is_prime(n): |
||||
for i in range(2, int(math.ceil(math.sqrt(n)))): |
||||
if n % i == 0: |
||||
return False |
||||
else: |
||||
return True |
||||
|
||||
|
||||
class PrimeChecker(prime_pb2_grpc.PrimeCheckerServicer): |
||||
|
||||
def check(self, request, context): |
||||
_LOGGER.info('Determining primality of %s', request.candidate) |
||||
return prime_pb2.Primality(isPrime=is_prime(request.candidate)) |
||||
|
||||
|
||||
def _wait_forever(server): |
||||
try: |
||||
while True: |
||||
time.sleep(_ONE_DAY.total_seconds()) |
||||
except KeyboardInterrupt: |
||||
server.stop(None) |
||||
|
||||
|
||||
def _run_server(bind_address): |
||||
"""Start a server in a subprocess.""" |
||||
_LOGGER.info('Starting new server.') |
||||
options = (('grpc.so_reuseport', 1),) |
||||
|
||||
# WARNING: This example takes advantage of SO_REUSEPORT. Due to the |
||||
# limitations of manylinux1, none of our precompiled Linux wheels currently |
||||
# support this option. (https://github.com/grpc/grpc/issues/18210). To take |
||||
# advantage of this feature, install from source with |
||||
# `pip install grpcio --no-binary grpcio`. |
||||
|
||||
server = grpc.server( |
||||
futures.ThreadPoolExecutor(max_workers=_THREAD_CONCURRENCY,), |
||||
options=options) |
||||
prime_pb2_grpc.add_PrimeCheckerServicer_to_server(PrimeChecker(), server) |
||||
server.add_insecure_port(bind_address) |
||||
server.start() |
||||
_wait_forever(server) |
||||
|
||||
|
||||
@contextlib.contextmanager |
||||
def _reserve_port(): |
||||
"""Find and reserve a port for all subprocesses to use.""" |
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) |
||||
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) |
||||
if sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT) != 1: |
||||
raise RuntimeError("Failed to set SO_REUSEPORT.") |
||||
sock.bind(('', 0)) |
||||
try: |
||||
yield sock.getsockname()[1] |
||||
finally: |
||||
sock.close() |
||||
|
||||
|
||||
def main(): |
||||
with _reserve_port() as port: |
||||
bind_address = 'localhost:{}'.format(port) |
||||
_LOGGER.info("Binding to '%s'", bind_address) |
||||
sys.stdout.flush() |
||||
workers = [] |
||||
for _ in range(_PROCESS_COUNT): |
||||
# NOTE: It is imperative that the worker subprocesses be forked before |
||||
# any gRPC servers start up. See |
||||
# https://github.com/grpc/grpc/issues/16001 for more details. |
||||
worker = multiprocessing.Process( |
||||
target=_run_server, args=(bind_address,)) |
||||
worker.start() |
||||
workers.append(worker) |
||||
for worker in workers: |
||||
worker.join() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
handler = logging.StreamHandler(sys.stdout) |
||||
formatter = logging.Formatter('[PID %(process)d] %(message)s') |
||||
handler.setFormatter(formatter) |
||||
_LOGGER.addHandler(handler) |
||||
_LOGGER.setLevel(logging.INFO) |
||||
main() |
@ -0,0 +1,74 @@ |
||||
# Copyright 2019 the 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. |
||||
"""Test for multiprocessing example.""" |
||||
|
||||
import ast |
||||
import logging |
||||
import math |
||||
import os |
||||
import re |
||||
import subprocess |
||||
import tempfile |
||||
import unittest |
||||
|
||||
_BINARY_DIR = os.path.realpath( |
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..')) |
||||
_SERVER_PATH = os.path.join(_BINARY_DIR, 'server') |
||||
_CLIENT_PATH = os.path.join(_BINARY_DIR, 'client') |
||||
|
||||
|
||||
def is_prime(n): |
||||
for i in range(2, int(math.ceil(math.sqrt(n)))): |
||||
if n % i == 0: |
||||
return False |
||||
else: |
||||
return True |
||||
|
||||
|
||||
def _get_server_address(server_stream): |
||||
while True: |
||||
server_stream.seek(0) |
||||
line = server_stream.readline() |
||||
while line: |
||||
matches = re.search('Binding to \'(.+)\'', line) |
||||
if matches is not None: |
||||
return matches.groups()[0] |
||||
line = server_stream.readline() |
||||
|
||||
|
||||
class MultiprocessingExampleTest(unittest.TestCase): |
||||
|
||||
def test_multiprocessing_example(self): |
||||
server_stdout = tempfile.TemporaryFile(mode='r') |
||||
server_process = subprocess.Popen((_SERVER_PATH,), stdout=server_stdout) |
||||
server_address = _get_server_address(server_stdout) |
||||
client_stdout = tempfile.TemporaryFile(mode='r') |
||||
client_process = subprocess.Popen( |
||||
( |
||||
_CLIENT_PATH, |
||||
server_address, |
||||
), stdout=client_stdout) |
||||
client_process.wait() |
||||
server_process.terminate() |
||||
client_stdout.seek(0) |
||||
results = ast.literal_eval(client_stdout.read().strip().split('\n')[-1]) |
||||
values = tuple(result[0] for result in results) |
||||
self.assertSequenceEqual(range(2, 10000), values) |
||||
for result in results: |
||||
self.assertEqual(is_prime(result[0]), result[1]) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
logging.basicConfig() |
||||
unittest.main(verbosity=2) |
@ -0,0 +1,79 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_CREATE_CHANNEL_IMPL_H |
||||
#define GRPCPP_CREATE_CHANNEL_IMPL_H |
||||
|
||||
#include <memory> |
||||
|
||||
#include <grpcpp/channel.h> |
||||
#include <grpcpp/impl/codegen/client_interceptor.h> |
||||
#include <grpcpp/security/credentials.h> |
||||
#include <grpcpp/support/channel_arguments.h> |
||||
#include <grpcpp/support/config.h> |
||||
|
||||
namespace grpc_impl { |
||||
|
||||
/// Create a new \a Channel pointing to \a target.
|
||||
///
|
||||
/// \param target The URI of the endpoint to connect to.
|
||||
/// \param creds Credentials to use for the created channel. If it does not
|
||||
/// hold an object or is invalid, a lame channel (one on which all operations
|
||||
/// fail) is returned.
|
||||
std::shared_ptr<grpc::Channel> CreateChannel( |
||||
const grpc::string& target, |
||||
const std::shared_ptr<grpc::ChannelCredentials>& creds); |
||||
|
||||
/// Create a new \em custom \a Channel pointing to \a target.
|
||||
///
|
||||
/// \warning For advanced use and testing ONLY. Override default channel
|
||||
/// arguments only if necessary.
|
||||
///
|
||||
/// \param target The URI of the endpoint to connect to.
|
||||
/// \param creds Credentials to use for the created channel. If it does not
|
||||
/// hold an object or is invalid, a lame channel (one on which all operations
|
||||
/// fail) is returned.
|
||||
/// \param args Options for channel creation.
|
||||
std::shared_ptr<grpc::Channel> CreateCustomChannel( |
||||
const grpc::string& target, |
||||
const std::shared_ptr<grpc::ChannelCredentials>& creds, |
||||
const grpc::ChannelArguments& args); |
||||
|
||||
namespace experimental { |
||||
/// Create a new \em custom \a Channel pointing to \a target with \a
|
||||
/// interceptors being invoked per call.
|
||||
///
|
||||
/// \warning For advanced use and testing ONLY. Override default channel
|
||||
/// arguments only if necessary.
|
||||
///
|
||||
/// \param target The URI of the endpoint to connect to.
|
||||
/// \param creds Credentials to use for the created channel. If it does not
|
||||
/// hold an object or is invalid, a lame channel (one on which all operations
|
||||
/// fail) is returned.
|
||||
/// \param args Options for channel creation.
|
||||
std::shared_ptr<grpc::Channel> CreateCustomChannelWithInterceptors( |
||||
const grpc::string& target, |
||||
const std::shared_ptr<grpc::ChannelCredentials>& creds, |
||||
const grpc::ChannelArguments& args, |
||||
std::vector< |
||||
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>> |
||||
interceptor_creators); |
||||
} // namespace experimental
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_CREATE_CHANNEL_IMPL_H
|
@ -0,0 +1,70 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H |
||||
#define GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H |
||||
|
||||
#include <memory> |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
#include <grpcpp/channel.h> |
||||
#include <grpcpp/support/channel_arguments.h> |
||||
|
||||
namespace grpc_impl { |
||||
|
||||
#ifdef GPR_SUPPORT_CHANNELS_FROM_FD |
||||
|
||||
/// Create a new \a Channel communicating over the given file descriptor.
|
||||
///
|
||||
/// \param target The name of the target.
|
||||
/// \param fd The file descriptor representing a socket.
|
||||
std::shared_ptr<grpc::Channel> CreateInsecureChannelFromFd( |
||||
const grpc::string& target, int fd); |
||||
|
||||
/// Create a new \a Channel communicating over given file descriptor with custom
|
||||
/// channel arguments.
|
||||
///
|
||||
/// \param target The name of the target.
|
||||
/// \param fd The file descriptor representing a socket.
|
||||
/// \param args Options for channel creation.
|
||||
std::shared_ptr<grpc::Channel> CreateCustomInsecureChannelFromFd( |
||||
const grpc::string& target, int fd, const grpc::ChannelArguments& args); |
||||
|
||||
namespace experimental { |
||||
|
||||
/// Create a new \a Channel communicating over given file descriptor with custom
|
||||
/// channel arguments.
|
||||
///
|
||||
/// \param target The name of the target.
|
||||
/// \param fd The file descriptor representing a socket.
|
||||
/// \param args Options for channel creation.
|
||||
/// \param interceptor_creators Vector of interceptor factory objects.
|
||||
std::shared_ptr<grpc::Channel> |
||||
CreateCustomInsecureChannelWithInterceptorsFromFd( |
||||
const grpc::string& target, int fd, const grpc::ChannelArguments& args, |
||||
std::unique_ptr<std::vector< |
||||
std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>>> |
||||
interceptor_creators); |
||||
|
||||
} // namespace experimental
|
||||
|
||||
#endif // GPR_SUPPORT_CHANNELS_FROM_FD
|
||||
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H
|
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H |
||||
#define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpcpp/impl/server_builder_plugin.h> |
||||
#include <grpcpp/impl/server_initializer.h> |
||||
#include <grpcpp/support/config.h> |
||||
|
||||
namespace grpc_impl { |
||||
namespace channelz { |
||||
namespace experimental { |
||||
|
||||
/// Add channelz server plugin to \a ServerBuilder. This function should
|
||||
/// be called at static initialization time. This service is experimental
|
||||
/// for now. Track progress in https://github.com/grpc/grpc/issues/15988.
|
||||
void InitChannelzService(); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace channelz
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H
|
@ -0,0 +1,55 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H |
||||
#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H |
||||
|
||||
#include <grpcpp/impl/server_builder_plugin.h> |
||||
#include <grpcpp/support/config.h> |
||||
|
||||
namespace grpc { |
||||
class ProtoServerReflection; |
||||
} // namespace grpc
|
||||
|
||||
namespace grpc_impl { |
||||
class ServerInitializer; |
||||
|
||||
namespace reflection { |
||||
|
||||
class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { |
||||
public: |
||||
ProtoServerReflectionPlugin(); |
||||
::grpc::string name() override; |
||||
void InitServer(::grpc_impl::ServerInitializer* si) override; |
||||
void Finish(::grpc_impl::ServerInitializer* si) override; |
||||
void ChangeArguments(const ::grpc::string& name, void* value) override; |
||||
bool has_async_methods() const override; |
||||
bool has_sync_methods() const override; |
||||
|
||||
private: |
||||
std::shared_ptr<grpc::ProtoServerReflection> reflection_service_; |
||||
}; |
||||
|
||||
/// Add proto reflection plugin to \a ServerBuilder.
|
||||
/// This function should be called at the static initialization time.
|
||||
void InitProtoReflectionServerBuilderPlugin(); |
||||
|
||||
} // namespace reflection
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H
|
@ -0,0 +1,54 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H |
||||
#define GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/load_reporting.h> |
||||
#include <grpcpp/impl/codegen/config.h> |
||||
#include <grpcpp/impl/codegen/server_context.h> |
||||
#include <grpcpp/impl/server_builder_option.h> |
||||
|
||||
namespace grpc_impl { |
||||
namespace load_reporter { |
||||
namespace experimental { |
||||
|
||||
// The ServerBuilderOption to enable server-side load reporting feature. To
|
||||
// enable the feature, please make sure the binary builds with the
|
||||
// grpcpp_server_load_reporting library and set this option in the
|
||||
// ServerBuilder.
|
||||
class LoadReportingServiceServerBuilderOption |
||||
: public grpc::ServerBuilderOption { |
||||
public: |
||||
void UpdateArguments(::grpc::ChannelArguments* args) override; |
||||
void UpdatePlugins(std::vector<std::unique_ptr<::grpc::ServerBuilderPlugin>>* |
||||
plugins) override; |
||||
}; |
||||
|
||||
// Adds the load reporting cost with \a cost_name and \a cost_value in the
|
||||
// trailing metadata of the server context.
|
||||
void AddLoadReportingCost(grpc::ServerContext* ctx, |
||||
const grpc::string& cost_name, double cost_value); |
||||
|
||||
} // namespace experimental
|
||||
} // namespace load_reporter
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H
|
@ -0,0 +1,108 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_GENERIC_GENERIC_STUB_IMPL_H |
||||
#define GRPCPP_GENERIC_GENERIC_STUB_IMPL_H |
||||
|
||||
#include <functional> |
||||
|
||||
#include <grpcpp/support/async_stream.h> |
||||
#include <grpcpp/support/async_unary_call.h> |
||||
#include <grpcpp/support/byte_buffer.h> |
||||
#include <grpcpp/support/client_callback.h> |
||||
#include <grpcpp/support/status.h> |
||||
|
||||
namespace grpc { |
||||
|
||||
class CompletionQueue; |
||||
typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer> |
||||
GenericClientAsyncReaderWriter; |
||||
typedef ClientAsyncResponseReader<ByteBuffer> GenericClientAsyncResponseReader; |
||||
} // namespace grpc
|
||||
namespace grpc_impl { |
||||
|
||||
/// Generic stubs provide a type-unsafe interface to call gRPC methods
|
||||
/// by name.
|
||||
class GenericStub final { |
||||
public: |
||||
explicit GenericStub(std::shared_ptr<grpc::ChannelInterface> channel) |
||||
: channel_(channel) {} |
||||
|
||||
/// Setup a call to a named method \a method using \a context, but don't
|
||||
/// start it. Let it be started explicitly with StartCall and a tag.
|
||||
/// The return value only indicates whether or not registration of the call
|
||||
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
|
||||
std::unique_ptr<grpc::GenericClientAsyncReaderWriter> PrepareCall( |
||||
grpc::ClientContext* context, const grpc::string& method, |
||||
grpc::CompletionQueue* cq); |
||||
|
||||
/// Setup a unary call to a named method \a method using \a context, and don't
|
||||
/// start it. Let it be started explicitly with StartCall.
|
||||
/// The return value only indicates whether or not registration of the call
|
||||
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
|
||||
std::unique_ptr<grpc::GenericClientAsyncResponseReader> PrepareUnaryCall( |
||||
grpc::ClientContext* context, const grpc::string& method, |
||||
const grpc::ByteBuffer& request, grpc::CompletionQueue* cq); |
||||
|
||||
/// DEPRECATED for multi-threaded use
|
||||
/// Begin a call to a named method \a method using \a context.
|
||||
/// A tag \a tag will be delivered to \a cq when the call has been started
|
||||
/// (i.e, initial metadata has been sent).
|
||||
/// The return value only indicates whether or not registration of the call
|
||||
/// succeeded (i.e. the call won't proceed if the return value is nullptr).
|
||||
std::unique_ptr<grpc::GenericClientAsyncReaderWriter> Call( |
||||
grpc::ClientContext* context, const grpc::string& method, |
||||
grpc::CompletionQueue* cq, void* tag); |
||||
|
||||
/// NOTE: class experimental_type is not part of the public API of this class
|
||||
/// TODO(vjpai): Move these contents to the public API of GenericStub when
|
||||
/// they are no longer experimental
|
||||
class experimental_type { |
||||
public: |
||||
explicit experimental_type(GenericStub* stub) : stub_(stub) {} |
||||
|
||||
/// Setup and start a unary call to a named method \a method using
|
||||
/// \a context and specifying the \a request and \a response buffers.
|
||||
void UnaryCall(grpc::ClientContext* context, const grpc::string& method, |
||||
const grpc::ByteBuffer* request, grpc::ByteBuffer* response, |
||||
std::function<void(grpc::Status)> on_completion); |
||||
|
||||
/// Setup a call to a named method \a method using \a context and tied to
|
||||
/// \a reactor . Like any other bidi streaming RPC, it will not be activated
|
||||
/// until StartCall is invoked on its reactor.
|
||||
void PrepareBidiStreamingCall( |
||||
grpc::ClientContext* context, const grpc::string& method, |
||||
grpc::experimental::ClientBidiReactor<grpc::ByteBuffer, |
||||
grpc::ByteBuffer>* reactor); |
||||
|
||||
private: |
||||
GenericStub* stub_; |
||||
}; |
||||
|
||||
/// NOTE: The function experimental() is not stable public API. It is a view
|
||||
/// to the experimental components of this class. It may be changed or removed
|
||||
/// at any time.
|
||||
experimental_type experimental() { return experimental_type(this); } |
||||
|
||||
private: |
||||
std::shared_ptr<grpc::ChannelInterface> channel_; |
||||
}; |
||||
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_GENERIC_GENERIC_STUB_IMPL_H
|
@ -0,0 +1,55 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H |
||||
#define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H |
||||
|
||||
#include <grpcpp/support/config.h> |
||||
|
||||
namespace grpc_impl { |
||||
|
||||
/// The gRPC server uses this interface to expose the health checking service
|
||||
/// without depending on protobuf.
|
||||
class HealthCheckServiceInterface { |
||||
public: |
||||
virtual ~HealthCheckServiceInterface() {} |
||||
|
||||
/// Set or change the serving status of the given \a service_name.
|
||||
virtual void SetServingStatus(const grpc::string& service_name, |
||||
bool serving) = 0; |
||||
/// Apply to all registered service names.
|
||||
virtual void SetServingStatus(bool serving) = 0; |
||||
|
||||
/// Set all registered service names to not serving and prevent future
|
||||
/// state changes.
|
||||
virtual void Shutdown() {} |
||||
}; |
||||
|
||||
/// Enable/disable the default health checking service. This applies to all C++
|
||||
/// servers created afterwards. For each server, user can override the default
|
||||
/// with a HealthCheckServiceServerBuilderOption.
|
||||
/// NOT thread safe.
|
||||
void EnableDefaultHealthCheckService(bool enable); |
||||
|
||||
/// Returns whether the default health checking service is enabled.
|
||||
/// NOT thread safe.
|
||||
bool DefaultHealthCheckServiceEnabled(); |
||||
|
||||
} // namespace grpc_impl
|
||||
|
||||
#endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue