Files
ray-project--ray/python/ray/tests/test_multinode_failures_2.py
T
2026-07-13 13:17:40 +08:00

61 lines
2.0 KiB
Python

import sys
import numpy as np
import pytest
import ray
from ray._private.test_utils import get_other_nodes
@pytest.mark.parametrize(
"ray_start_cluster",
[{"num_cpus": 4, "num_nodes": 3, "do_init": True}],
indirect=True,
)
def test_actor_creation_node_failure(ray_start_cluster):
# TODO(swang): Refactor test_raylet_failed, etc to reuse the below code.
cluster = ray_start_cluster
@ray.remote
class Child:
def __init__(self, death_probability):
self.death_probability = death_probability
def ping(self):
# Exit process with some probability.
exit_chance = np.random.rand()
if exit_chance < self.death_probability:
sys.exit(-1)
num_children = 25
# Children actors will die about half the time.
death_probability = 0.5
children = [Child.remote(death_probability) for _ in range(num_children)]
while len(cluster.list_all_nodes()) > 1:
for j in range(2):
# Submit some tasks on the actors. About half of the actors will
# fail.
children_out = [child.ping.remote() for child in children]
# Wait a while for all the tasks to complete. This should trigger
# reconstruction for any actor creation tasks that were forwarded
# to nodes that then failed.
ready, _ = ray.wait(
children_out, num_returns=len(children_out), timeout=5 * 60.0
)
assert len(ready) == len(children_out)
# Replace any actors that died.
for i, out in enumerate(children_out):
try:
ray.get(out)
except ray.exceptions.RayActorError:
children[i] = Child.remote(death_probability)
# Remove a node. Any actor creation tasks that were forwarded to this
# node must be resubmitted.
cluster.remove_node(get_other_nodes(cluster, True)[-1])
if __name__ == "__main__":
sys.exit(pytest.main(["-sv", __file__]))