def _get_maybe_ready_for_revert(self, atom): """Returns if an atom is *likely* ready to be reverted.""" def ready_checker(succ_connected_it): for succ in succ_connected_it: succ_atom, (succ_atom_state, _succ_atom_intention) = succ if succ_atom_state not in (st.PENDING, st.REVERTED, st.IGNORE): LOG.trace("Unable to begin to revert since successor" " atom '%s' is in state %s", succ_atom, succ_atom_state) return False LOG.trace("Able to let '%s' revert", atom) return True noop_decider = deciders.NoOpDecider() connected_fetcher = lambda: \ traversal.depth_first_iterate(self._execution_graph, atom, # Whether the desired atom # can revert is dependent on its # successors states (thus why we # look forwards). traversal.Direction.FORWARD) decider_fetcher = lambda: noop_decider # If this atoms current state is able to be transitioned to REVERTING # and its intention is either REVERT or RETRY and all of its # successors are either PENDING or REVERTED then this atom is ready # to revert. LOG.trace("Checking if '%s' is ready to revert", atom) return self._get_maybe_ready(atom, st.REVERTING, [st.REVERT, st.RETRY], connected_fetcher, ready_checker, decider_fetcher, for_what='revert')
def _get_maybe_ready_for_execute(self, atom): """Returns if an atom is *likely* ready to be executed.""" def ready_checker(pred_connected_it): for pred in pred_connected_it: pred_atom, (pred_atom_state, pred_atom_intention) = pred if (pred_atom_state in (st.SUCCESS, st.IGNORE) and pred_atom_intention in (st.EXECUTE, st.IGNORE)): continue LOG.trace("Unable to begin to execute since predecessor" " atom '%s' is in state %s with intention %s", pred_atom, pred_atom_state, pred_atom_intention) return False LOG.trace("Able to let '%s' execute", atom) return True decider_fetcher = lambda: \ deciders.IgnoreDecider( atom, self._runtime.fetch_edge_deciders(atom)) connected_fetcher = lambda: \ traversal.depth_first_iterate(self._execution_graph, atom, # Whether the desired atom # can execute is dependent on its # predecessors outcomes (thus why # we look backwards). traversal.Direction.BACKWARD) # If this atoms current state is able to be transitioned to RUNNING # and its intention is to EXECUTE and all of its predecessors executed # successfully or were ignored then this atom is ready to execute. LOG.trace("Checking if '%s' is ready to execute", atom) return self._get_maybe_ready(atom, st.RUNNING, [st.EXECUTE], connected_fetcher, ready_checker, decider_fetcher, for_what='execute')
def _affect_all_successors(atom, runtime): execution_graph = runtime.compilation.execution_graph successors_iter = traversal.depth_first_iterate( execution_graph, atom, traversal.Direction.FORWARD) runtime.reset_atoms(itertools.chain([atom], successors_iter), state=states.IGNORE, intention=states.IGNORE)
def reset_subgraph(self, atom, state=st.PENDING, intention=st.EXECUTE): """Resets a atoms subgraph to the given state and intention. The subgraph is contained of **all** of the atoms successors. """ execution_graph = self._compilation.execution_graph atoms_it = tr.depth_first_iterate(execution_graph, atom, tr.Direction.FORWARD) return self.reset_atoms(atoms_it, state=state, intention=intention)
def _affect_successor_tasks_in_same_flow(atom, runtime): execution_graph = runtime.compilation.execution_graph successors_iter = traversal.depth_first_iterate( execution_graph, atom, traversal.Direction.FORWARD, # Do not go through nested flows but do follow *all* tasks that # are directly connected in this same flow (thus the reason this is # called the same flow decider); retries are direct successors # of flows, so they should also be not traversed through, but # setting this explicitly ensures that. through_flows=False, through_retries=False) runtime.reset_atoms(itertools.chain([atom], successors_iter), state=states.IGNORE, intention=states.IGNORE)