def test_distributed_actor_handle_deletion(ray_start_regular_shared): @ray.remote class Actor: def method(self): return 1 def getpid(self): return os.getpid() @ray.remote def f(actor, signal): ray.get(signal.wait.remote()) return ray.get(actor.method.remote()) SignalActor = create_remote_signal_actor(ray) signal = SignalActor.remote() a = Actor.remote() pid = ray.get(a.getpid.remote()) # Pass the handle to another task that cannot run yet. x_id = f.remote(a, signal) # Delete the original handle. The actor should not get killed yet. del a # Once the task finishes, the actor process should get killed. ray.get(signal.send.remote()) assert ray.get(x_id) == 1 wait_for_pid_to_exit(pid)
def test_remote_functions(ray_start_regular_shared): with ray_start_client_server() as ray: SignalActor = create_remote_signal_actor(ray) signaler = SignalActor.remote() @ray.remote def plus2(x): return x + 2 @ray.remote def fact(x): print(x, type(fact)) if x <= 0: return 1 # This hits the "nested tasks" issue # https://github.com/ray-project/ray/issues/3644 # So we're on the right track! return ray.get(fact.remote(x - 1)) * x ref2 = plus2.remote(234) # `236` assert ray.get(ref2) == 236 ref3 = fact.remote(20) # `2432902008176640000` assert ray.get(ref3) == 2_432_902_008_176_640_000 # Reuse the cached ClientRemoteFunc object ref4 = fact.remote(5) assert ray.get(ref4) == 120 # Test ray.wait() ref5 = fact.remote(10) # should return ref2, ref3, ref4 res = ray.wait([ref5, ref2, ref3, ref4], num_returns=3) assert [ref2, ref3, ref4] == res[0] assert [ref5] == res[1] assert ray.get(res[0]) == [236, 2_432_902_008_176_640_000, 120] # should return ref2, ref3, ref4, ref5 res = ray.wait([ref2, ref3, ref4, ref5], num_returns=4) assert [ref2, ref3, ref4, ref5] == res[0] assert [] == res[1] all_vals = ray.get(res[0]) assert all_vals == [236, 2_432_902_008_176_640_000, 120, 3628800] # Timeout 0 on ray.wait leads to immediate return # (not indefinite wait for first return as with timeout None): unready_ref = signaler.wait.remote() res = ray.wait([unready_ref], timeout=0) # Not ready. assert res[0] == [] and len(res[1]) == 1 ray.get(signaler.send.remote()) ready_ref = signaler.wait.remote() # Ready. res = ray.wait([ready_ref], timeout=10) assert len(res[0]) == 1 and res[1] == []
def test_get_with_timeout(ray_start_regular_shared): SignalActor = create_remote_signal_actor(ray) signal = SignalActor.remote() # Check that get() returns early if object is ready. start = time.time() ray.get(signal.wait.remote(should_wait=False), timeout=30) assert time.time() - start < 30 # Check that get() raises a TimeoutError after the timeout if the object # is not ready yet. result_id = signal.wait.remote() with pytest.raises(GetTimeoutError): ray.get(result_id, timeout=0.1) # Check that a subsequent get() returns early. ray.get(signal.send.remote()) start = time.time() ray.get(result_id, timeout=30) assert time.time() - start < 30
def test_cancel_chain(ray_start_regular, use_force): with ray_start_client_server() as ray: SignalActor = create_remote_signal_actor(ray) signaler = SignalActor.remote() @ray.remote def wait_for(t): return ray.get(t[0]) obj1 = wait_for.remote([signaler.wait.remote()]) obj2 = wait_for.remote([obj1]) obj3 = wait_for.remote([obj2]) obj4 = wait_for.remote([obj3]) assert len(ray.wait([obj1], timeout=.1)[0]) == 0 ray.cancel(obj1, force=use_force) for ob in [obj1, obj2, obj3, obj4]: with pytest.raises(valid_exceptions(use_force)): ray.get(ob) signaler2 = SignalActor.remote() obj1 = wait_for.remote([signaler2.wait.remote()]) obj2 = wait_for.remote([obj1]) obj3 = wait_for.remote([obj2]) obj4 = wait_for.remote([obj3]) assert len(ray.wait([obj3], timeout=.1)[0]) == 0 ray.cancel(obj3, force=use_force) for ob in [obj3, obj4]: with pytest.raises(valid_exceptions(use_force)): ray.get(ob) with pytest.raises(GetTimeoutError): ray.get(obj1, timeout=.1) with pytest.raises(GetTimeoutError): ray.get(obj2, timeout=.1) signaler2.send.remote() ray.get(obj1)