def test_output_with_name(workflow_start_regular): @ray.remote def double(v): return 2 * v inner_task = double.options(**workflow.options(name="inner")).bind(1) outer_task = double.options(**workflow.options( name="outer")).bind(inner_task) result = workflow.run_async(outer_task, workflow_id="double") inner = workflow.get_output_async("double", name="inner") outer = workflow.get_output_async("double", name="outer") assert ray.get(inner) == 2 assert ray.get(outer) == 4 assert ray.get(result) == 4 @workflow.options(name="double") @ray.remote def double_2(s): return s * 2 inner_task = double_2.bind(1) outer_task = double_2.bind(inner_task) workflow_id = "double_2" result = workflow.run_async(outer_task, workflow_id=workflow_id) inner = workflow.get_output_async(workflow_id, name="double") outer = workflow.get_output_async(workflow_id, name="double_1") assert ray.get(inner) == 2 assert ray.get(outer) == 4 assert ray.get(result) == 4
def test_get_output_4(workflow_start_regular, tmp_path): """Test getting output of a workflow tasks that are dynamically generated.""" lock_path = str(tmp_path / "lock") lock = FileLock(lock_path) @ray.remote def recursive(n): if n <= 0: with FileLock(lock_path): return 42 return workflow.continuation( recursive.options(**workflow.options(name=str(n - 1))).bind(n - 1)) workflow_id = "test_get_output_4" lock.acquire() obj = workflow.run_async( recursive.options(**workflow.options(name="10")).bind(10), workflow_id=workflow_id, ) outputs = [ workflow.get_output_async(workflow_id, name=str(i)) for i in range(11) ] outputs.append(obj) import time # wait so that 'get_output' is scheduled before executing the workflow time.sleep(3) lock.release() assert ray.get(outputs) == [42] * len(outputs)
def test_get_named_step_output_running(workflow_start_regular, tmp_path): @ray.remote def double(v, lock=None): if lock is not None: with FileLock(lock_path): return 2 * v else: return 2 * v # Get the result from named step after workflow before it's finished lock_path = str(tmp_path / "lock") lock = FileLock(lock_path) lock.acquire() output = workflow.run_async( double.options(**workflow.options(name="outer")).bind( double.options(**workflow.options(name="inner")).bind( 1, lock_path), lock_path, ), workflow_id="double-2", ) inner = workflow.get_output_async("double-2", name="inner") outer = workflow.get_output_async("double-2", name="outer") @ray.remote def wait(obj_ref): return ray.get(obj_ref[0]) # Make sure nothing is finished. ready, waiting = ray.wait( [wait.remote([output]), wait.remote([inner]), wait.remote([outer])], timeout=1) assert 0 == len(ready) assert 3 == len(waiting) # Once job finished, we'll be able to get the result. lock.release() assert [4, 2, 4] == ray.get([output, inner, outer]) inner = workflow.get_output_async("double-2", name="inner") outer = workflow.get_output_async("double-2", name="outer") assert [2, 4] == ray.get([inner, outer])
def test_task_id_generation(workflow_start_regular_shared, request): @ray.remote def simple(x): return x + 1 x = simple.options(**workflow.options(name="simple")).bind(-1) n = 20 for i in range(1, n): x = simple.options(**workflow.options(name="simple")).bind(x) workflow_id = "test_task_id_generation" ret = workflow.run_async(x, workflow_id=workflow_id) outputs = [workflow.get_output_async(workflow_id, name="simple")] for i in range(1, n): outputs.append( workflow.get_output_async(workflow_id, name=f"simple_{i}")) assert ray.get(ret) == n - 1 assert ray.get(outputs) == list(range(n))
def test_get_non_exist_output(workflow_start_regular, tmp_path): lock_path = str(tmp_path / "lock") @ray.remote def simple(): with FileLock(lock_path): return "hello" workflow_id = "test_get_non_exist_output" with FileLock(lock_path): dag = simple.options(**workflow.options(name="simple")).bind() ret = workflow.run_async(dag, workflow_id=workflow_id) exist = workflow.get_output_async(workflow_id, name="simple") non_exist = workflow.get_output_async(workflow_id, name="non_exist") assert ray.get(ret) == "hello" assert ray.get(exist) == "hello" with pytest.raises(ValueError, match="non_exist"): ray.get(non_exist)
def test_get_output_2(workflow_start_regular, tmp_path): lock_path = str(tmp_path / "lock") lock = FileLock(lock_path) @ray.remote def simple(v): with FileLock(lock_path): return v lock.acquire() obj = workflow.run_async(simple.bind(0), workflow_id="simple") obj2 = workflow.get_output_async("simple") lock.release() assert ray.get([obj, obj2]) == [0, 0]
def test_get_output_5(workflow_start_regular, tmp_path): """Test getting output of a workflow task immediately after executing it asynchronously.""" @ray.remote def simple(): return 314 workflow_id = "test_get_output_5_{}" outputs = [] for i in range(20): workflow.run_async(simple.bind(), workflow_id=workflow_id.format(i)) outputs.append(workflow.get_output_async(workflow_id.format(i))) assert ray.get(outputs) == [314] * len(outputs)