def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) rpc_state = _handle_call(event, state.generic_handlers, state.thread_pool) if rpc_state is not None: state.rpc_states.add(rpc_state) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return
def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) rpc_state = _handle_call( event, state.generic_handlers, state.thread_pool) if rpc_state is not None: state.rpc_states.add(rpc_state) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return
def add_done_callback(self, fn): """See future.Future.add_done_callback for specification.""" with self._condition: if self._callbacks is not None: self._callbacks.add(fn) return callable_util.call_logging_exceptions(fn, _DONE_CALLBACK_LOG_MESSAGE, self)
def add_done_callback(self, fn): """See future.Future.add_done_callback for specification.""" with self._condition: if self._callbacks is not None: self._callbacks.append(fn) return callable_util.call_logging_exceptions(fn, _DONE_CALLBACK_LOG_MESSAGE, self)
def _update(self, connectivity): with self._condition: if not self._cancelled and connectivity is beta.ChannelConnectivity.READY: self._matured = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
def _update(self, connectivity): with self._condition: if not self._cancelled and connectivity is beta.ChannelConnectivity.READY: self._matured = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
def cancel(self): with self._condition: if not self._matured: self._cancelled = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return False for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
def cancel(self): with self._condition: if not self._matured: self._cancelled = True self._channel.unsubscribe(self._update) self._condition.notify_all() done_callbacks = tuple(self._done_callbacks) self._done_callbacks = None else: return False for done_callback in done_callbacks: callable_util.call_logging_exceptions( done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self)
def _deliver(state, initial_connectivity, initial_callbacks): connectivity = initial_connectivity callbacks = initial_callbacks while True: for callback in callbacks: callable_util.call_logging_exceptions( callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, connectivity) with state.lock: callbacks = _deliveries(state) if callbacks: connectivity = state.connectivity else: state.delivering = False return
def _deliver(state, initial_connectivity, initial_callbacks): connectivity = initial_connectivity callbacks = initial_callbacks while True: for callback in callbacks: callable_util.call_logging_exceptions( callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, connectivity) with state.lock: callbacks = _deliveries(state) if callbacks: connectivity = state.connectivity else: state.delivering = False return
def initialize(): consumer_creation_outcome = callable_util.call_logging_exceptions( self._consumer_creator.create_consumer, _CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE, requirement) if consumer_creation_outcome.return_value is None: with self._lock: self._abort_and_notify(self._failure_outcome) self._processing = False elif consumer_creation_outcome.return_value.remote_error: with self._lock: self._abort_and_notify(interfaces.Outcome.RECEPTION_FAILURE) self._processing = False elif consumer_creation_outcome.return_value.abandoned: with self._lock: if self._pending_ingestion is not None: self._abort_and_notify(self._failure_outcome) self._processing = False else: wrapped_ingestion_consumer = _WrappedConsumer( consumer_creation_outcome.return_value.consumer) with self._lock: self._wrapped_ingestion_consumer = wrapped_ingestion_consumer payload, complete, moar = self._next() if not moar: self._processing = False return self._process(wrapped_ingestion_consumer, payload, complete)
def _operator_process( self, wrapped_operator, initial_metadata, payload, completion, allowance): while True: advance_outcome = callable_util.call_logging_exceptions( wrapped_operator, _INGESTION_EXCEPTION_LOG_MESSAGE, initial_metadata=initial_metadata, payload=payload, completion=completion, allowance=allowance) if advance_outcome.exception is None: if advance_outcome.return_value: with self._lock: if self._termination_manager.outcome is not None: return if completion is not None: self._termination_manager.ingestion_complete() initial_metadata, payload, completion, allowance, moar = ( self._operator_next()) if not moar: self._processing = False return else: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) return else: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) return
def initialize(): consumer_creation_outcome = callable_util.call_logging_exceptions( self._consumer_creator.create_consumer, _CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE, requirement) if consumer_creation_outcome.return_value is None: with self._lock: self._abort_and_notify(self._failure_outcome) self._processing = False elif consumer_creation_outcome.return_value.remote_error: with self._lock: self._abort_and_notify( interfaces.Outcome.RECEPTION_FAILURE) self._processing = False elif consumer_creation_outcome.return_value.abandoned: with self._lock: if self._pending_ingestion is not None: self._abort_and_notify(self._failure_outcome) self._processing = False else: wrapped_ingestion_consumer = _WrappedConsumer( consumer_creation_outcome.return_value.consumer) with self._lock: self._wrapped_ingestion_consumer = wrapped_ingestion_consumer payload, complete, moar = self._next() if not moar: self._processing = False return self._process(wrapped_ingestion_consumer, payload, complete)
def _create(self, subscription_creator, group, name): outcome = callable_util.call_logging_exceptions( subscription_creator.create, _CREATE_SUBSCRIPTION_EXCEPTION_LOG_MESSAGE, group, name) if outcome.return_value is None: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.ABANDONED: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.REMOTE_ERROR: code = outcome.return_value.code details = outcome.return_value.details with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify( base.Outcome.Kind.REMOTE_FAILURE, code, details) elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: self._protocol_manager.set_protocol_receiver( outcome.return_value.subscription.protocol_receiver) self._operator_post_create(outcome.return_value.subscription) else: # TODO(nathaniel): Support other subscriptions. raise ValueError( 'Unsupported "%s"!' % outcome.return_value.subscription.kind)
def _operator_process(self, wrapped_operator, initial_metadata, payload, completion, allowance): while True: advance_outcome = callable_util.call_logging_exceptions( wrapped_operator, _INGESTION_EXCEPTION_LOG_MESSAGE, initial_metadata=initial_metadata, payload=payload, completion=completion, allowance=allowance) if advance_outcome.exception is None: if advance_outcome.return_value: with self._lock: if self._termination_manager.outcome is not None: return if completion is not None: self._termination_manager.ingestion_complete() initial_metadata, payload, completion, allowance, moar = ( self._operator_next()) if not moar: self._processing = False return else: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) return else: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) return
def _create(self, subscription_creator, group, name): outcome = callable_util.call_logging_exceptions( subscription_creator.create, _CREATE_SUBSCRIPTION_EXCEPTION_LOG_MESSAGE, group, name) if outcome.return_value is None: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.ABANDONED: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.REMOTE_ERROR: code = outcome.return_value.code message = outcome.return_value.message with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.REMOTE_FAILURE, code, message) elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: self._operator_post_create(outcome.return_value.subscription) else: # TODO(nathaniel): Support other subscriptions. raise ValueError('Unsupported "%s"!' % outcome.return_value.subscription.kind)
def call_callbacks_and_act(callbacks, outcome): for callback in callbacks: callback_outcome = callable_util.call_logging_exceptions( callback, _CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) if callback_outcome.exception is not None: outcome = _KINDS_TO_OUTCOMES[self._local_failure] break self._utility_pool.submit(act, outcome)
def call_callbacks_and_act(callbacks, outcome): for callback in callbacks: callback_outcome = callable_util.call_logging_exceptions( callback, _CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) if callback_outcome.exception is not None: outcome = self._local_failure break self._utility_pool.submit(act, outcome)
def on_operation_termination(self, operation_outcome): """Indicates to this object that the operation has terminated. Args: operation_outcome: A base_interfaces.Outcome value indicating the outcome of the operation. """ with self._condition: cancelled = self._cancelled if cancelled: callbacks = list(self._callbacks) self._callbacks = None else: rendezvous = self._rendezvous if not cancelled: payload = None exception = None traceback = None if operation_outcome == base_interfaces.Outcome.COMPLETED: try: payload = next(rendezvous) except Exception as e: # pylint: disable=broad-except exception = e traceback = sys.exc_info()[2] else: try: # We raise and then immediately catch in order to create a traceback. raise _control.abortion_outcome_to_exception( operation_outcome) except Exception as e: # pylint: disable=broad-except exception = e traceback = sys.exc_info()[2] with self._condition: if not self._cancelled: self._computed = True self._payload = payload self._exception = exception self._traceback = traceback callbacks = list(self._callbacks) self._callbacks = None for callback in callbacks: callable_util.call_logging_exceptions(callback, _DONE_CALLBACK_LOG_MESSAGE, self)
def call_callbacks_and_act(callbacks, outcome): for callback in callbacks: callback_outcome = callable_util.call_logging_exceptions( callback, _constants.TERMINATION_CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) if callback_outcome.exception is not None: outcome = base.Outcome.LOCAL_FAILURE break act(outcome)
def on_operation_termination(self, operation_outcome): """Indicates to this object that the operation has terminated. Args: operation_outcome: A base_interfaces.Outcome value indicating the outcome of the operation. """ with self._condition: cancelled = self._cancelled if cancelled: callbacks = list(self._callbacks) self._callbacks = None else: rendezvous = self._rendezvous if not cancelled: payload = None exception = None traceback = None if operation_outcome == base_interfaces.Outcome.COMPLETED: try: payload = next(rendezvous) except Exception as e: # pylint: disable=broad-except exception = e traceback = sys.exc_info()[2] else: try: # We raise and then immediately catch in order to create a traceback. raise _control.abortion_outcome_to_exception(operation_outcome) except Exception as e: # pylint: disable=broad-except exception = e traceback = sys.exc_info()[2] with self._condition: if not self._cancelled: self._computed = True self._payload = payload self._exception = exception self._traceback = traceback callbacks = list(self._callbacks) self._callbacks = None for callback in callbacks: callable_util.call_logging_exceptions( callback, _DONE_CALLBACK_LOG_MESSAGE, self)
def call_callbacks_and_act(callbacks, outcome): for callback in callbacks: callback_outcome = callable_util.call_logging_exceptions( callback, _constants.TERMINATION_CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) if callback_outcome.exception is not None: outcome = base.Outcome.LOCAL_FAILURE break act(outcome)
def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) concurrency_exceeded = ( state.maximum_concurrent_rpcs is not None and state.active_rpc_count >= state.maximum_concurrent_rpcs) rpc_state, rpc_future = _handle_call(event, state.generic_handlers, state.thread_pool, concurrency_exceeded) if rpc_state is not None: state.rpc_states.add(rpc_state) if rpc_future is not None: state.active_rpc_count += 1 rpc_future.add_done_callback( lambda unused_future: _on_call_completed(state)) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return # We want to force the deletion of the previous event # ~before~ we poll again; if the event has a reference # to a shutdown Call object, this can induce spinlock. event = None
def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) concurrency_exceeded = ( state.maximum_concurrent_rpcs is not None and state.active_rpc_count >= state.maximum_concurrent_rpcs) rpc_state, rpc_future = _handle_call( event, state.generic_handlers, state.thread_pool, concurrency_exceeded) if rpc_state is not None: state.rpc_states.add(rpc_state) if rpc_future is not None: state.active_rpc_count += 1 rpc_future.add_done_callback( lambda unused_future: _on_call_completed(state)) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return # We want to force the deletion of the previous event # ~before~ we poll again; if the event has a reference # to a shutdown Call object, this can induce spinlock. event = None
def _process_event_and_continue(state, event): should_continue = True if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): should_continue = False elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) concurrency_exceeded = ( state.maximum_concurrent_rpcs is not None and state.active_rpc_count >= state.maximum_concurrent_rpcs) rpc_state, rpc_future = _handle_call(event, state.generic_handlers, state.interceptor_pipeline, state.thread_pool, concurrency_exceeded) if rpc_state is not None: state.rpc_states.add(rpc_state) if rpc_future is not None: state.active_rpc_count += 1 rpc_future.add_done_callback( lambda unused_future: _on_call_completed(state)) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): should_continue = False else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): should_continue = False return should_continue
def _serve(state): while True: event = state.completion_queue.poll() if event.tag is _SHUTDOWN_TAG: with state.lock: state.due.remove(_SHUTDOWN_TAG) if _stop_serving(state): return elif event.tag is _REQUEST_CALL_TAG: with state.lock: state.due.remove(_REQUEST_CALL_TAG) concurrency_exceeded = ( state.maximum_concurrent_rpcs is not None and state.active_rpc_count >= state.maximum_concurrent_rpcs) rpc_state, rpc_future = _handle_call( event, state.generic_handlers, state.thread_pool, concurrency_exceeded) if rpc_state is not None: state.rpc_states.add(rpc_state) if rpc_future is not None: state.active_rpc_count += 1 rpc_future.add_done_callback( lambda unused_future: _on_call_completed(state)) if state.stage is _ServerStage.STARTED: _request_call(state) elif _stop_serving(state): return else: rpc_state, callbacks = event.tag(event) for callback in callbacks: callable_util.call_logging_exceptions( callback, 'Exception calling callback!') if rpc_state is not None: with state.lock: state.rpc_states.remove(rpc_state) if _stop_serving(state): return
def transmit(ticket): while True: transmission_outcome = callable_util.call_logging_exceptions( self._ticket_sink, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket) if transmission_outcome.exception is None: with self._lock: if ticket.termination is links.Ticket.Termination.COMPLETION: self._termination_manager.transmission_complete() ticket = self._next_ticket() if ticket is None: self._transmitting = False return else: with self._lock: if self._termination_manager.outcome is None: self._termination_manager.abort(base.Outcome.TRANSMISSION_FAILURE) self._expiration_manager.terminate() return
def transmit(ticket): while True: transmission_outcome = callable_util.call_logging_exceptions( self._ticket_sink, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket) if transmission_outcome.exception is None: with self._lock: if ticket.termination is links.Ticket.Termination.COMPLETION: self._termination_manager.transmission_complete() ticket = self._next_ticket() if ticket is None: self._transmitting = False return else: with self._lock: if self._termination_manager.outcome is None: self._termination_manager.abort( base.Outcome.TRANSMISSION_FAILURE) self._expiration_manager.terminate() return
def transmit(ticket): while True: transmission_outcome = callable_util.call_logging_exceptions( self._callback, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, ticket) if transmission_outcome.exception is None: with self._lock: complete, ticket = self._next_ticket() if ticket is None: if complete: self._termination_manager.transmission_complete() self._transmitting = False return else: with self._lock: self._emissions = None self._termination_manager.abort( interfaces.Outcome.TRANSMISSION_FAILURE) self._ingestion_manager.abort() self._expiration_manager.abort() self._transmitting = False return
def transmit(packet): while True: transmission_outcome = callable_util.call_logging_exceptions( self._callback, _TRANSMISSION_EXCEPTION_LOG_MESSAGE, packet ) if transmission_outcome.exception is None: with self._lock: complete, packet = self._next_packet() if packet is None: if complete: self._termination_manager.transmission_complete() self._transmitting = False return else: with self._lock: self._emissions = None self._termination_manager.abort(packets.Kind.TRANSMISSION_FAILURE) self._ingestion_manager.abort() self._expiration_manager.abort() self._transmitting = False return
def _process(self, wrapped_ingestion_consumer, payload, complete): """A method to call to execute customer code. This object's lock must *not* be held when calling this method. Args: wrapped_ingestion_consumer: The _WrappedConsumer with which to pass payloads to customer code. payload: A customer payload. May be None only if complete is True. complete: Whether or not the sequence of payloads to pass to the customer has concluded. """ while True: consumption_outcome = callable_util.call_logging_exceptions( wrapped_ingestion_consumer.moar, _CONSUME_EXCEPTION_LOG_MESSAGE, payload, complete) if consumption_outcome.exception is None: if consumption_outcome.return_value: with self._lock: if complete: self._pending_ingestion = None self._termination_manager.ingestion_complete() return else: payload, complete, moar = self._next() if not moar: self._processing = False return else: with self._lock: if self._pending_ingestion is not None: self._abort_and_notify(self._failure_outcome) self._processing = False return else: with self._lock: self._abort_and_notify(self._failure_outcome) self._processing = False return
def _create(self, subscription_creator, group, name): outcome = callable_util.call_logging_exceptions( subscription_creator.create, _CREATE_SUBSCRIPTION_EXCEPTION_LOG_MESSAGE, group, name) if outcome.return_value is None: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE) elif outcome.return_value.abandoned: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.LOCAL_FAILURE) elif outcome.return_value.remote_error: with self._lock: if self._termination_manager.outcome is None: self._abort_and_notify(base.Outcome.REMOTE_FAILURE) elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: self._operator_post_create(outcome.return_value.subscription) else: # TODO(nathaniel): Support other subscriptions. raise ValueError( 'Unsupported "%s"!' % outcome.return_value.subscription.kind)
def _process(self, wrapped_ingestion_consumer, payload, complete): """A method to call to execute customer code. This object's lock must *not* be held when calling this method. Args: wrapped_ingestion_consumer: The _WrappedConsumer with which to pass payloads to customer code. payload: A customer payload. May be None only if complete is True. complete: Whether or not the sequence of payloads to pass to the customer has concluded. """ while True: consumption_outcome = callable_util.call_logging_exceptions( wrapped_ingestion_consumer.moar, _CONSUME_EXCEPTION_LOG_MESSAGE, payload, complete) if consumption_outcome.exception is None: if consumption_outcome.return_value: with self._lock: if complete: self._pending_ingestion = None self._termination_manager.ingestion_complete() return else: payload, complete, moar = self._next() if not moar: self._processing = False return else: with self._lock: if self._pending_ingestion is not None: self._abort_and_notify(self._failure_outcome) self._processing = False return else: with self._lock: self._abort_and_notify(self._failure_outcome) self._processing = False return
def deliver(): delivery_outcome = callable_util.call_logging_exceptions( behavior, _EXCEPTION_LOG_MESSAGE, value) if delivery_outcome.kind is callable_util.Outcome.Kind.RAISED: with self._lock: self._abort_and_notify(_LOCAL_FAILURE_OUTCOME)
def deliver(): delivery_outcome = callable_util.call_logging_exceptions( behavior, _EXCEPTION_LOG_MESSAGE, value) if delivery_outcome.kind is callable_util.Outcome.Kind.RAISED: with self._lock: self._abort_and_notify(_LOCAL_FAILURE_OUTCOME)