def read_core_sequence()

in src/core/src/service_interfaces/LifecycleManager.py [0:0]


    def read_core_sequence(self):
        """ Reads the core sequence file, but additionally establishes if this class is allowed to write to it when the freshest data is evaluated. """
        self.composite_logger.log_debug("Reading core sequence...")
        self.identify_and_mitigate_core_sequence_issues()

        # Read (with retries for only IO Errors)
        for i in range(0, Constants.MAX_FILE_OPERATION_RETRY_COUNT):
            try:
                with self.env_layer.file_system.open(self.core_state_file_path, mode="r") as file_handle:
                    core_sequence = json.load(file_handle)['coreSequence']

                # The following code will only execute in the event of a bug
                if not self.read_only_mode and os.getpid() not in core_sequence['processIds']:
                    self.composite_logger.log_error("SERIOUS ERROR -- Core sequence was taken over in violation of sequence contract.")
                    self.read_only_mode = True  # This should never happen, but we're switching back into read-only mode.
                    if self.execution_config.exec_auto_assess_only:  # Yield execution precedence out of caution, if it's low pri auto-assessment
                        return core_sequence

                if self.read_only_mode:
                    if core_sequence['completed'].lower() == 'true' or len(self.identify_running_processes(core_sequence['processIds'])) == 0:
                        # Short-circuit for re-enable for completed non-auto-assess operations that should not run
                        if not self.execution_config.exec_auto_assess_only and core_sequence['number'] == self.execution_config.sequence_number and core_sequence['completed'].lower() == 'true':
                            self.composite_logger.log_debug("Not attempting to take ownership of core sequence since the sequence number as it's already done and this is the main process.")
                            return core_sequence

                        # Auto-assess over non-auto-assess is not a trivial override and is short-circuited to be evaluated in detail later
                        if self.execution_config.exec_auto_assess_only and not core_sequence["autoAssessment"].lower() == 'true':
                            self.composite_logger.log_debug("Auto-assessment cannot supersede the main core process trivially.")
                            return core_sequence

                        self.composite_logger.log_debug("Attempting to take ownership of core sequence.")
                        self.read_only_mode = False
                        self.update_core_sequence()
                        self.read_only_mode = True

                        # help re-evaluate if assertion succeeded
                        with self.env_layer.file_system.open(self.core_state_file_path, mode="r") as file_handle:
                            core_sequence = json.load(file_handle)['coreSequence']

                    if os.getpid() in core_sequence['processIds']:
                        self.composite_logger.log_debug("Successfully took ownership of core sequence.")
                        self.read_only_mode = False

                return core_sequence
            except Exception as error:
                if i < Constants.MAX_FILE_OPERATION_RETRY_COUNT - 1:
                    self.composite_logger.log_warning("Exception on core sequence read. [Exception={0}] [RetryCount={1}]".format(repr(error), str(i)))
                    time.sleep(i + 1)
                else:
                    self.composite_logger.log_error("Unable to read core state file (retries exhausted). [Exception={0}]".format(repr(error)))
                    raise