mirror of https://github.com/grpc/grpc.git
commit
baf28f501f
252 changed files with 5480 additions and 11579 deletions
@ -0,0 +1,15 @@ |
|||||||
|
gRPC Fail Fast Semantics |
||||||
|
======================== |
||||||
|
|
||||||
|
Fail fast requests allow terminating requests (with status UNAVAILABLE) prior |
||||||
|
to the deadline of the request being met. |
||||||
|
|
||||||
|
gRPC implementations of fail fast can terminate requests whenever a channel is |
||||||
|
in the TRANSIENT_FAILURE or SHUTDOWN states. If the channel is in any other |
||||||
|
state (CONNECTING, READY, or IDLE) the request should not be terminated. |
||||||
|
|
||||||
|
Fail fast SHOULD be the default for gRPC implementations, with an option to |
||||||
|
switch to non fail fast. |
||||||
|
|
||||||
|
The opposite of fail fast is 'ignore connectivity'. |
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,94 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2016, 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
/* Posix code for gpr snprintf support. */ |
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#ifdef GPR_WIN32 |
||||||
|
|
||||||
|
/* Some platforms (namely msys) need wchar to be included BEFORE
|
||||||
|
anything else, especially strsafe.h. */ |
||||||
|
#include <wchar.h> |
||||||
|
|
||||||
|
#include <stdarg.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <strsafe.h> |
||||||
|
|
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
|
||||||
|
#include "src/core/lib/support/string.h" |
||||||
|
|
||||||
|
#if defined UNICODE || defined _UNICODE |
||||||
|
LPTSTR |
||||||
|
gpr_char_to_tchar(LPCSTR input) { |
||||||
|
LPTSTR ret; |
||||||
|
int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0); |
||||||
|
if (needed <= 0) return NULL; |
||||||
|
ret = gpr_malloc((unsigned)needed * sizeof(TCHAR)); |
||||||
|
MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
LPSTR |
||||||
|
gpr_tchar_to_char(LPCTSTR input) { |
||||||
|
LPSTR ret; |
||||||
|
int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL); |
||||||
|
if (needed <= 0) return NULL; |
||||||
|
ret = gpr_malloc((unsigned)needed); |
||||||
|
WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL); |
||||||
|
return ret; |
||||||
|
} |
||||||
|
#else |
||||||
|
char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); } |
||||||
|
|
||||||
|
char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); } |
||||||
|
#endif |
||||||
|
|
||||||
|
char *gpr_format_message(int messageid) { |
||||||
|
LPTSTR tmessage; |
||||||
|
char *message; |
||||||
|
DWORD status = FormatMessage( |
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | |
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS, |
||||||
|
NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
||||||
|
(LPTSTR)(&tmessage), 0, NULL); |
||||||
|
if (status == 0) return gpr_strdup("Unable to retrieve error string"); |
||||||
|
message = gpr_tchar_to_char(tmessage); |
||||||
|
LocalFree(tmessage); |
||||||
|
return message; |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* GPR_WIN32 */ |
@ -0,0 +1,73 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <grpc/support/port_platform.h> |
||||||
|
|
||||||
|
#ifdef GPR_MSYS_TMPFILE |
||||||
|
|
||||||
|
#include <io.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
#include <tchar.h> |
||||||
|
|
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
|
||||||
|
#include "src/core/lib/support/string_win32.h" |
||||||
|
#include "src/core/lib/support/tmpfile.h" |
||||||
|
|
||||||
|
FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) { |
||||||
|
FILE *result = NULL; |
||||||
|
char tmp_filename[MAX_PATH]; |
||||||
|
UINT success; |
||||||
|
|
||||||
|
if (tmp_filename_out != NULL) *tmp_filename_out = NULL; |
||||||
|
|
||||||
|
/* Generate a unique filename with our template + temporary path. */ |
||||||
|
success = GetTempFileNameA(".", prefix, 0, tmp_filename); |
||||||
|
fprintf(stderr, "success = %d\n", success); |
||||||
|
|
||||||
|
if (success) { |
||||||
|
/* Open a file there. */ |
||||||
|
result = fopen(tmp_filename, "wb+"); |
||||||
|
fprintf(stderr, "result = %p\n", result); |
||||||
|
} |
||||||
|
if (result != NULL && tmp_filename_out) { |
||||||
|
*tmp_filename_out = gpr_strdup(tmp_filename); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
#endif /* GPR_MSYS_TMPFILE */ |
@ -0,0 +1,54 @@ |
|||||||
|
#!/usr/bin/env node
|
||||||
|
/* |
||||||
|
* |
||||||
|
* 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
/** |
||||||
|
* This file is required because package.json cannot reference a file that |
||||||
|
* is not distributed with the package, and we use node-pre-gyp to distribute |
||||||
|
* the plugin binary |
||||||
|
*/ |
||||||
|
|
||||||
|
'use strict'; |
||||||
|
|
||||||
|
var path = require('path'); |
||||||
|
var execFile = require('child_process').execFile; |
||||||
|
|
||||||
|
var protoc = path.resolve(__dirname, 'grpc_node_plugin'); |
||||||
|
|
||||||
|
execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) { |
||||||
|
if (error) { |
||||||
|
throw error; |
||||||
|
} |
||||||
|
console.log(stdout); |
||||||
|
console.log(stderr); |
||||||
|
}); |
@ -0,0 +1,56 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2016, 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#import "GRPCCall.h" |
||||||
|
|
||||||
|
/** Helpers for setting TLS Trusted Roots, Client Certificates, and Private Key */ |
||||||
|
@interface GRPCCall (ChannelCredentials) |
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the provided @c pemRootCert as the set of trusted root Certificate Authorities for @c host. |
||||||
|
*/ |
||||||
|
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert |
||||||
|
forHost:(nonnull NSString *)host |
||||||
|
error:(NSError **)errorPtr; |
||||||
|
/**
|
||||||
|
* Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate |
||||||
|
* Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be |
||||||
|
* used. |
||||||
|
*/ |
||||||
|
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts |
||||||
|
withPrivateKey:(nullable NSString *)pemPrivateKey |
||||||
|
withCertChain:(nullable NSString *)pemCertChain |
||||||
|
forHost:(nonnull NSString *)host |
||||||
|
error:(NSError **)errorPtr; |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,66 @@ |
|||||||
|
/* |
||||||
|
* |
||||||
|
* Copyright 2016, 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. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#import "GRPCCall+ChannelCredentials.h" |
||||||
|
|
||||||
|
#import "private/GRPCHost.h" |
||||||
|
|
||||||
|
@implementation GRPCCall (ChannelCredentials) |
||||||
|
|
||||||
|
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts |
||||||
|
withPrivateKey:(nullable NSString *)pemPrivateKey |
||||||
|
withCertChain:(nullable NSString *)pemCertChain |
||||||
|
forHost:(nonnull NSString *)host |
||||||
|
error:(NSError **)errorPtr { |
||||||
|
if (!host) { |
||||||
|
[NSException raise:NSInvalidArgumentException |
||||||
|
format:@"host must be provided."]; |
||||||
|
} |
||||||
|
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host]; |
||||||
|
return [hostConfig setTLSPEMRootCerts:pemRootCerts |
||||||
|
withPrivateKey:pemPrivateKey |
||||||
|
withCertChain:pemCertChain |
||||||
|
error:errorPtr]; |
||||||
|
} |
||||||
|
|
||||||
|
+ (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts |
||||||
|
forHost:(nonnull NSString *)host |
||||||
|
error:(NSError **)errorPtr { |
||||||
|
return [GRPCCall setTLSPEMRootCerts:pemRootCerts |
||||||
|
withPrivateKey:nil |
||||||
|
withCertChain:nil |
||||||
|
forHost:host |
||||||
|
error:errorPtr]; |
||||||
|
} |
||||||
|
|
||||||
|
@end |
@ -0,0 +1,75 @@ |
|||||||
|
// Copyright 2016, 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. |
||||||
|
|
||||||
|
// File detached comment 1 |
||||||
|
|
||||||
|
// File detached comment 2 |
||||||
|
|
||||||
|
// File leading comment 1 |
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
// Ignored detached comment |
||||||
|
|
||||||
|
// Ignored package leading comment |
||||||
|
package grpc.testing; |
||||||
|
|
||||||
|
message Request { |
||||||
|
} |
||||||
|
message Response { |
||||||
|
} |
||||||
|
|
||||||
|
// ServiceA detached comment 1 |
||||||
|
|
||||||
|
// ServiceA detached comment 2 |
||||||
|
|
||||||
|
// ServiceA leading comment 1 |
||||||
|
service ServiceA { |
||||||
|
// MethodA1 leading comment 1 |
||||||
|
rpc MethodA1(Request) returns (Response); // MethodA1 trailing comment 1 |
||||||
|
|
||||||
|
// MethodA2 detached leading comment 1 |
||||||
|
|
||||||
|
// Method A2 leading comment 1 |
||||||
|
// Method A2 leading comment 2 |
||||||
|
rpc MethodA2(stream Request) returns (Response); |
||||||
|
// MethodA2 trailing comment 1 |
||||||
|
} |
||||||
|
// Ignored ServiceA trailing comment 1 |
||||||
|
|
||||||
|
// ServiceB leading comment 1 |
||||||
|
service ServiceB { |
||||||
|
// ServiceB trailing comment 1 |
||||||
|
|
||||||
|
// MethodB1 leading comment 1 |
||||||
|
rpc MethodB1(Request) returns (Response); |
||||||
|
// MethodB1 trailing comment 1 |
||||||
|
} |
||||||
|
// Ignored ServiceB trailing comment 2 |
||||||
|
|
||||||
|
// Ignored file trailing comment |
@ -1,363 +0,0 @@ |
|||||||
# 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 RPC-service-side bridge between RPC Framework and GRPC-on-the-wire.""" |
|
||||||
|
|
||||||
import enum |
|
||||||
import logging |
|
||||||
import threading |
|
||||||
import time |
|
||||||
|
|
||||||
from grpc._adapter import _common |
|
||||||
from grpc._adapter import _intermediary_low as _low |
|
||||||
from grpc.framework.base import interfaces as base_interfaces |
|
||||||
from grpc.framework.base import null |
|
||||||
from grpc.framework.foundation import activated |
|
||||||
from grpc.framework.foundation import logging_pool |
|
||||||
|
|
||||||
_THREAD_POOL_SIZE = 10 |
|
||||||
|
|
||||||
|
|
||||||
@enum.unique |
|
||||||
class _LowWrite(enum.Enum): |
|
||||||
"""The possible categories of low-level write state.""" |
|
||||||
|
|
||||||
OPEN = 'OPEN' |
|
||||||
ACTIVE = 'ACTIVE' |
|
||||||
CLOSED = 'CLOSED' |
|
||||||
|
|
||||||
|
|
||||||
def _write(call, rpc_state, payload): |
|
||||||
serialized_payload = rpc_state.serializer(payload) |
|
||||||
if rpc_state.write.low is _LowWrite.OPEN: |
|
||||||
call.write(serialized_payload, call, 0) |
|
||||||
rpc_state.write.low = _LowWrite.ACTIVE |
|
||||||
else: |
|
||||||
rpc_state.write.pending.append(serialized_payload) |
|
||||||
|
|
||||||
|
|
||||||
def _status(call, rpc_state): |
|
||||||
call.status(_low.Status(_low.Code.OK, ''), call) |
|
||||||
rpc_state.write.low = _LowWrite.CLOSED |
|
||||||
|
|
||||||
|
|
||||||
class ForeLink(base_interfaces.ForeLink, activated.Activated): |
|
||||||
"""A service-side bridge between RPC Framework and the C-ish _low code.""" |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, pool, request_deserializers, response_serializers, |
|
||||||
root_certificates, key_chain_pairs, port=None): |
|
||||||
"""Constructor. |
|
||||||
|
|
||||||
Args: |
|
||||||
pool: A thread pool. |
|
||||||
request_deserializers: A dict from RPC method names to request object |
|
||||||
deserializer behaviors. |
|
||||||
response_serializers: A dict from RPC method names to response object |
|
||||||
serializer behaviors. |
|
||||||
root_certificates: The PEM-encoded client root certificates as a |
|
||||||
bytestring or None. |
|
||||||
key_chain_pairs: A sequence of PEM-encoded private key-certificate chain |
|
||||||
pairs. |
|
||||||
port: The port on which to serve, or None to have a port selected |
|
||||||
automatically. |
|
||||||
""" |
|
||||||
self._condition = threading.Condition() |
|
||||||
self._pool = pool |
|
||||||
self._request_deserializers = request_deserializers |
|
||||||
self._response_serializers = response_serializers |
|
||||||
self._root_certificates = root_certificates |
|
||||||
self._key_chain_pairs = key_chain_pairs |
|
||||||
self._requested_port = port |
|
||||||
|
|
||||||
self._rear_link = null.NULL_REAR_LINK |
|
||||||
self._completion_queue = None |
|
||||||
self._server = None |
|
||||||
self._rpc_states = {} |
|
||||||
self._spinning = False |
|
||||||
self._port = None |
|
||||||
|
|
||||||
def _on_stop_event(self): |
|
||||||
self._spinning = False |
|
||||||
self._condition.notify_all() |
|
||||||
|
|
||||||
def _on_service_acceptance_event(self, event, server): |
|
||||||
"""Handle a service invocation event.""" |
|
||||||
service_acceptance = event.service_acceptance |
|
||||||
if service_acceptance is None: |
|
||||||
return |
|
||||||
|
|
||||||
call = service_acceptance.call |
|
||||||
call.accept(self._completion_queue, call) |
|
||||||
# TODO(nathaniel): Metadata support. |
|
||||||
call.premetadata() |
|
||||||
call.read(call) |
|
||||||
method = service_acceptance.method |
|
||||||
|
|
||||||
self._rpc_states[call] = _common.CommonRPCState( |
|
||||||
_common.WriteState(_LowWrite.OPEN, _common.HighWrite.OPEN, []), 1, |
|
||||||
self._request_deserializers[method], |
|
||||||
self._response_serializers[method]) |
|
||||||
|
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, 0, base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT, method, |
|
||||||
base_interfaces.ServicedSubscription.Kind.FULL, None, None, |
|
||||||
service_acceptance.deadline - time.time()) |
|
||||||
self._rear_link.accept_front_to_back_ticket(ticket) |
|
||||||
|
|
||||||
server.service(None) |
|
||||||
|
|
||||||
def _on_read_event(self, event): |
|
||||||
"""Handle data arriving during an RPC.""" |
|
||||||
call = event.tag |
|
||||||
rpc_state = self._rpc_states.get(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
sequence_number = rpc_state.sequence_number |
|
||||||
rpc_state.sequence_number += 1 |
|
||||||
if event.bytes is None: |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.COMPLETION, None, None, None, |
|
||||||
None, None) |
|
||||||
else: |
|
||||||
call.read(call) |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.CONTINUATION, None, None, |
|
||||||
None, rpc_state.deserializer(event.bytes), None) |
|
||||||
|
|
||||||
self._rear_link.accept_front_to_back_ticket(ticket) |
|
||||||
|
|
||||||
def _on_write_event(self, event): |
|
||||||
call = event.tag |
|
||||||
rpc_state = self._rpc_states.get(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
if rpc_state.write.pending: |
|
||||||
serialized_payload = rpc_state.write.pending.pop(0) |
|
||||||
call.write(serialized_payload, call, 0) |
|
||||||
elif rpc_state.write.high is _common.HighWrite.CLOSED: |
|
||||||
_status(call, rpc_state) |
|
||||||
else: |
|
||||||
rpc_state.write.low = _LowWrite.OPEN |
|
||||||
|
|
||||||
def _on_complete_event(self, event): |
|
||||||
if not event.complete_accepted: |
|
||||||
logging.error('Complete not accepted! %s', (event,)) |
|
||||||
call = event.tag |
|
||||||
rpc_state = self._rpc_states.pop(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
sequence_number = rpc_state.sequence_number |
|
||||||
rpc_state.sequence_number += 1 |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None, |
|
||||||
None, None, None, None) |
|
||||||
self._rear_link.accept_front_to_back_ticket(ticket) |
|
||||||
|
|
||||||
def _on_finish_event(self, event): |
|
||||||
"""Handle termination of an RPC.""" |
|
||||||
call = event.tag |
|
||||||
rpc_state = self._rpc_states.pop(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
code = event.status.code |
|
||||||
if code is _low.Code.OK: |
|
||||||
return |
|
||||||
|
|
||||||
sequence_number = rpc_state.sequence_number |
|
||||||
rpc_state.sequence_number += 1 |
|
||||||
if code is _low.Code.CANCELLED: |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.CANCELLATION, None, None, |
|
||||||
None, None, None) |
|
||||||
elif code is _low.Code.DEADLINE_EXCEEDED: |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.EXPIRATION, None, None, None, |
|
||||||
None, None) |
|
||||||
else: |
|
||||||
# TODO(nathaniel): Better mapping of codes to ticket-categories |
|
||||||
ticket = base_interfaces.FrontToBackTicket( |
|
||||||
call, sequence_number, |
|
||||||
base_interfaces.FrontToBackTicket.Kind.TRANSMISSION_FAILURE, None, |
|
||||||
None, None, None, None) |
|
||||||
self._rear_link.accept_front_to_back_ticket(ticket) |
|
||||||
|
|
||||||
def _spin(self, completion_queue, server): |
|
||||||
while True: |
|
||||||
event = completion_queue.get(None) |
|
||||||
|
|
||||||
with self._condition: |
|
||||||
if event.kind is _low.Event.Kind.STOP: |
|
||||||
self._on_stop_event() |
|
||||||
return |
|
||||||
elif self._server is None: |
|
||||||
continue |
|
||||||
elif event.kind is _low.Event.Kind.SERVICE_ACCEPTED: |
|
||||||
self._on_service_acceptance_event(event, server) |
|
||||||
elif event.kind is _low.Event.Kind.READ_ACCEPTED: |
|
||||||
self._on_read_event(event) |
|
||||||
elif event.kind is _low.Event.Kind.WRITE_ACCEPTED: |
|
||||||
self._on_write_event(event) |
|
||||||
elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED: |
|
||||||
self._on_complete_event(event) |
|
||||||
elif event.kind is _low.Event.Kind.FINISH: |
|
||||||
self._on_finish_event(event) |
|
||||||
else: |
|
||||||
logging.error('Illegal event! %s', (event,)) |
|
||||||
|
|
||||||
def _continue(self, call, payload): |
|
||||||
rpc_state = self._rpc_states.get(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
_write(call, rpc_state, payload) |
|
||||||
|
|
||||||
def _complete(self, call, payload): |
|
||||||
"""Handle completion of the writes of an RPC.""" |
|
||||||
rpc_state = self._rpc_states.get(call, None) |
|
||||||
if rpc_state is None: |
|
||||||
return |
|
||||||
|
|
||||||
if rpc_state.write.low is _LowWrite.OPEN: |
|
||||||
if payload is None: |
|
||||||
_status(call, rpc_state) |
|
||||||
else: |
|
||||||
_write(call, rpc_state, payload) |
|
||||||
elif rpc_state.write.low is _LowWrite.ACTIVE: |
|
||||||
if payload is not None: |
|
||||||
rpc_state.write.pending.append(rpc_state.serializer(payload)) |
|
||||||
else: |
|
||||||
raise ValueError('Called to complete after having already completed!') |
|
||||||
rpc_state.write.high = _common.HighWrite.CLOSED |
|
||||||
|
|
||||||
def _cancel(self, call): |
|
||||||
call.cancel() |
|
||||||
self._rpc_states.pop(call, None) |
|
||||||
|
|
||||||
def join_rear_link(self, rear_link): |
|
||||||
"""See base_interfaces.ForeLink.join_rear_link for specification.""" |
|
||||||
self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link |
|
||||||
|
|
||||||
def _start(self): |
|
||||||
"""Starts this ForeLink. |
|
||||||
|
|
||||||
This method must be called before attempting to exchange tickets with this |
|
||||||
object. |
|
||||||
""" |
|
||||||
with self._condition: |
|
||||||
address = '[::]:%d' % ( |
|
||||||
0 if self._requested_port is None else self._requested_port) |
|
||||||
self._completion_queue = _low.CompletionQueue() |
|
||||||
if self._root_certificates is None and not self._key_chain_pairs: |
|
||||||
self._server = _low.Server(self._completion_queue) |
|
||||||
self._port = self._server.add_http2_addr(address) |
|
||||||
else: |
|
||||||
server_credentials = _low.ServerCredentials( |
|
||||||
self._root_certificates, self._key_chain_pairs, False) |
|
||||||
self._server = _low.Server(self._completion_queue) |
|
||||||
self._port = self._server.add_secure_http2_addr( |
|
||||||
address, server_credentials) |
|
||||||
self._server.start() |
|
||||||
|
|
||||||
self._server.service(None) |
|
||||||
|
|
||||||
self._pool.submit(self._spin, self._completion_queue, self._server) |
|
||||||
self._spinning = True |
|
||||||
|
|
||||||
return self |
|
||||||
|
|
||||||
# TODO(nathaniel): Expose graceful-shutdown semantics in which this object |
|
||||||
# enters a state in which it finishes ongoing RPCs but refuses new ones. |
|
||||||
def _stop(self): |
|
||||||
"""Stops this ForeLink. |
|
||||||
|
|
||||||
This method must be called for proper termination of this object, and no |
|
||||||
attempts to exchange tickets with this object may be made after this method |
|
||||||
has been called. |
|
||||||
""" |
|
||||||
with self._condition: |
|
||||||
self._server.stop() |
|
||||||
# TODO(nathaniel): Yep, this is weird. Deleting a server shouldn't have a |
|
||||||
# behaviorally significant side-effect. |
|
||||||
self._server = None |
|
||||||
self._completion_queue.stop() |
|
||||||
|
|
||||||
while self._spinning: |
|
||||||
self._condition.wait() |
|
||||||
|
|
||||||
self._port = None |
|
||||||
|
|
||||||
def __enter__(self): |
|
||||||
"""See activated.Activated.__enter__ for specification.""" |
|
||||||
return self._start() |
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb): |
|
||||||
"""See activated.Activated.__exit__ for specification.""" |
|
||||||
self._stop() |
|
||||||
return False |
|
||||||
|
|
||||||
def start(self): |
|
||||||
"""See activated.Activated.start for specification.""" |
|
||||||
return self._start() |
|
||||||
|
|
||||||
def stop(self): |
|
||||||
"""See activated.Activated.stop for specification.""" |
|
||||||
self._stop() |
|
||||||
|
|
||||||
def port(self): |
|
||||||
"""Identifies the port on which this ForeLink is servicing RPCs. |
|
||||||
|
|
||||||
Returns: |
|
||||||
The number of the port on which this ForeLink is servicing RPCs, or None |
|
||||||
if this ForeLink is not currently activated and servicing RPCs. |
|
||||||
""" |
|
||||||
with self._condition: |
|
||||||
return self._port |
|
||||||
|
|
||||||
def accept_back_to_front_ticket(self, ticket): |
|
||||||
"""See base_interfaces.ForeLink.accept_back_to_front_ticket for spec.""" |
|
||||||
with self._condition: |
|
||||||
if self._server is None: |
|
||||||
return |
|
||||||
|
|
||||||
if ticket.kind is base_interfaces.BackToFrontTicket.Kind.CONTINUATION: |
|
||||||
self._continue(ticket.operation_id, ticket.payload) |
|
||||||
elif ticket.kind is base_interfaces.BackToFrontTicket.Kind.COMPLETION: |
|
||||||
self._complete(ticket.operation_id, ticket.payload) |
|
||||||
else: |
|
||||||
self._cancel(ticket.operation_id) |
|
@ -1,395 +0,0 @@ |
|||||||
# 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 RPC-invocation-side bridge between RPC Framework and GRPC-on-the-wire.""" |
|
||||||
|
|
||||||
import enum |
|
||||||
import logging |
|
||||||
import threading |
|
||||||
import time |
|
||||||
|
|
||||||
from grpc._adapter import _common |
|
||||||
from grpc._adapter import _intermediary_low as _low |
|
||||||
from grpc.framework.base import interfaces as base_interfaces |
|
||||||
from grpc.framework.base import null |
|
||||||
from grpc.framework.foundation import activated |
|
||||||
from grpc.framework.foundation import logging_pool |
|
||||||
|
|
||||||
_THREAD_POOL_SIZE = 10 |
|
||||||
|
|
||||||
_INVOCATION_EVENT_KINDS = ( |
|
||||||
_low.Event.Kind.METADATA_ACCEPTED, |
|
||||||
_low.Event.Kind.FINISH |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
@enum.unique |
|
||||||
class _LowWrite(enum.Enum): |
|
||||||
"""The possible categories of low-level write state.""" |
|
||||||
|
|
||||||
OPEN = 'OPEN' |
|
||||||
ACTIVE = 'ACTIVE' |
|
||||||
CLOSED = 'CLOSED' |
|
||||||
|
|
||||||
|
|
||||||
class _RPCState(object): |
|
||||||
"""The full state of any tracked RPC. |
|
||||||
|
|
||||||
Attributes: |
|
||||||
call: The _low.Call object for the RPC. |
|
||||||
outstanding: The set of Event.Kind values describing expected future events |
|
||||||
for the RPC. |
|
||||||
active: A boolean indicating whether or not the RPC is active. |
|
||||||
common: An _common.RPCState describing additional state for the RPC. |
|
||||||
""" |
|
||||||
|
|
||||||
def __init__(self, call, outstanding, active, common): |
|
||||||
self.call = call |
|
||||||
self.outstanding = outstanding |
|
||||||
self.active = active |
|
||||||
self.common = common |
|
||||||
|
|
||||||
|
|
||||||
def _write(operation_id, call, outstanding, write_state, serialized_payload): |
|
||||||
if write_state.low is _LowWrite.OPEN: |
|
||||||
call.write(serialized_payload, operation_id, 0) |
|
||||||
outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) |
|
||||||
write_state.low = _LowWrite.ACTIVE |
|
||||||
elif write_state.low is _LowWrite.ACTIVE: |
|
||||||
write_state.pending.append(serialized_payload) |
|
||||||
else: |
|
||||||
raise ValueError('Write attempted after writes completed!') |
|
||||||
|
|
||||||
|
|
||||||
class RearLink(base_interfaces.RearLink, activated.Activated): |
|
||||||
"""An invocation-side bridge between RPC Framework and the C-ish _low code.""" |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, host, port, pool, request_serializers, response_deserializers, |
|
||||||
secure, root_certificates, private_key, certificate_chain, |
|
||||||
metadata_transformer=None, server_host_override=None): |
|
||||||
"""Constructor. |
|
||||||
|
|
||||||
Args: |
|
||||||
host: The host to which to connect for RPC service. |
|
||||||
port: The port to which to connect for RPC service. |
|
||||||
pool: A thread pool. |
|
||||||
request_serializers: A dict from RPC method names to request object |
|
||||||
serializer behaviors. |
|
||||||
response_deserializers: A dict from RPC method names to response object |
|
||||||
deserializer behaviors. |
|
||||||
secure: A boolean indicating whether or not to use a secure connection. |
|
||||||
root_certificates: The PEM-encoded root certificates or None to ask for |
|
||||||
them to be retrieved from a default location. |
|
||||||
private_key: The PEM-encoded private key to use or None if no private |
|
||||||
key should be used. |
|
||||||
certificate_chain: The PEM-encoded certificate chain to use or None if |
|
||||||
no certificate chain should be used. |
|
||||||
metadata_transformer: A function that given a metadata object produces |
|
||||||
another metadata to be used in the underlying communication on the |
|
||||||
wire. |
|
||||||
server_host_override: (For testing only) the target name used for SSL |
|
||||||
host name checking. |
|
||||||
""" |
|
||||||
self._condition = threading.Condition() |
|
||||||
self._host = host |
|
||||||
self._port = port |
|
||||||
self._pool = pool |
|
||||||
self._request_serializers = request_serializers |
|
||||||
self._response_deserializers = response_deserializers |
|
||||||
|
|
||||||
self._fore_link = null.NULL_FORE_LINK |
|
||||||
self._completion_queue = None |
|
||||||
self._channel = None |
|
||||||
self._rpc_states = {} |
|
||||||
self._spinning = False |
|
||||||
if secure: |
|
||||||
self._client_credentials = _low.ClientCredentials( |
|
||||||
root_certificates, private_key, certificate_chain) |
|
||||||
else: |
|
||||||
self._client_credentials = None |
|
||||||
self._root_certificates = root_certificates |
|
||||||
self._private_key = private_key |
|
||||||
self._certificate_chain = certificate_chain |
|
||||||
self._metadata_transformer = metadata_transformer |
|
||||||
self._server_host_override = server_host_override |
|
||||||
|
|
||||||
def _on_write_event(self, operation_id, event, rpc_state): |
|
||||||
if event.write_accepted: |
|
||||||
if rpc_state.common.write.pending: |
|
||||||
rpc_state.call.write( |
|
||||||
rpc_state.common.write.pending.pop(0), operation_id, 0) |
|
||||||
rpc_state.outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) |
|
||||||
elif rpc_state.common.write.high is _common.HighWrite.CLOSED: |
|
||||||
rpc_state.call.complete(operation_id) |
|
||||||
rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) |
|
||||||
rpc_state.common.write.low = _LowWrite.CLOSED |
|
||||||
else: |
|
||||||
rpc_state.common.write.low = _LowWrite.OPEN |
|
||||||
else: |
|
||||||
logging.error('RPC write not accepted! Event: %s', (event,)) |
|
||||||
rpc_state.active = False |
|
||||||
ticket = base_interfaces.BackToFrontTicket( |
|
||||||
operation_id, rpc_state.common.sequence_number, |
|
||||||
base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None) |
|
||||||
rpc_state.common.sequence_number += 1 |
|
||||||
self._fore_link.accept_back_to_front_ticket(ticket) |
|
||||||
|
|
||||||
def _on_read_event(self, operation_id, event, rpc_state): |
|
||||||
if event.bytes is not None: |
|
||||||
rpc_state.call.read(operation_id) |
|
||||||
rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED) |
|
||||||
|
|
||||||
ticket = base_interfaces.BackToFrontTicket( |
|
||||||
operation_id, rpc_state.common.sequence_number, |
|
||||||
base_interfaces.BackToFrontTicket.Kind.CONTINUATION, |
|
||||||
rpc_state.common.deserializer(event.bytes)) |
|
||||||
rpc_state.common.sequence_number += 1 |
|
||||||
self._fore_link.accept_back_to_front_ticket(ticket) |
|
||||||
|
|
||||||
def _on_complete_event(self, operation_id, event, rpc_state): |
|
||||||
if not event.complete_accepted: |
|
||||||
logging.error('RPC complete not accepted! Event: %s', (event,)) |
|
||||||
rpc_state.active = False |
|
||||||
ticket = base_interfaces.BackToFrontTicket( |
|
||||||
operation_id, rpc_state.common.sequence_number, |
|
||||||
base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE, None) |
|
||||||
rpc_state.common.sequence_number += 1 |
|
||||||
self._fore_link.accept_back_to_front_ticket(ticket) |
|
||||||
|
|
||||||
# TODO(nathaniel): Metadata support. |
|
||||||
def _on_metadata_event(self, operation_id, event, rpc_state): # pylint: disable=unused-argument |
|
||||||
rpc_state.call.read(operation_id) |
|
||||||
rpc_state.outstanding.add(_low.Event.Kind.READ_ACCEPTED) |
|
||||||
|
|
||||||
def _on_finish_event(self, operation_id, event, rpc_state): |
|
||||||
"""Handle termination of an RPC.""" |
|
||||||
# TODO(nathaniel): Cover all statuses. |
|
||||||
if event.status.code is _low.Code.OK: |
|
||||||
kind = base_interfaces.BackToFrontTicket.Kind.COMPLETION |
|
||||||
elif event.status.code is _low.Code.CANCELLED: |
|
||||||
kind = base_interfaces.BackToFrontTicket.Kind.CANCELLATION |
|
||||||
elif event.status.code is _low.Code.DEADLINE_EXCEEDED: |
|
||||||
kind = base_interfaces.BackToFrontTicket.Kind.EXPIRATION |
|
||||||
else: |
|
||||||
kind = base_interfaces.BackToFrontTicket.Kind.TRANSMISSION_FAILURE |
|
||||||
ticket = base_interfaces.BackToFrontTicket( |
|
||||||
operation_id, rpc_state.common.sequence_number, kind, None) |
|
||||||
rpc_state.common.sequence_number += 1 |
|
||||||
self._fore_link.accept_back_to_front_ticket(ticket) |
|
||||||
|
|
||||||
def _spin(self, completion_queue): |
|
||||||
while True: |
|
||||||
event = completion_queue.get(None) |
|
||||||
operation_id = event.tag |
|
||||||
|
|
||||||
with self._condition: |
|
||||||
rpc_state = self._rpc_states[operation_id] |
|
||||||
rpc_state.outstanding.remove(event.kind) |
|
||||||
if rpc_state.active and self._completion_queue is not None: |
|
||||||
if event.kind is _low.Event.Kind.WRITE_ACCEPTED: |
|
||||||
self._on_write_event(operation_id, event, rpc_state) |
|
||||||
elif event.kind is _low.Event.Kind.METADATA_ACCEPTED: |
|
||||||
self._on_metadata_event(operation_id, event, rpc_state) |
|
||||||
elif event.kind is _low.Event.Kind.READ_ACCEPTED: |
|
||||||
self._on_read_event(operation_id, event, rpc_state) |
|
||||||
elif event.kind is _low.Event.Kind.COMPLETE_ACCEPTED: |
|
||||||
self._on_complete_event(operation_id, event, rpc_state) |
|
||||||
elif event.kind is _low.Event.Kind.FINISH: |
|
||||||
self._on_finish_event(operation_id, event, rpc_state) |
|
||||||
else: |
|
||||||
logging.error('Illegal RPC event! %s', (event,)) |
|
||||||
|
|
||||||
if not rpc_state.outstanding: |
|
||||||
self._rpc_states.pop(operation_id) |
|
||||||
if not self._rpc_states: |
|
||||||
self._spinning = False |
|
||||||
self._condition.notify_all() |
|
||||||
return |
|
||||||
|
|
||||||
def _invoke(self, operation_id, name, high_state, payload, timeout): |
|
||||||
"""Invoke an RPC. |
|
||||||
|
|
||||||
Args: |
|
||||||
operation_id: Any object to be used as an operation ID for the RPC. |
|
||||||
name: The RPC method name. |
|
||||||
high_state: A _common.HighWrite value representing the "high write state" |
|
||||||
of the RPC. |
|
||||||
payload: A payload object for the RPC or None if no payload was given at |
|
||||||
invocation-time. |
|
||||||
timeout: A duration of time in seconds to allow for the RPC. |
|
||||||
""" |
|
||||||
request_serializer = self._request_serializers[name] |
|
||||||
call = _low.Call(self._channel, self._completion_queue, name, self._host, time.time() + timeout) |
|
||||||
if self._metadata_transformer is not None: |
|
||||||
metadata = self._metadata_transformer([]) |
|
||||||
for metadata_key, metadata_value in metadata: |
|
||||||
call.add_metadata(metadata_key, metadata_value) |
|
||||||
call.invoke(self._completion_queue, operation_id, operation_id) |
|
||||||
outstanding = set(_INVOCATION_EVENT_KINDS) |
|
||||||
|
|
||||||
if payload is None: |
|
||||||
if high_state is _common.HighWrite.CLOSED: |
|
||||||
call.complete(operation_id) |
|
||||||
low_state = _LowWrite.CLOSED |
|
||||||
outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) |
|
||||||
else: |
|
||||||
low_state = _LowWrite.OPEN |
|
||||||
else: |
|
||||||
serialized_payload = request_serializer(payload) |
|
||||||
call.write(serialized_payload, operation_id, 0) |
|
||||||
outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) |
|
||||||
low_state = _LowWrite.ACTIVE |
|
||||||
|
|
||||||
write_state = _common.WriteState(low_state, high_state, []) |
|
||||||
common_state = _common.CommonRPCState( |
|
||||||
write_state, 0, self._response_deserializers[name], request_serializer) |
|
||||||
self._rpc_states[operation_id] = _RPCState( |
|
||||||
call, outstanding, True, common_state) |
|
||||||
|
|
||||||
if not self._spinning: |
|
||||||
self._pool.submit(self._spin, self._completion_queue) |
|
||||||
self._spinning = True |
|
||||||
|
|
||||||
def _commence(self, operation_id, name, payload, timeout): |
|
||||||
self._invoke(operation_id, name, _common.HighWrite.OPEN, payload, timeout) |
|
||||||
|
|
||||||
def _continue(self, operation_id, payload): |
|
||||||
rpc_state = self._rpc_states.get(operation_id, None) |
|
||||||
if rpc_state is None or not rpc_state.active: |
|
||||||
return |
|
||||||
|
|
||||||
_write( |
|
||||||
operation_id, rpc_state.call, rpc_state.outstanding, |
|
||||||
rpc_state.common.write, rpc_state.common.serializer(payload)) |
|
||||||
|
|
||||||
def _complete(self, operation_id, payload): |
|
||||||
"""Close writes associated with an ongoing RPC. |
|
||||||
|
|
||||||
Args: |
|
||||||
operation_id: Any object being use as an operation ID for the RPC. |
|
||||||
payload: A payload object for the RPC (and thus the last payload object |
|
||||||
for the RPC) or None if no payload was given along with the instruction |
|
||||||
to indicate the end of writes for the RPC. |
|
||||||
""" |
|
||||||
rpc_state = self._rpc_states.get(operation_id, None) |
|
||||||
if rpc_state is None or not rpc_state.active: |
|
||||||
return |
|
||||||
|
|
||||||
write_state = rpc_state.common.write |
|
||||||
if payload is None: |
|
||||||
if write_state.low is _LowWrite.OPEN: |
|
||||||
rpc_state.call.complete(operation_id) |
|
||||||
rpc_state.outstanding.add(_low.Event.Kind.COMPLETE_ACCEPTED) |
|
||||||
write_state.low = _LowWrite.CLOSED |
|
||||||
else: |
|
||||||
_write( |
|
||||||
operation_id, rpc_state.call, rpc_state.outstanding, write_state, |
|
||||||
rpc_state.common.serializer(payload)) |
|
||||||
write_state.high = _common.HighWrite.CLOSED |
|
||||||
|
|
||||||
def _entire(self, operation_id, name, payload, timeout): |
|
||||||
self._invoke(operation_id, name, _common.HighWrite.CLOSED, payload, timeout) |
|
||||||
|
|
||||||
def _cancel(self, operation_id): |
|
||||||
rpc_state = self._rpc_states.get(operation_id, None) |
|
||||||
if rpc_state is not None and rpc_state.active: |
|
||||||
rpc_state.call.cancel() |
|
||||||
rpc_state.active = False |
|
||||||
|
|
||||||
def join_fore_link(self, fore_link): |
|
||||||
"""See base_interfaces.RearLink.join_fore_link for specification.""" |
|
||||||
with self._condition: |
|
||||||
self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link |
|
||||||
|
|
||||||
def _start(self): |
|
||||||
"""Starts this RearLink. |
|
||||||
|
|
||||||
This method must be called before attempting to exchange tickets with this |
|
||||||
object. |
|
||||||
""" |
|
||||||
with self._condition: |
|
||||||
self._completion_queue = _low.CompletionQueue() |
|
||||||
self._channel = _low.Channel( |
|
||||||
'%s:%d' % (self._host, self._port), self._client_credentials, |
|
||||||
server_host_override=self._server_host_override) |
|
||||||
return self |
|
||||||
|
|
||||||
def _stop(self): |
|
||||||
"""Stops this RearLink. |
|
||||||
|
|
||||||
This method must be called for proper termination of this object, and no |
|
||||||
attempts to exchange tickets with this object may be made after this method |
|
||||||
has been called. |
|
||||||
""" |
|
||||||
with self._condition: |
|
||||||
self._completion_queue.stop() |
|
||||||
self._completion_queue = None |
|
||||||
|
|
||||||
while self._spinning: |
|
||||||
self._condition.wait() |
|
||||||
|
|
||||||
def __enter__(self): |
|
||||||
"""See activated.Activated.__enter__ for specification.""" |
|
||||||
return self._start() |
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb): |
|
||||||
"""See activated.Activated.__exit__ for specification.""" |
|
||||||
self._stop() |
|
||||||
return False |
|
||||||
|
|
||||||
def start(self): |
|
||||||
"""See activated.Activated.start for specification.""" |
|
||||||
return self._start() |
|
||||||
|
|
||||||
def stop(self): |
|
||||||
"""See activated.Activated.stop for specification.""" |
|
||||||
self._stop() |
|
||||||
|
|
||||||
def accept_front_to_back_ticket(self, ticket): |
|
||||||
"""See base_interfaces.RearLink.accept_front_to_back_ticket for spec.""" |
|
||||||
with self._condition: |
|
||||||
if self._completion_queue is None: |
|
||||||
return |
|
||||||
|
|
||||||
if ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMMENCEMENT: |
|
||||||
self._commence( |
|
||||||
ticket.operation_id, ticket.name, ticket.payload, ticket.timeout) |
|
||||||
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CONTINUATION: |
|
||||||
self._continue(ticket.operation_id, ticket.payload) |
|
||||||
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.COMPLETION: |
|
||||||
self._complete(ticket.operation_id, ticket.payload) |
|
||||||
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.ENTIRE: |
|
||||||
self._entire( |
|
||||||
ticket.operation_id, ticket.name, ticket.payload, ticket.timeout) |
|
||||||
elif ticket.kind is base_interfaces.FrontToBackTicket.Kind.CANCELLATION: |
|
||||||
self._cancel(ticket.operation_id) |
|
||||||
else: |
|
||||||
# NOTE(nathaniel): All other categories are treated as cancellation. |
|
||||||
self._cancel(ticket.operation_id) |
|
@ -1,35 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
import warnings |
|
||||||
|
|
||||||
warnings.simplefilter('always', DeprecationWarning) |
|
||||||
warnings.warn('the alpha API (includes this package) is deprecated, ' |
|
||||||
'unmaintained, and no longer tested. Please migrate to the beta ' |
|
||||||
'API.', DeprecationWarning, stacklevel=2) |
|
@ -1,262 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
"""Entry points into GRPC.""" |
|
||||||
|
|
||||||
import threading |
|
||||||
|
|
||||||
from grpc._adapter import fore as _fore |
|
||||||
from grpc._adapter import rear as _rear |
|
||||||
from grpc.framework.alpha import _face_utilities |
|
||||||
from grpc.framework.alpha import _reexport |
|
||||||
from grpc.framework.alpha import interfaces |
|
||||||
from grpc.framework.base import implementations as _base_implementations |
|
||||||
from grpc.framework.base import util as _base_utilities |
|
||||||
from grpc.framework.face import implementations as _face_implementations |
|
||||||
from grpc.framework.foundation import logging_pool |
|
||||||
|
|
||||||
_DEFAULT_THREAD_POOL_SIZE = 8 |
|
||||||
_ONE_DAY_IN_SECONDS = 24 * 60 * 60 |
|
||||||
|
|
||||||
|
|
||||||
class _Server(interfaces.Server): |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, breakdown, port, private_key, certificate_chain, |
|
||||||
thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): |
|
||||||
self._lock = threading.Lock() |
|
||||||
self._breakdown = breakdown |
|
||||||
self._port = port |
|
||||||
if private_key is None or certificate_chain is None: |
|
||||||
self._key_chain_pairs = () |
|
||||||
else: |
|
||||||
self._key_chain_pairs = ((private_key, certificate_chain),) |
|
||||||
|
|
||||||
self._pool_size = thread_pool_size |
|
||||||
self._pool = None |
|
||||||
self._back = None |
|
||||||
self._fore_link = None |
|
||||||
|
|
||||||
def _start(self): |
|
||||||
with self._lock: |
|
||||||
if self._pool is None: |
|
||||||
self._pool = logging_pool.pool(self._pool_size) |
|
||||||
servicer = _face_implementations.servicer( |
|
||||||
self._pool, self._breakdown.implementations, None) |
|
||||||
self._back = _base_implementations.back_link( |
|
||||||
servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS, |
|
||||||
_ONE_DAY_IN_SECONDS) |
|
||||||
self._fore_link = _fore.ForeLink( |
|
||||||
self._pool, self._breakdown.request_deserializers, |
|
||||||
self._breakdown.response_serializers, None, self._key_chain_pairs, |
|
||||||
port=self._port) |
|
||||||
self._back.join_fore_link(self._fore_link) |
|
||||||
self._fore_link.join_rear_link(self._back) |
|
||||||
self._fore_link.start() |
|
||||||
else: |
|
||||||
raise ValueError('Server currently running!') |
|
||||||
|
|
||||||
def _stop(self): |
|
||||||
with self._lock: |
|
||||||
if self._pool is None: |
|
||||||
raise ValueError('Server not running!') |
|
||||||
else: |
|
||||||
self._fore_link.stop() |
|
||||||
_base_utilities.wait_for_idle(self._back) |
|
||||||
self._pool.shutdown(wait=True) |
|
||||||
self._fore_link = None |
|
||||||
self._back = None |
|
||||||
self._pool = None |
|
||||||
|
|
||||||
def __enter__(self): |
|
||||||
self._start() |
|
||||||
return self |
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb): |
|
||||||
self._stop() |
|
||||||
return False |
|
||||||
|
|
||||||
def start(self): |
|
||||||
self._start() |
|
||||||
|
|
||||||
def stop(self): |
|
||||||
self._stop() |
|
||||||
|
|
||||||
def port(self): |
|
||||||
with self._lock: |
|
||||||
return self._fore_link.port() |
|
||||||
|
|
||||||
|
|
||||||
class _Stub(interfaces.Stub): |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, breakdown, host, port, secure, root_certificates, private_key, |
|
||||||
certificate_chain, metadata_transformer=None, server_host_override=None, |
|
||||||
thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): |
|
||||||
self._lock = threading.Lock() |
|
||||||
self._breakdown = breakdown |
|
||||||
self._host = host |
|
||||||
self._port = port |
|
||||||
self._secure = secure |
|
||||||
self._root_certificates = root_certificates |
|
||||||
self._private_key = private_key |
|
||||||
self._certificate_chain = certificate_chain |
|
||||||
self._metadata_transformer = metadata_transformer |
|
||||||
self._server_host_override = server_host_override |
|
||||||
|
|
||||||
self._pool_size = thread_pool_size |
|
||||||
self._pool = None |
|
||||||
self._front = None |
|
||||||
self._rear_link = None |
|
||||||
self._understub = None |
|
||||||
|
|
||||||
def __enter__(self): |
|
||||||
with self._lock: |
|
||||||
if self._pool is None: |
|
||||||
self._pool = logging_pool.pool(self._pool_size) |
|
||||||
self._front = _base_implementations.front_link( |
|
||||||
self._pool, self._pool, self._pool) |
|
||||||
self._rear_link = _rear.RearLink( |
|
||||||
self._host, self._port, self._pool, |
|
||||||
self._breakdown.request_serializers, |
|
||||||
self._breakdown.response_deserializers, self._secure, |
|
||||||
self._root_certificates, self._private_key, self._certificate_chain, |
|
||||||
metadata_transformer=self._metadata_transformer, |
|
||||||
server_host_override=self._server_host_override) |
|
||||||
self._front.join_rear_link(self._rear_link) |
|
||||||
self._rear_link.join_fore_link(self._front) |
|
||||||
self._rear_link.start() |
|
||||||
self._understub = _face_implementations.dynamic_stub( |
|
||||||
self._breakdown.face_cardinalities, self._front, self._pool, '') |
|
||||||
else: |
|
||||||
raise ValueError('Tried to __enter__ already-__enter__ed Stub!') |
|
||||||
return self |
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb): |
|
||||||
with self._lock: |
|
||||||
if self._pool is None: |
|
||||||
raise ValueError('Tried to __exit__ non-__enter__ed Stub!') |
|
||||||
else: |
|
||||||
self._rear_link.stop() |
|
||||||
_base_utilities.wait_for_idle(self._front) |
|
||||||
self._pool.shutdown(wait=True) |
|
||||||
self._rear_link = None |
|
||||||
self._front = None |
|
||||||
self._pool = None |
|
||||||
self._understub = None |
|
||||||
return False |
|
||||||
|
|
||||||
def __getattr__(self, attr): |
|
||||||
with self._lock: |
|
||||||
if self._pool is None: |
|
||||||
raise ValueError('Tried to __getattr__ non-__enter__ed Stub!') |
|
||||||
else: |
|
||||||
method_cardinality = self._breakdown.cardinalities.get(attr) |
|
||||||
underlying_attr = getattr( |
|
||||||
self._understub, self._breakdown.qualified_names.get(attr), None) |
|
||||||
if method_cardinality is interfaces.Cardinality.UNARY_UNARY: |
|
||||||
return _reexport.unary_unary_sync_async(underlying_attr) |
|
||||||
elif method_cardinality is interfaces.Cardinality.UNARY_STREAM: |
|
||||||
return lambda request, timeout: _reexport.cancellable_iterator( |
|
||||||
underlying_attr(request, timeout)) |
|
||||||
elif method_cardinality is interfaces.Cardinality.STREAM_UNARY: |
|
||||||
return _reexport.stream_unary_sync_async(underlying_attr) |
|
||||||
elif method_cardinality is interfaces.Cardinality.STREAM_STREAM: |
|
||||||
return lambda request_iterator, timeout: ( |
|
||||||
_reexport.cancellable_iterator(underlying_attr( |
|
||||||
request_iterator, timeout))) |
|
||||||
else: |
|
||||||
raise AttributeError(attr) |
|
||||||
|
|
||||||
|
|
||||||
def stub( |
|
||||||
service_name, methods, host, port, metadata_transformer=None, secure=False, |
|
||||||
root_certificates=None, private_key=None, certificate_chain=None, |
|
||||||
server_host_override=None, thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): |
|
||||||
"""Constructs an interfaces.Stub. |
|
||||||
|
|
||||||
Args: |
|
||||||
service_name: The package-qualified full name of the service. |
|
||||||
methods: A dictionary from RPC method name to |
|
||||||
interfaces.RpcMethodInvocationDescription describing the RPCs to be |
|
||||||
supported by the created stub. The RPC method names in the dictionary are |
|
||||||
not qualified by the service name or decorated in any other way. |
|
||||||
host: The host to which to connect for RPC service. |
|
||||||
port: The port to which to connect for RPC service. |
|
||||||
metadata_transformer: A callable that given a metadata object produces |
|
||||||
another metadata object to be used in the underlying communication on the |
|
||||||
wire. |
|
||||||
secure: Whether or not to construct the stub with a secure connection. |
|
||||||
root_certificates: The PEM-encoded root certificates or None to ask for |
|
||||||
them to be retrieved from a default location. |
|
||||||
private_key: The PEM-encoded private key to use or None if no private key |
|
||||||
should be used. |
|
||||||
certificate_chain: The PEM-encoded certificate chain to use or None if no |
|
||||||
certificate chain should be used. |
|
||||||
server_host_override: (For testing only) the target name used for SSL |
|
||||||
host name checking. |
|
||||||
thread_pool_size: The maximum number of threads to allow in the backing |
|
||||||
thread pool. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.Stub affording RPC invocation. |
|
||||||
""" |
|
||||||
breakdown = _face_utilities.break_down_invocation(service_name, methods) |
|
||||||
return _Stub( |
|
||||||
breakdown, host, port, secure, root_certificates, private_key, |
|
||||||
certificate_chain, server_host_override=server_host_override, |
|
||||||
metadata_transformer=metadata_transformer, |
|
||||||
thread_pool_size=thread_pool_size) |
|
||||||
|
|
||||||
|
|
||||||
def server( |
|
||||||
service_name, methods, port, private_key=None, certificate_chain=None, |
|
||||||
thread_pool_size=_DEFAULT_THREAD_POOL_SIZE): |
|
||||||
"""Constructs an interfaces.Server. |
|
||||||
|
|
||||||
Args: |
|
||||||
service_name: The package-qualified full name of the service. |
|
||||||
methods: A dictionary from RPC method name to |
|
||||||
interfaces.RpcMethodServiceDescription describing the RPCs to |
|
||||||
be serviced by the created server. The RPC method names in the dictionary |
|
||||||
are not qualified by the service name or decorated in any other way. |
|
||||||
port: The port on which to serve or zero to ask for a port to be |
|
||||||
automatically selected. |
|
||||||
private_key: A pem-encoded private key, or None for an insecure server. |
|
||||||
certificate_chain: A pem-encoded certificate chain, or None for an insecure |
|
||||||
server. |
|
||||||
thread_pool_size: The maximum number of threads to allow in the backing |
|
||||||
thread pool. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.Server that will serve secure traffic. |
|
||||||
""" |
|
||||||
breakdown = _face_utilities.break_down_service(service_name, methods) |
|
||||||
return _Server(breakdown, port, private_key, certificate_chain, |
|
||||||
thread_pool_size=thread_pool_size) |
|
@ -1,35 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
import warnings |
|
||||||
|
|
||||||
warnings.simplefilter('always', DeprecationWarning) |
|
||||||
warnings.warn('the alpha API (includes this package) is deprecated, ' |
|
||||||
'unmaintained, and no longer tested. Please migrate to the beta ' |
|
||||||
'API.', DeprecationWarning, stacklevel=2) |
|
@ -1,183 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
import abc |
|
||||||
import collections |
|
||||||
|
|
||||||
import six |
|
||||||
|
|
||||||
# face_interfaces is referenced from specification in this module. |
|
||||||
from grpc.framework.common import cardinality |
|
||||||
from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import |
|
||||||
from grpc.framework.face import utilities as face_utilities |
|
||||||
from grpc.framework.alpha import _reexport |
|
||||||
from grpc.framework.alpha import interfaces |
|
||||||
|
|
||||||
|
|
||||||
def _qualified_name(service_name, method_name): |
|
||||||
return '/%s/%s' % (service_name, method_name) |
|
||||||
|
|
||||||
|
|
||||||
# TODO(nathaniel): This structure is getting bloated; it could be shrunk if |
|
||||||
# implementations._Stub used a generic rather than a dynamic underlying |
|
||||||
# face-layer stub. |
|
||||||
class InvocationBreakdown(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""An intermediate representation of invocation-side views of RPC methods. |
|
||||||
|
|
||||||
Attributes: |
|
||||||
cardinalities: A dictionary from RPC method name to interfaces.Cardinality |
|
||||||
value. |
|
||||||
qualified_names: A dictionary from unqualified RPC method name to |
|
||||||
service-qualified RPC method name. |
|
||||||
face_cardinalities: A dictionary from service-qualified RPC method name to |
|
||||||
to cardinality.Cardinality value. |
|
||||||
request_serializers: A dictionary from service-qualified RPC method name to |
|
||||||
callable behavior to be used serializing request values for the RPC. |
|
||||||
response_deserializers: A dictionary from service-qualified RPC method name |
|
||||||
to callable behavior to be used deserializing response values for the |
|
||||||
RPC. |
|
||||||
""" |
|
||||||
|
|
||||||
|
|
||||||
class _EasyInvocationBreakdown( |
|
||||||
InvocationBreakdown, |
|
||||||
collections.namedtuple( |
|
||||||
'_EasyInvocationBreakdown', |
|
||||||
('cardinalities', 'qualified_names', 'face_cardinalities', |
|
||||||
'request_serializers', 'response_deserializers'))): |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
class ServiceBreakdown(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""An intermediate representation of service-side views of RPC methods. |
|
||||||
|
|
||||||
Attributes: |
|
||||||
implementations: A dictionary from service-qualified RPC method name to |
|
||||||
face_interfaces.MethodImplementation implementing the RPC method. |
|
||||||
request_deserializers: A dictionary from service-qualified RPC method name |
|
||||||
to callable behavior to be used deserializing request values for the RPC. |
|
||||||
response_serializers: A dictionary from service-qualified RPC method name |
|
||||||
to callable behavior to be used serializing response values for the RPC. |
|
||||||
""" |
|
||||||
|
|
||||||
|
|
||||||
class _EasyServiceBreakdown( |
|
||||||
ServiceBreakdown, |
|
||||||
collections.namedtuple( |
|
||||||
'_EasyServiceBreakdown', |
|
||||||
('implementations', 'request_deserializers', 'response_serializers'))): |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
def break_down_invocation(service_name, method_descriptions): |
|
||||||
"""Derives an InvocationBreakdown from several RPC method descriptions. |
|
||||||
|
|
||||||
Args: |
|
||||||
service_name: The package-qualified full name of the service. |
|
||||||
method_descriptions: A dictionary from RPC method name to |
|
||||||
interfaces.RpcMethodInvocationDescription describing the RPCs. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An InvocationBreakdown corresponding to the given method descriptions. |
|
||||||
""" |
|
||||||
cardinalities = {} |
|
||||||
qualified_names = {} |
|
||||||
face_cardinalities = {} |
|
||||||
request_serializers = {} |
|
||||||
response_deserializers = {} |
|
||||||
for name, method_description in six.iteritems(method_descriptions): |
|
||||||
qualified_name = _qualified_name(service_name, name) |
|
||||||
method_cardinality = method_description.cardinality() |
|
||||||
cardinalities[name] = method_description.cardinality() |
|
||||||
qualified_names[name] = qualified_name |
|
||||||
face_cardinalities[qualified_name] = _reexport.common_cardinality( |
|
||||||
method_cardinality) |
|
||||||
request_serializers[qualified_name] = method_description.serialize_request |
|
||||||
response_deserializers[qualified_name] = ( |
|
||||||
method_description.deserialize_response) |
|
||||||
return _EasyInvocationBreakdown( |
|
||||||
cardinalities, qualified_names, face_cardinalities, request_serializers, |
|
||||||
response_deserializers) |
|
||||||
|
|
||||||
|
|
||||||
def break_down_service(service_name, method_descriptions): |
|
||||||
"""Derives a ServiceBreakdown from several RPC method descriptions. |
|
||||||
|
|
||||||
Args: |
|
||||||
method_descriptions: A dictionary from RPC method name to |
|
||||||
interfaces.RpcMethodServiceDescription describing the RPCs. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A ServiceBreakdown corresponding to the given method descriptions. |
|
||||||
""" |
|
||||||
implementations = {} |
|
||||||
request_deserializers = {} |
|
||||||
response_serializers = {} |
|
||||||
for name, method_description in six.iteritems(method_descriptions): |
|
||||||
qualified_name = _qualified_name(service_name, name) |
|
||||||
method_cardinality = method_description.cardinality() |
|
||||||
if method_cardinality is interfaces.Cardinality.UNARY_UNARY: |
|
||||||
def service( |
|
||||||
request, face_rpc_context, |
|
||||||
service_behavior=method_description.service_unary_unary): |
|
||||||
return service_behavior( |
|
||||||
request, _reexport.rpc_context(face_rpc_context)) |
|
||||||
implementations[qualified_name] = face_utilities.unary_unary_inline( |
|
||||||
service) |
|
||||||
elif method_cardinality is interfaces.Cardinality.UNARY_STREAM: |
|
||||||
def service( |
|
||||||
request, face_rpc_context, |
|
||||||
service_behavior=method_description.service_unary_stream): |
|
||||||
return service_behavior( |
|
||||||
request, _reexport.rpc_context(face_rpc_context)) |
|
||||||
implementations[qualified_name] = face_utilities.unary_stream_inline( |
|
||||||
service) |
|
||||||
elif method_cardinality is interfaces.Cardinality.STREAM_UNARY: |
|
||||||
def service( |
|
||||||
request_iterator, face_rpc_context, |
|
||||||
service_behavior=method_description.service_stream_unary): |
|
||||||
return service_behavior( |
|
||||||
request_iterator, _reexport.rpc_context(face_rpc_context)) |
|
||||||
implementations[qualified_name] = face_utilities.stream_unary_inline( |
|
||||||
service) |
|
||||||
elif method_cardinality is interfaces.Cardinality.STREAM_STREAM: |
|
||||||
def service( |
|
||||||
request_iterator, face_rpc_context, |
|
||||||
service_behavior=method_description.service_stream_stream): |
|
||||||
return service_behavior( |
|
||||||
request_iterator, _reexport.rpc_context(face_rpc_context)) |
|
||||||
implementations[qualified_name] = face_utilities.stream_stream_inline( |
|
||||||
service) |
|
||||||
request_deserializers[qualified_name] = ( |
|
||||||
method_description.deserialize_request) |
|
||||||
response_serializers[qualified_name] = ( |
|
||||||
method_description.serialize_response) |
|
||||||
|
|
||||||
return _EasyServiceBreakdown( |
|
||||||
implementations, request_deserializers, response_serializers) |
|
@ -1,205 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
import six |
|
||||||
|
|
||||||
from grpc.framework.common import cardinality |
|
||||||
from grpc.framework.face import exceptions as face_exceptions |
|
||||||
from grpc.framework.face import interfaces as face_interfaces |
|
||||||
from grpc.framework.foundation import future |
|
||||||
from grpc.framework.alpha import exceptions |
|
||||||
from grpc.framework.alpha import interfaces |
|
||||||
|
|
||||||
_EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY = { |
|
||||||
interfaces.Cardinality.UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, |
|
||||||
interfaces.Cardinality.UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, |
|
||||||
interfaces.Cardinality.STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, |
|
||||||
interfaces.Cardinality.STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, |
|
||||||
} |
|
||||||
|
|
||||||
_ABORTION_REEXPORT = { |
|
||||||
face_interfaces.Abortion.CANCELLED: interfaces.Abortion.CANCELLED, |
|
||||||
face_interfaces.Abortion.EXPIRED: interfaces.Abortion.EXPIRED, |
|
||||||
face_interfaces.Abortion.NETWORK_FAILURE: |
|
||||||
interfaces.Abortion.NETWORK_FAILURE, |
|
||||||
face_interfaces.Abortion.SERVICED_FAILURE: |
|
||||||
interfaces.Abortion.SERVICED_FAILURE, |
|
||||||
face_interfaces.Abortion.SERVICER_FAILURE: |
|
||||||
interfaces.Abortion.SERVICER_FAILURE, |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
class _RpcError(exceptions.RpcError): |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
def _reexport_error(face_rpc_error): |
|
||||||
if isinstance(face_rpc_error, face_exceptions.CancellationError): |
|
||||||
return exceptions.CancellationError() |
|
||||||
elif isinstance(face_rpc_error, face_exceptions.ExpirationError): |
|
||||||
return exceptions.ExpirationError() |
|
||||||
else: |
|
||||||
return _RpcError() |
|
||||||
|
|
||||||
|
|
||||||
def _as_face_abortion_callback(abortion_callback): |
|
||||||
def face_abortion_callback(face_abortion): |
|
||||||
abortion_callback(_ABORTION_REEXPORT[face_abortion]) |
|
||||||
return face_abortion_callback |
|
||||||
|
|
||||||
|
|
||||||
class _ReexportedFuture(future.Future): |
|
||||||
|
|
||||||
def __init__(self, face_future): |
|
||||||
self._face_future = face_future |
|
||||||
|
|
||||||
def cancel(self): |
|
||||||
return self._face_future.cancel() |
|
||||||
|
|
||||||
def cancelled(self): |
|
||||||
return self._face_future.cancelled() |
|
||||||
|
|
||||||
def running(self): |
|
||||||
return self._face_future.running() |
|
||||||
|
|
||||||
def done(self): |
|
||||||
return self._face_future.done() |
|
||||||
|
|
||||||
def result(self, timeout=None): |
|
||||||
try: |
|
||||||
return self._face_future.result(timeout=timeout) |
|
||||||
except face_exceptions.RpcError as e: |
|
||||||
raise _reexport_error(e) |
|
||||||
|
|
||||||
def exception(self, timeout=None): |
|
||||||
face_error = self._face_future.exception(timeout=timeout) |
|
||||||
return None if face_error is None else _reexport_error(face_error) |
|
||||||
|
|
||||||
def traceback(self, timeout=None): |
|
||||||
return self._face_future.traceback(timeout=timeout) |
|
||||||
|
|
||||||
def add_done_callback(self, fn): |
|
||||||
self._face_future.add_done_callback(lambda unused_face_future: fn(self)) |
|
||||||
|
|
||||||
|
|
||||||
def _call_reexporting_errors(behavior, *args, **kwargs): |
|
||||||
try: |
|
||||||
return behavior(*args, **kwargs) |
|
||||||
except face_exceptions.RpcError as e: |
|
||||||
raise _reexport_error(e) |
|
||||||
|
|
||||||
|
|
||||||
def _reexported_future(face_future): |
|
||||||
return _ReexportedFuture(face_future) |
|
||||||
|
|
||||||
|
|
||||||
class _CancellableIterator(interfaces.CancellableIterator): |
|
||||||
|
|
||||||
def __init__(self, face_cancellable_iterator): |
|
||||||
self._face_cancellable_iterator = face_cancellable_iterator |
|
||||||
|
|
||||||
def __iter__(self): |
|
||||||
return self |
|
||||||
|
|
||||||
def next(self): |
|
||||||
return _call_reexporting_errors(self._face_cancellable_iterator.next) |
|
||||||
|
|
||||||
def cancel(self): |
|
||||||
self._face_cancellable_iterator.cancel() |
|
||||||
|
|
||||||
|
|
||||||
class _RpcContext(interfaces.RpcContext): |
|
||||||
|
|
||||||
def __init__(self, face_rpc_context): |
|
||||||
self._face_rpc_context = face_rpc_context |
|
||||||
|
|
||||||
def is_active(self): |
|
||||||
return self._face_rpc_context.is_active() |
|
||||||
|
|
||||||
def time_remaining(self): |
|
||||||
return self._face_rpc_context.time_remaining() |
|
||||||
|
|
||||||
def add_abortion_callback(self, abortion_callback): |
|
||||||
self._face_rpc_context.add_abortion_callback( |
|
||||||
_as_face_abortion_callback(abortion_callback)) |
|
||||||
|
|
||||||
|
|
||||||
class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync): |
|
||||||
|
|
||||||
def __init__(self, face_unary_unary_multi_callable): |
|
||||||
self._underlying = face_unary_unary_multi_callable |
|
||||||
|
|
||||||
def __call__(self, request, timeout): |
|
||||||
return _call_reexporting_errors( |
|
||||||
self._underlying, request, timeout) |
|
||||||
|
|
||||||
def async(self, request, timeout): |
|
||||||
return _ReexportedFuture(self._underlying.future(request, timeout)) |
|
||||||
|
|
||||||
|
|
||||||
class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync): |
|
||||||
|
|
||||||
def __init__(self, face_stream_unary_multi_callable): |
|
||||||
self._underlying = face_stream_unary_multi_callable |
|
||||||
|
|
||||||
def __call__(self, request_iterator, timeout): |
|
||||||
return _call_reexporting_errors( |
|
||||||
self._underlying, request_iterator, timeout) |
|
||||||
|
|
||||||
def async(self, request_iterator, timeout): |
|
||||||
return _ReexportedFuture(self._underlying.future(request_iterator, timeout)) |
|
||||||
|
|
||||||
|
|
||||||
def common_cardinality(early_adopter_cardinality): |
|
||||||
return _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[ |
|
||||||
early_adopter_cardinality] |
|
||||||
|
|
||||||
|
|
||||||
def common_cardinalities(early_adopter_cardinalities): |
|
||||||
common_cardinalities = {} |
|
||||||
for name, early_adopter_cardinality in six.iteritems(early_adopter_cardinalities): |
|
||||||
common_cardinalities[name] = _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[ |
|
||||||
early_adopter_cardinality] |
|
||||||
return common_cardinalities |
|
||||||
|
|
||||||
|
|
||||||
def rpc_context(face_rpc_context): |
|
||||||
return _RpcContext(face_rpc_context) |
|
||||||
|
|
||||||
|
|
||||||
def cancellable_iterator(face_cancellable_iterator): |
|
||||||
return _CancellableIterator(face_cancellable_iterator) |
|
||||||
|
|
||||||
|
|
||||||
def unary_unary_sync_async(face_unary_unary_multi_callable): |
|
||||||
return _UnaryUnarySyncAsync(face_unary_unary_multi_callable) |
|
||||||
|
|
||||||
|
|
||||||
def stream_unary_sync_async(face_stream_unary_multi_callable): |
|
||||||
return _StreamUnarySyncAsync(face_stream_unary_multi_callable) |
|
@ -1,384 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
"""Interfaces of GRPC.""" |
|
||||||
|
|
||||||
import abc |
|
||||||
import enum |
|
||||||
|
|
||||||
import six |
|
||||||
|
|
||||||
# exceptions is referenced from specification in this module. |
|
||||||
from grpc.framework.alpha import exceptions # pylint: disable=unused-import |
|
||||||
from grpc.framework.foundation import activated |
|
||||||
from grpc.framework.foundation import future |
|
||||||
|
|
||||||
|
|
||||||
@enum.unique |
|
||||||
class Cardinality(enum.Enum): |
|
||||||
"""Constants for the four cardinalities of RPC.""" |
|
||||||
|
|
||||||
UNARY_UNARY = 'request-unary/response-unary' |
|
||||||
UNARY_STREAM = 'request-unary/response-streaming' |
|
||||||
STREAM_UNARY = 'request-streaming/response-unary' |
|
||||||
STREAM_STREAM = 'request-streaming/response-streaming' |
|
||||||
|
|
||||||
|
|
||||||
@enum.unique |
|
||||||
class Abortion(enum.Enum): |
|
||||||
"""Categories of RPC abortion.""" |
|
||||||
|
|
||||||
CANCELLED = 'cancelled' |
|
||||||
EXPIRED = 'expired' |
|
||||||
NETWORK_FAILURE = 'network failure' |
|
||||||
SERVICED_FAILURE = 'serviced failure' |
|
||||||
SERVICER_FAILURE = 'servicer failure' |
|
||||||
|
|
||||||
|
|
||||||
class CancellableIterator(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""Implements the Iterator protocol and affords a cancel method.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def __iter__(self): |
|
||||||
"""Returns the self object in accordance with the Iterator protocol.""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
def __next__(self): |
|
||||||
return self.next() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def next(self): |
|
||||||
"""Returns a value or raises StopIteration per the Iterator protocol.""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def cancel(self): |
|
||||||
"""Requests cancellation of whatever computation underlies this iterator.""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class RpcContext(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""Provides RPC-related information and action.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def is_active(self): |
|
||||||
"""Describes whether the RPC is active or has terminated.""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def time_remaining(self): |
|
||||||
"""Describes the length of allowed time remaining for the RPC. |
|
||||||
Returns: |
|
||||||
A nonnegative float indicating the length of allowed time in seconds |
|
||||||
remaining for the RPC to complete before it is considered to have timed |
|
||||||
out. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def add_abortion_callback(self, abortion_callback): |
|
||||||
"""Registers a callback to be called if the RPC is aborted. |
|
||||||
Args: |
|
||||||
abortion_callback: A callable to be called and passed an Abortion value |
|
||||||
in the event of RPC abortion. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class UnaryUnarySyncAsync(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""Affords invoking a unary-unary RPC synchronously or asynchronously. |
|
||||||
Values implementing this interface are directly callable and present an |
|
||||||
"async" method. Both calls take a request value and a numeric timeout. |
|
||||||
Direct invocation of a value of this type invokes its associated RPC and |
|
||||||
blocks until the RPC's response is available. Calling the "async" method |
|
||||||
of a value of this type invokes its associated RPC and immediately returns a |
|
||||||
future.Future bound to the asynchronous execution of the RPC. |
|
||||||
""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def __call__(self, request, timeout): |
|
||||||
"""Synchronously invokes the underlying RPC. |
|
||||||
Args: |
|
||||||
request: The request value for the RPC. |
|
||||||
timeout: A duration of time in seconds to allow for the RPC. |
|
||||||
Returns: |
|
||||||
The response value for the RPC. |
|
||||||
Raises: |
|
||||||
exceptions.RpcError: Indicating that the RPC was aborted. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def async(self, request, timeout): |
|
||||||
"""Asynchronously invokes the underlying RPC. |
|
||||||
Args: |
|
||||||
request: The request value for the RPC. |
|
||||||
timeout: A duration of time in seconds to allow for the RPC. |
|
||||||
Returns: |
|
||||||
A future.Future representing the RPC. In the event of RPC completion, the |
|
||||||
returned Future's result value will be the response value of the RPC. |
|
||||||
In the event of RPC abortion, the returned Future's exception value |
|
||||||
will be an exceptions.RpcError. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class StreamUnarySyncAsync(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""Affords invoking a stream-unary RPC synchronously or asynchronously. |
|
||||||
Values implementing this interface are directly callable and present an |
|
||||||
"async" method. Both calls take an iterator of request values and a numeric |
|
||||||
timeout. Direct invocation of a value of this type invokes its associated RPC |
|
||||||
and blocks until the RPC's response is available. Calling the "async" method |
|
||||||
of a value of this type invokes its associated RPC and immediately returns a |
|
||||||
future.Future bound to the asynchronous execution of the RPC. |
|
||||||
""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def __call__(self, request_iterator, timeout): |
|
||||||
"""Synchronously invokes the underlying RPC. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_iterator: An iterator that yields request values for the RPC. |
|
||||||
timeout: A duration of time in seconds to allow for the RPC. |
|
||||||
|
|
||||||
Returns: |
|
||||||
The response value for the RPC. |
|
||||||
|
|
||||||
Raises: |
|
||||||
exceptions.RpcError: Indicating that the RPC was aborted. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def async(self, request_iterator, timeout): |
|
||||||
"""Asynchronously invokes the underlying RPC. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_iterator: An iterator that yields request values for the RPC. |
|
||||||
timeout: A duration of time in seconds to allow for the RPC. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A future.Future representing the RPC. In the event of RPC completion, the |
|
||||||
returned Future's result value will be the response value of the RPC. |
|
||||||
In the event of RPC abortion, the returned Future's exception value |
|
||||||
will be an exceptions.RpcError. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class RpcMethodDescription(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""A type for the common aspects of RPC method descriptions.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def cardinality(self): |
|
||||||
"""Identifies the cardinality of this RpcMethodDescription. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A Cardinality value identifying whether or not this |
|
||||||
RpcMethodDescription is request-unary or request-streaming and |
|
||||||
whether or not it is response-unary or response-streaming. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class RpcMethodInvocationDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)): |
|
||||||
"""Invocation-side description of an RPC method.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def serialize_request(self, request): |
|
||||||
"""Serializes a request value. |
|
||||||
|
|
||||||
Args: |
|
||||||
request: A request value appropriate for the RPC method described by this |
|
||||||
RpcMethodInvocationDescription. |
|
||||||
|
|
||||||
Returns: |
|
||||||
The serialization of the given request value as a |
|
||||||
bytestring. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def deserialize_response(self, serialized_response): |
|
||||||
"""Deserializes a response value. |
|
||||||
|
|
||||||
Args: |
|
||||||
serialized_response: A bytestring that is the serialization of a response |
|
||||||
value appropriate for the RPC method described by this |
|
||||||
RpcMethodInvocationDescription. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A response value corresponding to the given bytestring. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class RpcMethodServiceDescription(six.with_metaclass(abc.ABCMeta, RpcMethodDescription)): |
|
||||||
"""Service-side description of an RPC method.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def deserialize_request(self, serialized_request): |
|
||||||
"""Deserializes a request value. |
|
||||||
|
|
||||||
Args: |
|
||||||
serialized_request: A bytestring that is the serialization of a request |
|
||||||
value appropriate for the RPC method described by this |
|
||||||
RpcMethodServiceDescription. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A request value corresponding to the given bytestring. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def serialize_response(self, response): |
|
||||||
"""Serializes a response value. |
|
||||||
|
|
||||||
Args: |
|
||||||
response: A response value appropriate for the RPC method described by |
|
||||||
this RpcMethodServiceDescription. |
|
||||||
|
|
||||||
Returns: |
|
||||||
The serialization of the given response value as a |
|
||||||
bytestring. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def service_unary_unary(self, request, context): |
|
||||||
"""Carries out this RPC. |
|
||||||
|
|
||||||
This method may only be called if the cardinality of this |
|
||||||
RpcMethodServiceDescription is Cardinality.UNARY_UNARY. |
|
||||||
|
|
||||||
Args: |
|
||||||
request: A request value appropriate for the RPC method described by this |
|
||||||
RpcMethodServiceDescription. |
|
||||||
context: An RpcContext object for the RPC. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A response value appropriate for the RPC method described by this |
|
||||||
RpcMethodServiceDescription. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def service_unary_stream(self, request, context): |
|
||||||
"""Carries out this RPC. |
|
||||||
|
|
||||||
This method may only be called if the cardinality of this |
|
||||||
RpcMethodServiceDescription is Cardinality.UNARY_STREAM. |
|
||||||
|
|
||||||
Args: |
|
||||||
request: A request value appropriate for the RPC method described by this |
|
||||||
RpcMethodServiceDescription. |
|
||||||
context: An RpcContext object for the RPC. |
|
||||||
|
|
||||||
Yields: |
|
||||||
Zero or more response values appropriate for the RPC method described by |
|
||||||
this RpcMethodServiceDescription. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def service_stream_unary(self, request_iterator, context): |
|
||||||
"""Carries out this RPC. |
|
||||||
|
|
||||||
This method may only be called if the cardinality of this |
|
||||||
RpcMethodServiceDescription is Cardinality.STREAM_UNARY. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_iterator: An iterator of request values appropriate for the RPC |
|
||||||
method described by this RpcMethodServiceDescription. |
|
||||||
context: An RpcContext object for the RPC. |
|
||||||
|
|
||||||
Returns: |
|
||||||
A response value appropriate for the RPC method described by this |
|
||||||
RpcMethodServiceDescription. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def service_stream_stream(self, request_iterator, context): |
|
||||||
"""Carries out this RPC. |
|
||||||
|
|
||||||
This method may only be called if the cardinality of this |
|
||||||
RpcMethodServiceDescription is Cardinality.STREAM_STREAM. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_iterator: An iterator of request values appropriate for the RPC |
|
||||||
method described by this RpcMethodServiceDescription. |
|
||||||
context: An RpcContext object for the RPC. |
|
||||||
|
|
||||||
Yields: |
|
||||||
Zero or more response values appropriate for the RPC method described by |
|
||||||
this RpcMethodServiceDescription. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
||||||
|
|
||||||
|
|
||||||
class Stub(six.with_metaclass(abc.ABCMeta)): |
|
||||||
"""A stub with callable RPC method names for attributes. |
|
||||||
|
|
||||||
Instances of this type are context managers and only afford RPC invocation |
|
||||||
when used in context. |
|
||||||
|
|
||||||
Instances of this type, when used in context, respond to attribute access |
|
||||||
as follows: if the requested attribute is the name of a unary-unary RPC |
|
||||||
method, the value of the attribute will be a UnaryUnarySyncAsync with which |
|
||||||
to invoke the RPC method. If the requested attribute is the name of a |
|
||||||
unary-stream RPC method, the value of the attribute will be a callable taking |
|
||||||
a request object and a timeout parameter and returning a CancellableIterator |
|
||||||
that yields the response values of the RPC. If the requested attribute is the |
|
||||||
name of a stream-unary RPC method, the value of the attribute will be a |
|
||||||
StreamUnarySyncAsync with which to invoke the RPC method. If the requested |
|
||||||
attribute is the name of a stream-stream RPC method, the value of the |
|
||||||
attribute will be a callable taking an iterator of request objects and a |
|
||||||
timeout and returning a CancellableIterator that yields the response values |
|
||||||
of the RPC. |
|
||||||
|
|
||||||
In all cases indication of abortion is indicated by raising of |
|
||||||
exceptions.RpcError, exceptions.CancellationError, |
|
||||||
and exceptions.ExpirationError. |
|
||||||
""" |
|
||||||
|
|
||||||
|
|
||||||
class Server(six.with_metaclass(abc.ABCMeta, activated.Activated)): |
|
||||||
"""A GRPC Server.""" |
|
||||||
|
|
||||||
@abc.abstractmethod |
|
||||||
def port(self): |
|
||||||
"""Reports the port on which the server is serving. |
|
||||||
|
|
||||||
This method may only be called while the server is activated. |
|
||||||
|
|
||||||
Returns: |
|
||||||
The port on which the server is serving. |
|
||||||
""" |
|
||||||
raise NotImplementedError() |
|
@ -1,269 +0,0 @@ |
|||||||
# 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 GRPC.""" |
|
||||||
|
|
||||||
from grpc.framework.alpha import interfaces |
|
||||||
|
|
||||||
|
|
||||||
class _RpcMethodDescription( |
|
||||||
interfaces.RpcMethodInvocationDescription, |
|
||||||
interfaces.RpcMethodServiceDescription): |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, cardinality, unary_unary, unary_stream, stream_unary, |
|
||||||
stream_stream, request_serializer, request_deserializer, |
|
||||||
response_serializer, response_deserializer): |
|
||||||
self._cardinality = cardinality |
|
||||||
self._unary_unary = unary_unary |
|
||||||
self._unary_stream = unary_stream |
|
||||||
self._stream_unary = stream_unary |
|
||||||
self._stream_stream = stream_stream |
|
||||||
self._request_serializer = request_serializer |
|
||||||
self._request_deserializer = request_deserializer |
|
||||||
self._response_serializer = response_serializer |
|
||||||
self._response_deserializer = response_deserializer |
|
||||||
|
|
||||||
def cardinality(self): |
|
||||||
"""See interfaces.RpcMethodDescription.cardinality for specification.""" |
|
||||||
return self._cardinality |
|
||||||
|
|
||||||
def serialize_request(self, request): |
|
||||||
"""See interfaces.RpcMethodInvocationDescription.serialize_request.""" |
|
||||||
return self._request_serializer(request) |
|
||||||
|
|
||||||
def deserialize_request(self, serialized_request): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.deserialize_request.""" |
|
||||||
return self._request_deserializer(serialized_request) |
|
||||||
|
|
||||||
def serialize_response(self, response): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.serialize_response.""" |
|
||||||
return self._response_serializer(response) |
|
||||||
|
|
||||||
def deserialize_response(self, serialized_response): |
|
||||||
"""See interfaces.RpcMethodInvocationDescription.deserialize_response.""" |
|
||||||
return self._response_deserializer(serialized_response) |
|
||||||
|
|
||||||
def service_unary_unary(self, request, context): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.service_unary_unary.""" |
|
||||||
return self._unary_unary(request, context) |
|
||||||
|
|
||||||
def service_unary_stream(self, request, context): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.service_unary_stream.""" |
|
||||||
return self._unary_stream(request, context) |
|
||||||
|
|
||||||
def service_stream_unary(self, request_iterator, context): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.service_stream_unary.""" |
|
||||||
return self._stream_unary(request_iterator, context) |
|
||||||
|
|
||||||
def service_stream_stream(self, request_iterator, context): |
|
||||||
"""See interfaces.RpcMethodServiceDescription.service_stream_stream.""" |
|
||||||
return self._stream_stream(request_iterator, context) |
|
||||||
|
|
||||||
|
|
||||||
def unary_unary_invocation_description( |
|
||||||
request_serializer, response_deserializer): |
|
||||||
"""Creates an interfaces.RpcMethodInvocationDescription for an RPC method. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_serializer: A callable that when called on a request |
|
||||||
value returns a bytestring corresponding to that value. |
|
||||||
response_deserializer: A callable that when called on a |
|
||||||
bytestring returns the response value corresponding to |
|
||||||
that bytestring. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodInvocationDescription constructed from the given |
|
||||||
arguments representing a unary-request/unary-response RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.UNARY_UNARY, None, None, None, None, |
|
||||||
request_serializer, None, None, response_deserializer) |
|
||||||
|
|
||||||
|
|
||||||
def unary_stream_invocation_description( |
|
||||||
request_serializer, response_deserializer): |
|
||||||
"""Creates an interfaces.RpcMethodInvocationDescription for an RPC method. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_serializer: A callable that when called on a request |
|
||||||
value returns a bytestring corresponding to that value. |
|
||||||
response_deserializer: A callable that when called on a |
|
||||||
bytestring returns the response value corresponding to |
|
||||||
that bytestring. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodInvocationDescription constructed from the given |
|
||||||
arguments representing a unary-request/streaming-response RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.UNARY_STREAM, None, None, None, None, |
|
||||||
request_serializer, None, None, response_deserializer) |
|
||||||
|
|
||||||
|
|
||||||
def stream_unary_invocation_description( |
|
||||||
request_serializer, response_deserializer): |
|
||||||
"""Creates an interfaces.RpcMethodInvocationDescription for an RPC method. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_serializer: A callable that when called on a request |
|
||||||
value returns a bytestring corresponding to that value. |
|
||||||
response_deserializer: A callable that when called on a |
|
||||||
bytestring returns the response value corresponding to |
|
||||||
that bytestring. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodInvocationDescription constructed from the given |
|
||||||
arguments representing a streaming-request/unary-response RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.STREAM_UNARY, None, None, None, None, |
|
||||||
request_serializer, None, None, response_deserializer) |
|
||||||
|
|
||||||
|
|
||||||
def stream_stream_invocation_description( |
|
||||||
request_serializer, response_deserializer): |
|
||||||
"""Creates an interfaces.RpcMethodInvocationDescription for an RPC method. |
|
||||||
|
|
||||||
Args: |
|
||||||
request_serializer: A callable that when called on a request |
|
||||||
value returns a bytestring corresponding to that value. |
|
||||||
response_deserializer: A callable that when called on a |
|
||||||
bytestring returns the response value corresponding to |
|
||||||
that bytestring. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodInvocationDescription constructed from the given |
|
||||||
arguments representing a streaming-request/streaming-response RPC |
|
||||||
method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.STREAM_STREAM, None, None, None, None, |
|
||||||
request_serializer, None, None, response_deserializer) |
|
||||||
|
|
||||||
|
|
||||||
def unary_unary_service_description( |
|
||||||
behavior, request_deserializer, response_serializer): |
|
||||||
"""Creates an interfaces.RpcMethodServiceDescription for the given behavior. |
|
||||||
|
|
||||||
Args: |
|
||||||
behavior: A callable that implements a unary-unary RPC |
|
||||||
method that accepts a single request and an interfaces.RpcContext and |
|
||||||
returns a single response. |
|
||||||
request_deserializer: A callable that when called on a |
|
||||||
bytestring returns the request value corresponding to that |
|
||||||
bytestring. |
|
||||||
response_serializer: A callable that when called on a |
|
||||||
response value returns the bytestring corresponding to |
|
||||||
that value. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodServiceDescription constructed from the given |
|
||||||
arguments representing a unary-request/unary-response RPC |
|
||||||
method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.UNARY_UNARY, behavior, None, None, None, |
|
||||||
None, request_deserializer, response_serializer, None) |
|
||||||
|
|
||||||
|
|
||||||
def unary_stream_service_description( |
|
||||||
behavior, request_deserializer, response_serializer): |
|
||||||
"""Creates an interfaces.RpcMethodServiceDescription for the given behavior. |
|
||||||
|
|
||||||
Args: |
|
||||||
behavior: A callable that implements a unary-stream RPC |
|
||||||
method that accepts a single request and an interfaces.RpcContext |
|
||||||
and returns an iterator of zero or more responses. |
|
||||||
request_deserializer: A callable that when called on a |
|
||||||
bytestring returns the request value corresponding to that |
|
||||||
bytestring. |
|
||||||
response_serializer: A callable that when called on a |
|
||||||
response value returns the bytestring corresponding to |
|
||||||
that value. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodServiceDescription constructed from the given |
|
||||||
arguments representing a unary-request/streaming-response |
|
||||||
RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.UNARY_STREAM, None, behavior, None, None, |
|
||||||
None, request_deserializer, response_serializer, None) |
|
||||||
|
|
||||||
|
|
||||||
def stream_unary_service_description( |
|
||||||
behavior, request_deserializer, response_serializer): |
|
||||||
"""Creates an interfaces.RpcMethodServiceDescription for the given behavior. |
|
||||||
|
|
||||||
Args: |
|
||||||
behavior: A callable that implements a stream-unary RPC |
|
||||||
method that accepts an iterator of zero or more requests |
|
||||||
and an interfaces.RpcContext and returns a single response. |
|
||||||
request_deserializer: A callable that when called on a |
|
||||||
bytestring returns the request value corresponding to that |
|
||||||
bytestring. |
|
||||||
response_serializer: A callable that when called on a |
|
||||||
response value returns the bytestring corresponding to |
|
||||||
that value. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodServiceDescription constructed from the given |
|
||||||
arguments representing a streaming-request/unary-response |
|
||||||
RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.STREAM_UNARY, None, None, behavior, None, |
|
||||||
None, request_deserializer, response_serializer, None) |
|
||||||
|
|
||||||
|
|
||||||
def stream_stream_service_description( |
|
||||||
behavior, request_deserializer, response_serializer): |
|
||||||
"""Creates an interfaces.RpcMethodServiceDescription for the given behavior. |
|
||||||
|
|
||||||
Args: |
|
||||||
behavior: A callable that implements a stream-stream RPC |
|
||||||
method that accepts an iterator of zero or more requests |
|
||||||
and an interfaces.RpcContext and returns an iterator of |
|
||||||
zero or more responses. |
|
||||||
request_deserializer: A callable that when called on a |
|
||||||
bytestring returns the request value corresponding to that |
|
||||||
bytestring. |
|
||||||
response_serializer: A callable that when called on a |
|
||||||
response value returns the bytestring corresponding to |
|
||||||
that value. |
|
||||||
|
|
||||||
Returns: |
|
||||||
An interfaces.RpcMethodServiceDescription constructed from the given |
|
||||||
arguments representing a |
|
||||||
streaming-request/streaming-response RPC method. |
|
||||||
""" |
|
||||||
return _RpcMethodDescription( |
|
||||||
interfaces.Cardinality.STREAM_STREAM, None, None, None, behavior, |
|
||||||
None, request_deserializer, response_serializer, None) |
|
@ -1,35 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
import warnings |
|
||||||
|
|
||||||
warnings.simplefilter('always', DeprecationWarning) |
|
||||||
warnings.warn('the alpha API (includes this package) is deprecated, ' |
|
||||||
'unmaintained, and no longer tested. Please migrate to the beta ' |
|
||||||
'API.', DeprecationWarning, stacklevel=2) |
|
@ -1,99 +0,0 @@ |
|||||||
# 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. |
|
||||||
|
|
||||||
"""State and behavior for operation context.""" |
|
||||||
|
|
||||||
import time |
|
||||||
|
|
||||||
# _interfaces is referenced from specification in this module. |
|
||||||
from grpc.framework.base import interfaces |
|
||||||
from grpc.framework.base import _interfaces # pylint: disable=unused-import |
|
||||||
|
|
||||||
|
|
||||||
class OperationContext(interfaces.OperationContext): |
|
||||||
"""An implementation of interfaces.OperationContext.""" |
|
||||||
|
|
||||||
def __init__( |
|
||||||
self, lock, operation_id, local_failure, termination_manager, |
|
||||||
transmission_manager): |
|
||||||
"""Constructor. |
|
||||||
|
|
||||||
Args: |
|
||||||
lock: The operation-wide lock. |
|
||||||
operation_id: An object identifying the operation. |
|
||||||
local_failure: Whichever one of interfaces.Outcome.SERVICED_FAILURE or |
|
||||||
interfaces.Outcome.SERVICER_FAILURE describes local failure of |
|
||||||
customer code. |
|
||||||
termination_manager: The _interfaces.TerminationManager for the operation. |
|
||||||
transmission_manager: The _interfaces.TransmissionManager for the |
|
||||||
operation. |
|
||||||
""" |
|
||||||
self._lock = lock |
|
||||||
self._local_failure = local_failure |
|
||||||
self._termination_manager = termination_manager |
|
||||||
self._transmission_manager = transmission_manager |
|
||||||
self._ingestion_manager = None |
|
||||||
self._expiration_manager = None |
|
||||||
|
|
||||||
self.operation_id = operation_id |
|
||||||
|
|
||||||
def set_ingestion_and_expiration_managers( |
|
||||||
self, ingestion_manager, expiration_manager): |
|
||||||
"""Sets managers with which this OperationContext cooperates. |
|
||||||
|
|
||||||
Args: |
|
||||||
ingestion_manager: The _interfaces.IngestionManager for the operation. |
|
||||||
expiration_manager: The _interfaces.ExpirationManager for the operation. |
|
||||||
""" |
|
||||||
self._ingestion_manager = ingestion_manager |
|
||||||
self._expiration_manager = expiration_manager |
|
||||||
|
|
||||||
def is_active(self): |
|
||||||
"""See interfaces.OperationContext.is_active for specification.""" |
|
||||||
with self._lock: |
|
||||||
return self._termination_manager.is_active() |
|
||||||
|
|
||||||
def add_termination_callback(self, callback): |
|
||||||
"""See interfaces.OperationContext.add_termination_callback.""" |
|
||||||
with self._lock: |
|
||||||
self._termination_manager.add_callback(callback) |
|
||||||
|
|
||||||
def time_remaining(self): |
|
||||||
"""See interfaces.OperationContext.time_remaining for specification.""" |
|
||||||
with self._lock: |
|
||||||
deadline = self._expiration_manager.deadline() |
|
||||||
return max(0.0, deadline - time.time()) |
|
||||||
|
|
||||||
def fail(self, exception): |
|
||||||
"""See interfaces.OperationContext.fail for specification.""" |
|
||||||
with self._lock: |
|
||||||
self._termination_manager.abort(self._local_failure) |
|
||||||
self._transmission_manager.abort(self._local_failure) |
|
||||||
self._ingestion_manager.abort() |
|
||||||
self._expiration_manager.abort() |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue