def METHOD_NAME(self, targets: Iterable[Step]) -> Tuple[Dict, Dict]:
    import concurrent.futures
    all_steps = set(targets)
    for step in targets:
        all_steps |= step.recursive_dependencies
    steps: Dict[str, StepInfo] = {}
    run_data: Dict[str, str] = {}
    # Collect step info.
    with concurrent.futures.ThreadPoolExecutor(
        thread_name_prefix="RemoteWorkspace._get_run_step_info()-"
    ) as executor:
        step_info_futures = []
        for step in all_steps:
            if step.name is None:
                continue
            step_info_futures.append(executor.submit(self.step_info, step))
        for future in concurrent.futures.as_completed(step_info_futures):
            step_info = future.result()
            assert step_info.step_name is not None
            steps[step_info.step_name] = step_info
            run_data[step_info.step_name] = step_info.unique_id
    return steps, run_data