def __tell_publisher_to_stop_waiting_for_gentle_finish(self): logdebug(LOGGER, 'Main thread does not need to wait anymore. (%s).', get_now_utc_as_formatted_string()) # This avoids that the last iteration is redone # and redone upon reconnection, as after reconnection, # if this is True, the algorithm is entered again. self.__is_in_process_of_gently_closing = False # This releases the event that blocks the main thread # until the gentle finish is done. self.thread.tell_publisher_to_stop_waiting_for_gentle_finish()
def __please_open_connection(self): params = self.__node_manager.get_connection_parameters() self.__start_connect_time = datetime.datetime.now() logdebug(LOGGER, 'Connecting to RabbitMQ at %s... (%s)', params.host, get_now_utc_as_formatted_string()) loginfo(LOGGER, 'Opening connection to RabbitMQ...') self.thread._connection = pika.SelectConnection( parameters=params, on_open_callback=self.on_connection_open, on_open_error_callback=self.on_connection_error, on_close_callback=self.on_connection_closed, stop_ioloop_on_close=False # why? see below. )
def __please_open_connection(self): params = self.__node_manager.get_connection_parameters() self.__start_connect_time = datetime.datetime.now() logdebug(LOGGER, 'Connecting to RabbitMQ at %s... (%s)', params.host, get_now_utc_as_formatted_string()) loginfo(LOGGER, 'Opening connection to RabbitMQ...') self.thread._connection = pika.SelectConnection( parameters=params, on_open_callback=self.on_connection_open, on_open_error_callback=self.on_connection_error, on_close_callback=self.on_connection_closed # Removed parameter, see https://github.com/pika/pika/issues/961 )
def __finish_gently(self): # Called directly from outside the thread! # No more messages can arrive from publisher (because # the main thread blocks), but publishes/confirms are still # accepted. # Inform user if self.__are_any_messages_pending(): wait_seconds = defaults.RABBIT_ASYN_FINISH_WAIT_SECONDS max_waits = defaults.RABBIT_ASYN_FINISH_MAX_TRIES loginfo( LOGGER, 'Preparing to close PID module. Some messages are pending. Maximum waiting time: %i seconds. (%s)', wait_seconds * max_waits, get_now_utc_as_formatted_string()) else: loginfo(LOGGER, 'Closing PID module. No pending messages. (%s)', get_now_utc_as_formatted_string()) # Go through decision tree (close or wait for pending messages) self.__close_decision_iterations = 1 self.__is_in_process_of_gently_closing = True self.recursive_decision_about_closing()
def on_connection_open(self, unused_connection): logdebug(LOGGER, 'Opening connection... done.') loginfo(LOGGER, 'Connection to RabbitMQ at %s opened... (%s)', self.__node_manager.get_connection_parameters().host, get_now_utc_as_formatted_string()) # Tell the main thread we're open for events now: # When the connection is open, the thread is ready to accept events. # Note: It was already ready when the connection object was created, # not just now that it's actually open. There was already a call to # "...stop_waiting..." in start_waiting_for_events(), which quite # certainly was carried out before this callback. So this call to # "...stop_waiting..." is likelily redundant! self.thread.tell_publisher_to_stop_waiting_for_thread_to_accept_events( ) self.__please_open_rabbit_channel()
def make_permanently_closed_by_user(self): # This changes the state of the state machine! # This needs to be called from the shutter module # in case there is a force_finish while the connection # is already closed (as the callback on_connection_closed # is not called then). self.statemachine.set_to_permanently_unavailable() logtrace(LOGGER, 'Stop waiting for events due to user interrupt!') logtrace(LOGGER, 'Permanent close: Stopping ioloop of connection %s...', self.thread._connection) self.thread._connection.ioloop.stop() loginfo(LOGGER, 'Stopped listening for RabbitMQ events (%s).', get_now_utc_as_formatted_string()) logdebug( LOGGER, 'Connection to messaging service closed by user. Will not reopen.')
def __finish_gently(self): # Called directly from outside the thread! #self.statemachine.asked_to_closed_by_publisher = True # TODO # Make sure no more messages are accepted from publisher # TODO # while publishes/confirms are still accepted: #if self.statemachine.is_available_for_client_publishes(): # self.statemachine.set_to_wanting_to_stop() # Inform user if self.__are_any_messages_pending(): wait_seconds = defaults.RABBIT_ASYN_FINISH_WAIT_SECONDS max_waits = defaults.RABBIT_ASYN_FINISH_MAX_TRIES loginfo(LOGGER, 'Preparing to close PID module. Some messages are pending. Maximum waiting time: %i seconds. (%s)', wait_seconds*max_waits, get_now_utc_as_formatted_string()) else: loginfo(LOGGER, 'Closing PID module. No pending messages. (%s)', get_now_utc_as_formatted_string()) # Go through decision tree (close or wait for pending messages) self.__close_decision_iterations = 1 self.__is_in_process_of_gently_closing = True self.recursive_decision_about_closing()
def make_permanently_closed_by_error(self, connection, reply_text): # This changes the state of the state machine! # This needs to be called if there is a permanent # error and we don't want the library to reonnect, # and we also don't want to pretend it was closed # by the user. # This is really rarely needed. self.statemachine.set_to_permanently_unavailable() logtrace(LOGGER, 'Stop waiting for events due to permanent error!') # In case the main thread was waiting for any synchronization event. self.thread.unblock_events() # Close ioloop, which blocks the thread. logdebug(LOGGER, 'Permanent close: Stopping ioloop of connection %s...', self.thread._connection) self.thread._connection.ioloop.stop() loginfo(LOGGER, 'Stopped listening for RabbitMQ events (%s).', get_now_utc_as_formatted_string()) logdebug( LOGGER, 'Connection to messaging service closed because of error. Will not reopen. Reason: %s', reply_text)
def __define_other_attributes(self): self.__dataset_handle = None self.__list_of_file_handles = [] self.__list_of_file_messages = [] self.__message_timestamp = utils.get_now_utc_as_formatted_string()
def __setup_rabbit_connection(self, params): LOGGER.debug('Setting up the connection with the RabbitMQ.') self.__start_connect_time = datetime.datetime.now() self.__all_hosts_that_were_tried.add(params.host) try: time_now = get_now_utc_as_formatted_string() logdebug(LOGGER, 'Connecting to RabbitMQ at %s... (%s)', params.host, time_now) # Make connection conn = self.__make_connection(params) # Log success time_now = get_now_utc_as_formatted_string() time_passed = datetime.datetime.now() - self.__start_connect_time time_seconds = time_passed.total_seconds() loginfo( LOGGER, 'Connection to RabbitMQ at %s opened after %i seconds... (%s)', params.host, time_seconds, time_now) return conn except pika.exceptions.ProbableAuthenticationError as e: time_passed = datetime.datetime.now() - self.__start_connect_time time_seconds = time_passed.total_seconds() error_name = e.__class__.__name__ logerror( LOGGER, 'Caught Authentication Exception after %s seconds during connection ("%s").', time_seconds, error_name) msg = ( 'Problem setting up the rabbit with username "%s" and password "%s" at url %s.' % (params.credentials.username, params.credentials.password, params.host)) LOGGER.error(msg) self.__error_messages_during_init.append(msg) return None except pika.exceptions.AMQPConnectionError as e: time_passed = datetime.datetime.now() - self.__start_connect_time time_seconds = time_passed.total_seconds() error_name = e.__class__.__name__ logerror( LOGGER, 'Caught AMQPConnectionError Exception after %s seconds during connection ("%s").', time_seconds, error_name) msg = ('Problem setting up the rabbit connection to %s.' % params.host) self.__error_messages_during_init.append(msg) return None except Exception as e: time_passed = datetime.datetime.now() - self.__start_connect_time time_seconds = time_passed.total_seconds() error_name = e.__class__.__name__ logerror( LOGGER, 'Error ("%s") during connection to %s, after %s seconds.', error_name, params.host, time_seconds) msg = ( 'Unexpected problem setting up the rabbit connection to %s (%s)' % (params.host, error_name)) self.__error_messages_during_init.append(msg) raise e