aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/python/grpcio/grpc/framework/interfaces
diff options
context:
space:
mode:
authorGravatar Nathaniel Manista <nathaniel@google.com>2015-08-17 16:50:42 +0000
committerGravatar Nathaniel Manista <nathaniel@google.com>2015-08-17 19:49:53 +0000
commit9df83ab9e2978f38c49f31de33e67a0d6689bd14 (patch)
tree8942daeacb0ea903737bc3b3179613aeca297b37 /src/python/grpcio/grpc/framework/interfaces
parent1892b787d8120a4acae3af394a265dc5f0b5a21b (diff)
The base interface of RPC Framework
This is the public API of the old base package of RPC Framework extracted into a first-class interface and adapted to metadata, status, and flow control.
Diffstat (limited to 'src/python/grpcio/grpc/framework/interfaces')
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/base/__init__.py30
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/base/base.py273
-rw-r--r--src/python/grpcio/grpc/framework/interfaces/base/utilities.py79
3 files changed, 382 insertions, 0 deletions
diff --git a/src/python/grpcio/grpc/framework/interfaces/base/__init__.py b/src/python/grpcio/grpc/framework/interfaces/base/__init__.py
new file mode 100644
index 0000000000..7086519106
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/base/__init__.py
@@ -0,0 +1,30 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py
new file mode 100644
index 0000000000..9d1651daac
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py
@@ -0,0 +1,273 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""The base interface of RPC Framework."""
+
+import abc
+import enum
+
+# abandonment is referenced from specification in this module.
+from grpc.framework.foundation import abandonment # pylint: disable=unused-import
+
+
+class NoSuchMethodError(Exception):
+ """Indicates that an unrecognized operation has been called."""
+
+
+@enum.unique
+class Outcome(enum.Enum):
+ """Operation outcomes."""
+
+ COMPLETED = 'completed'
+ CANCELLED = 'cancelled'
+ EXPIRED = 'expired'
+ LOCAL_SHUTDOWN = 'local shutdown'
+ REMOTE_SHUTDOWN = 'remote shutdown'
+ RECEPTION_FAILURE = 'reception failure'
+ TRANSMISSION_FAILURE = 'transmission failure'
+ LOCAL_FAILURE = 'local failure'
+ REMOTE_FAILURE = 'remote failure'
+
+
+class Completion(object):
+ """An aggregate of the values exchanged upon operation completion.
+
+ Attributes:
+ terminal_metadata: A terminal metadata value for the operaton.
+ code: A code value for the operation.
+ message: A message value for the operation.
+ """
+ __metaclass__ = abc.ABCMeta
+
+
+class OperationContext(object):
+ """Provides operation-related information and action."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def outcome(self):
+ """Indicates the operation's outcome (or that the operation is ongoing).
+
+ Returns:
+ None if the operation is still active or the Outcome value for the
+ operation if it has terminated.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def add_termination_callback(self, callback):
+ """Adds a function to be called upon operation termination.
+
+ Args:
+ callback: A callable to be passed an Outcome value on operation
+ termination.
+
+ Returns:
+ None if the operation has not yet terminated and the passed callback will
+ later be called when it does terminate, or if the operation has already
+ terminated an Outcome value describing the operation termination and the
+ passed callback will not be called as a result of this method call.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def time_remaining(self):
+ """Describes the length of allowed time remaining for the operation.
+
+ Returns:
+ A nonnegative float indicating the length of allowed time in seconds
+ remaining for the operation to complete before it is considered to have
+ timed out. Zero is returned if the operation has terminated.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def cancel(self):
+ """Cancels the operation if the operation has not yet terminated."""
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def fail(self, exception):
+ """Indicates that the operation has failed.
+
+ Args:
+ exception: An exception germane to the operation failure. May be None.
+ """
+ raise NotImplementedError()
+
+
+class Operator(object):
+ """An interface through which to participate in an operation."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def advance(
+ self, initial_metadata=None, payload=None, completion=None,
+ allowance=None):
+ """Progresses the operation.
+
+ Args:
+ initial_metadata: An initial metadata value. Only one may ever be
+ communicated in each direction for an operation, and they must be
+ communicated no later than either the first payload or the completion.
+ payload: A payload value.
+ completion: A Completion value. May only ever be non-None once in either
+ direction, and no payloads may be passed after it has been communicated.
+ allowance: A positive integer communicating the number of additional
+ payloads allowed to be passed by the remote side of the operation.
+ """
+ raise NotImplementedError()
+
+
+class Subscription(object):
+ """Describes customer code's interest in values from the other side.
+
+ Attributes:
+ kind: A Kind value describing the overall kind of this value.
+ termination_callback: A callable to be passed the Outcome associated with
+ the operation after it has terminated. Must be non-None if kind is
+ Kind.TERMINATION_ONLY. Must be None otherwise.
+ allowance: A callable behavior that accepts positive integers representing
+ the number of additional payloads allowed to be passed to the other side
+ of the operation. Must be None if kind is Kind.FULL. Must not be None
+ otherwise.
+ operator: An Operator to be passed values from the other side of the
+ operation. Must be non-None if kind is Kind.FULL. Must be None otherwise.
+ """
+
+ @enum.unique
+ class Kind(enum.Enum):
+
+ NONE = 'none'
+ TERMINATION_ONLY = 'termination only'
+ FULL = 'full'
+
+
+class Servicer(object):
+ """Interface for service implementations."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def service(self, group, method, context, output_operator):
+ """Services an operation.
+
+ Args:
+ group: The group identifier of the operation to be serviced.
+ method: The method identifier of the operation to be serviced.
+ context: An OperationContext object affording contextual information and
+ actions.
+ output_operator: An Operator that will accept output values of the
+ operation.
+
+ Returns:
+ A Subscription via which this object may or may not accept more values of
+ the operation.
+
+ Raises:
+ NoSuchMethodError: If this Servicer does not handle operations with the
+ given group and method.
+ abandonment.Abandoned: If the operation has been aborted and there no
+ longer is any reason to service the operation.
+ """
+ raise NotImplementedError()
+
+
+class End(object):
+ """Common type for entry-point objects on both sides of an operation."""
+ __metaclass__ = abc.ABCMeta
+
+ @abc.abstractmethod
+ def start(self):
+ """Starts this object's service of operations."""
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stop_gracefully(self):
+ """Gracefully stops this object's service of operations.
+
+ Operations in progress will be allowed to complete, and this method blocks
+ until all of them have.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def stop_immediately(self):
+ """Immediately stops this object's service of operations.
+
+ Operations in progress will not be allowed to complete.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def operate(
+ self, group, method, subscription, timeout, initial_metadata=None,
+ payload=None, completion=None):
+ """Commences an operation.
+
+ Args:
+ group: The group identifier of the invoked operation.
+ method: The method identifier of the invoked operation.
+ subscription: A Subscription to which the results of the operation will be
+ passed.
+ timeout: A length of time in seconds to allow for the operation.
+ initial_metadata: An initial metadata value to be sent to the other side
+ of the operation. May be None if the initial metadata will be later
+ passed via the returned operator or if there will be no initial metadata
+ passed at all.
+ payload: An initial payload for the operation.
+ completion: A Completion value indicating the end of transmission to the
+ other side of the operation.
+
+ Returns:
+ A pair of objects affording information about the operation and action
+ continuing the operation. The first element of the returned pair is an
+ OperationContext for the operation and the second element of the
+ returned pair is an Operator to which operation values not passed in
+ this call should later be passed.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def operation_stats(self):
+ """Reports the number of terminated operations broken down by outcome.
+
+ Returns:
+ A dictionary from Outcome value to an integer identifying the number
+ of operations that terminated with that outcome.
+ """
+ raise NotImplementedError()
+
+ @abc.abstractmethod
+ def add_idle_action(self, action):
+ """Adds an action to be called when this End has no ongoing operations.
+
+ Args:
+ action: A callable that accepts no arguments.
+ """
+ raise NotImplementedError()
diff --git a/src/python/grpcio/grpc/framework/interfaces/base/utilities.py b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py
new file mode 100644
index 0000000000..a9ee1a0981
--- /dev/null
+++ b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py
@@ -0,0 +1,79 @@
+# Copyright 2015, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Utilities for use with the base interface of RPC Framework."""
+
+import collections
+
+from grpc.framework.interfaces.base import base
+
+
+class _Completion(
+ base.Completion,
+ collections.namedtuple(
+ '_Completion', ('terminal_metadata', 'code', 'message',))):
+ """A trivial implementation of base.Completion."""
+
+
+class _Subscription(
+ base.Subscription,
+ collections.namedtuple(
+ '_Subscription',
+ ('kind', 'termination_callback', 'allowance', 'operator',))):
+ """A trivial implementation of base.Subscription."""
+
+_NONE_SUBSCRIPTION = _Subscription(
+ base.Subscription.Kind.NONE, None, None, None)
+
+
+def completion(terminal_metadata, code, message):
+ """Creates a base.Completion aggregating the given operation values.
+
+ Args:
+ terminal_metadata: A terminal metadata value for an operaton.
+ code: A code value for an operation.
+ message: A message value for an operation.
+
+ Returns:
+ A base.Completion aggregating the given operation values.
+ """
+ return _Completion(terminal_metadata, code, message)
+
+
+def full_subscription(operator):
+ """Creates a "full" base.Subscription for the given base.Operator.
+
+ Args:
+ operator: A base.Operator to be used in an operation.
+
+ Returns:
+ A base.Subscription of kind base.Subscription.Kind.FULL wrapping the given
+ base.Operator.
+ """
+ return _Subscription(base.Subscription.Kind.FULL, None, None, operator)