|
|
|
@ -79,27 +79,6 @@ def _wait_once_until(condition, until): |
|
|
|
|
condition.wait(timeout=remaining) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = ( |
|
|
|
|
'Internal gRPC call error %d. ' + |
|
|
|
|
'Please report to https://github.com/grpc/grpc/issues') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _check_call_error(call_error, metadata): |
|
|
|
|
if call_error == cygrpc.CallError.invalid_metadata: |
|
|
|
|
raise ValueError('metadata was invalid: %s' % metadata) |
|
|
|
|
elif call_error != cygrpc.CallError.ok: |
|
|
|
|
raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _call_error_set_RPCstate(state, call_error, metadata): |
|
|
|
|
if call_error == cygrpc.CallError.invalid_metadata: |
|
|
|
|
_abort(state, grpc.StatusCode.INTERNAL, |
|
|
|
|
'metadata was invalid: %s' % metadata) |
|
|
|
|
else: |
|
|
|
|
_abort(state, grpc.StatusCode.INTERNAL, |
|
|
|
|
_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _RPCState(object): |
|
|
|
|
|
|
|
|
|
def __init__(self, due, initial_metadata, trailing_metadata, code, details): |
|
|
|
@ -163,7 +142,7 @@ def _handle_event(event, state, response_deserializer): |
|
|
|
|
return callbacks |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _event_handler(state, call, response_deserializer): |
|
|
|
|
def _event_handler(state, response_deserializer): |
|
|
|
|
|
|
|
|
|
def handle_event(event): |
|
|
|
|
with state.condition: |
|
|
|
@ -172,40 +151,47 @@ def _event_handler(state, call, response_deserializer): |
|
|
|
|
done = not state.due |
|
|
|
|
for callback in callbacks: |
|
|
|
|
callback() |
|
|
|
|
return call if done else None |
|
|
|
|
return done |
|
|
|
|
|
|
|
|
|
return handle_event |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _consume_request_iterator(request_iterator, state, call, |
|
|
|
|
request_serializer): |
|
|
|
|
event_handler = _event_handler(state, call, None) |
|
|
|
|
def _consume_request_iterator(request_iterator, state, call, request_serializer, |
|
|
|
|
event_handler): |
|
|
|
|
|
|
|
|
|
def consume_request_iterator(): |
|
|
|
|
def consume_request_iterator(): # pylint: disable=too-many-branches |
|
|
|
|
while True: |
|
|
|
|
try: |
|
|
|
|
request = next(request_iterator) |
|
|
|
|
except StopIteration: |
|
|
|
|
break |
|
|
|
|
except Exception: # pylint: disable=broad-except |
|
|
|
|
logging.exception("Exception iterating requests!") |
|
|
|
|
call.cancel() |
|
|
|
|
_abort(state, grpc.StatusCode.UNKNOWN, |
|
|
|
|
"Exception iterating requests!") |
|
|
|
|
code = grpc.StatusCode.UNKNOWN |
|
|
|
|
details = 'Exception iterating requests!' |
|
|
|
|
logging.exception(details) |
|
|
|
|
call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], |
|
|
|
|
details) |
|
|
|
|
_abort(state, code, details) |
|
|
|
|
return |
|
|
|
|
serialized_request = _common.serialize(request, request_serializer) |
|
|
|
|
with state.condition: |
|
|
|
|
if state.code is None and not state.cancelled: |
|
|
|
|
if serialized_request is None: |
|
|
|
|
call.cancel() |
|
|
|
|
code = grpc.StatusCode.INTERNAL # pylint: disable=redefined-variable-type |
|
|
|
|
details = 'Exception serializing request!' |
|
|
|
|
_abort(state, grpc.StatusCode.INTERNAL, details) |
|
|
|
|
call.cancel( |
|
|
|
|
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], |
|
|
|
|
details) |
|
|
|
|
_abort(state, code, details) |
|
|
|
|
return |
|
|
|
|
else: |
|
|
|
|
operations = (cygrpc.SendMessageOperation( |
|
|
|
|
serialized_request, _EMPTY_FLAGS),) |
|
|
|
|
call.start_client_batch(operations, event_handler) |
|
|
|
|
state.due.add(cygrpc.OperationType.send_message) |
|
|
|
|
operating = call.operate(operations, event_handler) |
|
|
|
|
if operating: |
|
|
|
|
state.due.add(cygrpc.OperationType.send_message) |
|
|
|
|
else: |
|
|
|
|
return |
|
|
|
|
while True: |
|
|
|
|
state.condition.wait() |
|
|
|
|
if state.code is None: |
|
|
|
@ -219,15 +205,19 @@ def _consume_request_iterator(request_iterator, state, call, |
|
|
|
|
if state.code is None: |
|
|
|
|
operations = ( |
|
|
|
|
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),) |
|
|
|
|
call.start_client_batch(operations, event_handler) |
|
|
|
|
state.due.add(cygrpc.OperationType.send_close_from_client) |
|
|
|
|
operating = call.operate(operations, event_handler) |
|
|
|
|
if operating: |
|
|
|
|
state.due.add(cygrpc.OperationType.send_close_from_client) |
|
|
|
|
|
|
|
|
|
def stop_consumption_thread(timeout): # pylint: disable=unused-argument |
|
|
|
|
with state.condition: |
|
|
|
|
if state.code is None: |
|
|
|
|
call.cancel() |
|
|
|
|
code = grpc.StatusCode.CANCELLED |
|
|
|
|
details = 'Consumption thread cleaned up!' |
|
|
|
|
call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], |
|
|
|
|
details) |
|
|
|
|
state.cancelled = True |
|
|
|
|
_abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!') |
|
|
|
|
_abort(state, code, details) |
|
|
|
|
state.condition.notify_all() |
|
|
|
|
|
|
|
|
|
consumption_thread = _common.CleanupThread( |
|
|
|
@ -247,9 +237,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): |
|
|
|
|
def cancel(self): |
|
|
|
|
with self._state.condition: |
|
|
|
|
if self._state.code is None: |
|
|
|
|
self._call.cancel() |
|
|
|
|
code = grpc.StatusCode.CANCELLED |
|
|
|
|
details = 'Locally cancelled by application!' |
|
|
|
|
self._call.cancel( |
|
|
|
|
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details) |
|
|
|
|
self._state.cancelled = True |
|
|
|
|
_abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!') |
|
|
|
|
_abort(self._state, code, details) |
|
|
|
|
self._state.condition.notify_all() |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
@ -318,12 +311,13 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): |
|
|
|
|
def _next(self): |
|
|
|
|
with self._state.condition: |
|
|
|
|
if self._state.code is None: |
|
|
|
|
event_handler = _event_handler(self._state, self._call, |
|
|
|
|
event_handler = _event_handler(self._state, |
|
|
|
|
self._response_deserializer) |
|
|
|
|
self._call.start_client_batch( |
|
|
|
|
operating = self._call.operate( |
|
|
|
|
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),), |
|
|
|
|
event_handler) |
|
|
|
|
self._state.due.add(cygrpc.OperationType.receive_message) |
|
|
|
|
if operating: |
|
|
|
|
self._state.due.add(cygrpc.OperationType.receive_message) |
|
|
|
|
elif self._state.code is grpc.StatusCode.OK: |
|
|
|
|
raise StopIteration() |
|
|
|
|
else: |
|
|
|
@ -408,9 +402,12 @@ class _Rendezvous(grpc.RpcError, grpc.Future, grpc.Call): |
|
|
|
|
def __del__(self): |
|
|
|
|
with self._state.condition: |
|
|
|
|
if self._state.code is None: |
|
|
|
|
self._call.cancel() |
|
|
|
|
self._state.cancelled = True |
|
|
|
|
self._state.code = grpc.StatusCode.CANCELLED |
|
|
|
|
self._state.details = 'Cancelled upon garbage collection!' |
|
|
|
|
self._state.cancelled = True |
|
|
|
|
self._call.cancel( |
|
|
|
|
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[self._state.code], |
|
|
|
|
self._state.details) |
|
|
|
|
self._state.condition.notify_all() |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -437,6 +434,24 @@ def _end_unary_response_blocking(state, call, with_call, deadline): |
|
|
|
|
raise _Rendezvous(state, None, None, deadline) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _stream_unary_invocation_operationses(metadata): |
|
|
|
|
return ( |
|
|
|
|
( |
|
|
|
|
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), |
|
|
|
|
), |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _stream_unary_invocation_operationses_and_tags(metadata): |
|
|
|
|
return tuple(( |
|
|
|
|
operations, |
|
|
|
|
None, |
|
|
|
|
) for operations in _stream_unary_invocation_operationses(metadata)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): |
|
|
|
|
|
|
|
|
|
def __init__(self, channel, managed_call, method, request_serializer, |
|
|
|
@ -448,8 +463,8 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): |
|
|
|
|
self._response_deserializer = response_deserializer |
|
|
|
|
|
|
|
|
|
def _prepare(self, request, timeout, metadata): |
|
|
|
|
deadline, serialized_request, rendezvous = (_start_unary_request( |
|
|
|
|
request, timeout, self._request_serializer)) |
|
|
|
|
deadline, serialized_request, rendezvous = _start_unary_request( |
|
|
|
|
request, timeout, self._request_serializer) |
|
|
|
|
if serialized_request is None: |
|
|
|
|
return None, None, None, rendezvous |
|
|
|
|
else: |
|
|
|
@ -467,48 +482,38 @@ class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable): |
|
|
|
|
def _blocking(self, request, timeout, metadata, credentials): |
|
|
|
|
state, operations, deadline, rendezvous = self._prepare( |
|
|
|
|
request, timeout, metadata) |
|
|
|
|
if rendezvous: |
|
|
|
|
if state is None: |
|
|
|
|
raise rendezvous |
|
|
|
|
else: |
|
|
|
|
completion_queue = cygrpc.CompletionQueue() |
|
|
|
|
call = self._channel.create_call(None, 0, completion_queue, |
|
|
|
|
self._method, None, deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
call_error = call.start_client_batch(operations, None) |
|
|
|
|
_check_call_error(call_error, metadata) |
|
|
|
|
_handle_event(completion_queue.poll(), state, |
|
|
|
|
self._response_deserializer) |
|
|
|
|
return state, call, deadline |
|
|
|
|
call = self._channel.segregated_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, (( |
|
|
|
|
operations, |
|
|
|
|
None, |
|
|
|
|
),)) |
|
|
|
|
event = call.next_event() |
|
|
|
|
_handle_event(event, state, self._response_deserializer) |
|
|
|
|
return state, call, |
|
|
|
|
|
|
|
|
|
def __call__(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
state, call, deadline = self._blocking(request, timeout, metadata, |
|
|
|
|
credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, False, deadline) |
|
|
|
|
state, call, = self._blocking(request, timeout, metadata, credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, False, None) |
|
|
|
|
|
|
|
|
|
def with_call(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
state, call, deadline = self._blocking(request, timeout, metadata, |
|
|
|
|
credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, True, deadline) |
|
|
|
|
state, call, = self._blocking(request, timeout, metadata, credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, True, None) |
|
|
|
|
|
|
|
|
|
def future(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
state, operations, deadline, rendezvous = self._prepare( |
|
|
|
|
request, timeout, metadata) |
|
|
|
|
if rendezvous: |
|
|
|
|
return rendezvous |
|
|
|
|
if state is None: |
|
|
|
|
raise rendezvous |
|
|
|
|
else: |
|
|
|
|
call, drive_call = self._managed_call(None, 0, self._method, None, |
|
|
|
|
deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
event_handler = _event_handler(state, call, |
|
|
|
|
self._response_deserializer) |
|
|
|
|
with state.condition: |
|
|
|
|
call_error = call.start_client_batch(operations, event_handler) |
|
|
|
|
if call_error != cygrpc.CallError.ok: |
|
|
|
|
_call_error_set_RPCstate(state, call_error, metadata) |
|
|
|
|
return _Rendezvous(state, None, None, deadline) |
|
|
|
|
drive_call() |
|
|
|
|
event_handler = _event_handler(state, self._response_deserializer) |
|
|
|
|
call = self._managed_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, |
|
|
|
|
(operations,), event_handler) |
|
|
|
|
return _Rendezvous(state, call, self._response_deserializer, |
|
|
|
|
deadline) |
|
|
|
|
|
|
|
|
@ -524,34 +529,27 @@ class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable): |
|
|
|
|
self._response_deserializer = response_deserializer |
|
|
|
|
|
|
|
|
|
def __call__(self, request, timeout=None, metadata=None, credentials=None): |
|
|
|
|
deadline, serialized_request, rendezvous = (_start_unary_request( |
|
|
|
|
request, timeout, self._request_serializer)) |
|
|
|
|
deadline, serialized_request, rendezvous = _start_unary_request( |
|
|
|
|
request, timeout, self._request_serializer) |
|
|
|
|
if serialized_request is None: |
|
|
|
|
raise rendezvous |
|
|
|
|
else: |
|
|
|
|
state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None) |
|
|
|
|
call, drive_call = self._managed_call(None, 0, self._method, None, |
|
|
|
|
deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
event_handler = _event_handler(state, call, |
|
|
|
|
self._response_deserializer) |
|
|
|
|
with state.condition: |
|
|
|
|
call.start_client_batch( |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
event_handler) |
|
|
|
|
operations = ( |
|
|
|
|
operationses = ( |
|
|
|
|
( |
|
|
|
|
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS), |
|
|
|
|
cygrpc.SendMessageOperation(serialized_request, |
|
|
|
|
_EMPTY_FLAGS), |
|
|
|
|
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), |
|
|
|
|
) |
|
|
|
|
call_error = call.start_client_batch(operations, event_handler) |
|
|
|
|
if call_error != cygrpc.CallError.ok: |
|
|
|
|
_call_error_set_RPCstate(state, call_error, metadata) |
|
|
|
|
return _Rendezvous(state, None, None, deadline) |
|
|
|
|
drive_call() |
|
|
|
|
), |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
) |
|
|
|
|
event_handler = _event_handler(state, self._response_deserializer) |
|
|
|
|
call = self._managed_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, |
|
|
|
|
operationses, event_handler) |
|
|
|
|
return _Rendezvous(state, call, self._response_deserializer, |
|
|
|
|
deadline) |
|
|
|
|
|
|
|
|
@ -569,49 +567,38 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): |
|
|
|
|
def _blocking(self, request_iterator, timeout, metadata, credentials): |
|
|
|
|
deadline = _deadline(timeout) |
|
|
|
|
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) |
|
|
|
|
completion_queue = cygrpc.CompletionQueue() |
|
|
|
|
call = self._channel.create_call(None, 0, completion_queue, |
|
|
|
|
self._method, None, deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
with state.condition: |
|
|
|
|
call.start_client_batch( |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), None) |
|
|
|
|
operations = ( |
|
|
|
|
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), |
|
|
|
|
) |
|
|
|
|
call_error = call.start_client_batch(operations, None) |
|
|
|
|
_check_call_error(call_error, metadata) |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer) |
|
|
|
|
call = self._channel.segregated_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, |
|
|
|
|
_stream_unary_invocation_operationses_and_tags(metadata)) |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer, None) |
|
|
|
|
while True: |
|
|
|
|
event = completion_queue.poll() |
|
|
|
|
event = call.next_event() |
|
|
|
|
with state.condition: |
|
|
|
|
_handle_event(event, state, self._response_deserializer) |
|
|
|
|
state.condition.notify_all() |
|
|
|
|
if not state.due: |
|
|
|
|
break |
|
|
|
|
return state, call, deadline |
|
|
|
|
return state, call, |
|
|
|
|
|
|
|
|
|
def __call__(self, |
|
|
|
|
request_iterator, |
|
|
|
|
timeout=None, |
|
|
|
|
metadata=None, |
|
|
|
|
credentials=None): |
|
|
|
|
state, call, deadline = self._blocking(request_iterator, timeout, |
|
|
|
|
metadata, credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, False, deadline) |
|
|
|
|
state, call, = self._blocking(request_iterator, timeout, metadata, |
|
|
|
|
credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, False, None) |
|
|
|
|
|
|
|
|
|
def with_call(self, |
|
|
|
|
request_iterator, |
|
|
|
|
timeout=None, |
|
|
|
|
metadata=None, |
|
|
|
|
credentials=None): |
|
|
|
|
state, call, deadline = self._blocking(request_iterator, timeout, |
|
|
|
|
metadata, credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, True, deadline) |
|
|
|
|
state, call, = self._blocking(request_iterator, timeout, metadata, |
|
|
|
|
credentials) |
|
|
|
|
return _end_unary_response_blocking(state, call, True, None) |
|
|
|
|
|
|
|
|
|
def future(self, |
|
|
|
|
request_iterator, |
|
|
|
@ -620,27 +607,13 @@ class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable): |
|
|
|
|
credentials=None): |
|
|
|
|
deadline = _deadline(timeout) |
|
|
|
|
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None) |
|
|
|
|
call, drive_call = self._managed_call(None, 0, self._method, None, |
|
|
|
|
deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
event_handler = _event_handler(state, call, self._response_deserializer) |
|
|
|
|
with state.condition: |
|
|
|
|
call.start_client_batch( |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
event_handler) |
|
|
|
|
operations = ( |
|
|
|
|
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), |
|
|
|
|
) |
|
|
|
|
call_error = call.start_client_batch(operations, event_handler) |
|
|
|
|
if call_error != cygrpc.CallError.ok: |
|
|
|
|
_call_error_set_RPCstate(state, call_error, metadata) |
|
|
|
|
return _Rendezvous(state, None, None, deadline) |
|
|
|
|
drive_call() |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer) |
|
|
|
|
event_handler = _event_handler(state, self._response_deserializer) |
|
|
|
|
call = self._managed_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, |
|
|
|
|
_stream_unary_invocation_operationses(metadata), event_handler) |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer, event_handler) |
|
|
|
|
return _Rendezvous(state, call, self._response_deserializer, deadline) |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -661,26 +634,20 @@ class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable): |
|
|
|
|
credentials=None): |
|
|
|
|
deadline = _deadline(timeout) |
|
|
|
|
state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None) |
|
|
|
|
call, drive_call = self._managed_call(None, 0, self._method, None, |
|
|
|
|
deadline) |
|
|
|
|
if credentials is not None: |
|
|
|
|
call.set_credentials(credentials._credentials) |
|
|
|
|
event_handler = _event_handler(state, call, self._response_deserializer) |
|
|
|
|
with state.condition: |
|
|
|
|
call.start_client_batch( |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
event_handler) |
|
|
|
|
operations = ( |
|
|
|
|
operationses = ( |
|
|
|
|
( |
|
|
|
|
cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS), |
|
|
|
|
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS), |
|
|
|
|
) |
|
|
|
|
call_error = call.start_client_batch(operations, event_handler) |
|
|
|
|
if call_error != cygrpc.CallError.ok: |
|
|
|
|
_call_error_set_RPCstate(state, call_error, metadata) |
|
|
|
|
return _Rendezvous(state, None, None, deadline) |
|
|
|
|
drive_call() |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer) |
|
|
|
|
), |
|
|
|
|
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), |
|
|
|
|
) |
|
|
|
|
event_handler = _event_handler(state, self._response_deserializer) |
|
|
|
|
call = self._managed_call( |
|
|
|
|
0, self._method, None, deadline, metadata, None |
|
|
|
|
if credentials is None else credentials._credentials, operationses, |
|
|
|
|
event_handler) |
|
|
|
|
_consume_request_iterator(request_iterator, state, call, |
|
|
|
|
self._request_serializer, event_handler) |
|
|
|
|
return _Rendezvous(state, call, self._response_deserializer, deadline) |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -689,28 +656,25 @@ class _ChannelCallState(object): |
|
|
|
|
def __init__(self, channel): |
|
|
|
|
self.lock = threading.Lock() |
|
|
|
|
self.channel = channel |
|
|
|
|
self.completion_queue = cygrpc.CompletionQueue() |
|
|
|
|
self.managed_calls = None |
|
|
|
|
self.managed_calls = 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _run_channel_spin_thread(state): |
|
|
|
|
|
|
|
|
|
def channel_spin(): |
|
|
|
|
while True: |
|
|
|
|
event = state.completion_queue.poll() |
|
|
|
|
completed_call = event.tag(event) |
|
|
|
|
if completed_call is not None: |
|
|
|
|
event = state.channel.next_call_event() |
|
|
|
|
call_completed = event.tag(event) |
|
|
|
|
if call_completed: |
|
|
|
|
with state.lock: |
|
|
|
|
state.managed_calls.remove(completed_call) |
|
|
|
|
if not state.managed_calls: |
|
|
|
|
state.managed_calls = None |
|
|
|
|
state.managed_calls -= 1 |
|
|
|
|
if state.managed_calls == 0: |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
def stop_channel_spin(timeout): # pylint: disable=unused-argument |
|
|
|
|
with state.lock: |
|
|
|
|
if state.managed_calls is not None: |
|
|
|
|
for call in state.managed_calls: |
|
|
|
|
call.cancel() |
|
|
|
|
state.channel.close(cygrpc.StatusCode.cancelled, |
|
|
|
|
'Channel spin thread cleaned up!') |
|
|
|
|
|
|
|
|
|
channel_spin_thread = _common.CleanupThread( |
|
|
|
|
stop_channel_spin, target=channel_spin) |
|
|
|
@ -719,37 +683,41 @@ def _run_channel_spin_thread(state): |
|
|
|
|
|
|
|
|
|
def _channel_managed_call_management(state): |
|
|
|
|
|
|
|
|
|
def create(parent, flags, method, host, deadline): |
|
|
|
|
"""Creates a managed cygrpc.Call and a function to call to drive it. |
|
|
|
|
|
|
|
|
|
If operations are successfully added to the returned cygrpc.Call, the |
|
|
|
|
returned function must be called. If operations are not successfully added |
|
|
|
|
to the returned cygrpc.Call, the returned function must not be called. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
parent: A cygrpc.Call to be used as the parent of the created call. |
|
|
|
|
flags: An integer bitfield of call flags. |
|
|
|
|
method: The RPC method. |
|
|
|
|
host: A host string for the created call. |
|
|
|
|
deadline: A float to be the deadline of the created call or None if the |
|
|
|
|
call is to have an infinite deadline. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A cygrpc.Call with which to conduct an RPC and a function to call if |
|
|
|
|
operations are successfully started on the call. |
|
|
|
|
""" |
|
|
|
|
call = state.channel.create_call(parent, flags, state.completion_queue, |
|
|
|
|
method, host, deadline) |
|
|
|
|
|
|
|
|
|
def drive(): |
|
|
|
|
with state.lock: |
|
|
|
|
if state.managed_calls is None: |
|
|
|
|
state.managed_calls = set((call,)) |
|
|
|
|
_run_channel_spin_thread(state) |
|
|
|
|
else: |
|
|
|
|
state.managed_calls.add(call) |
|
|
|
|
# pylint: disable=too-many-arguments |
|
|
|
|
def create(flags, method, host, deadline, metadata, credentials, |
|
|
|
|
operationses, event_handler): |
|
|
|
|
"""Creates a cygrpc.IntegratedCall. |
|
|
|
|
|
|
|
|
|
return call, drive |
|
|
|
|
Args: |
|
|
|
|
flags: An integer bitfield of call flags. |
|
|
|
|
method: The RPC method. |
|
|
|
|
host: A host string for the created call. |
|
|
|
|
deadline: A float to be the deadline of the created call or None if |
|
|
|
|
the call is to have an infinite deadline. |
|
|
|
|
metadata: The metadata for the call or None. |
|
|
|
|
credentials: A cygrpc.CallCredentials or None. |
|
|
|
|
operationses: An iterable of iterables of cygrpc.Operations to be |
|
|
|
|
started on the call. |
|
|
|
|
event_handler: A behavior to call to handle the events resultant from |
|
|
|
|
the operations on the call. |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
A cygrpc.IntegratedCall with which to conduct an RPC. |
|
|
|
|
""" |
|
|
|
|
operationses_and_tags = tuple(( |
|
|
|
|
operations, |
|
|
|
|
event_handler, |
|
|
|
|
) for operations in operationses) |
|
|
|
|
with state.lock: |
|
|
|
|
call = state.channel.integrated_call(flags, method, host, deadline, |
|
|
|
|
metadata, credentials, |
|
|
|
|
operationses_and_tags) |
|
|
|
|
if state.managed_calls == 0: |
|
|
|
|
state.managed_calls = 1 |
|
|
|
|
_run_channel_spin_thread(state) |
|
|
|
|
else: |
|
|
|
|
state.managed_calls += 1 |
|
|
|
|
return call |
|
|
|
|
|
|
|
|
|
return create |
|
|
|
|
|
|
|
|
@ -819,12 +787,9 @@ def _poll_connectivity(state, channel, initial_try_to_connect): |
|
|
|
|
callback_and_connectivity[1] = state.connectivity |
|
|
|
|
if callbacks: |
|
|
|
|
_spawn_delivery(state, callbacks) |
|
|
|
|
completion_queue = cygrpc.CompletionQueue() |
|
|
|
|
while True: |
|
|
|
|
channel.watch_connectivity_state(connectivity, |
|
|
|
|
time.time() + 0.2, completion_queue, |
|
|
|
|
None) |
|
|
|
|
event = completion_queue.poll() |
|
|
|
|
event = channel.watch_connectivity_state(connectivity, |
|
|
|
|
time.time() + 0.2) |
|
|
|
|
with state.lock: |
|
|
|
|
if not state.callbacks_and_connectivities and not state.try_to_connect: |
|
|
|
|
state.polling = False |
|
|
|
|