mirror of
https://github.com/wassname/ray.git
synced 2026-08-10 12:30:14 +08:00
Implement a first pass at actors in the API. (#242)
* Implement actor field for tasks * Implement actor management in local scheduler. * initial python frontend for actors * import actors on worker * IPython code completion and tests * prepare creating actors through local schedulers * add actor id to PyTask * submit actor calls to local scheduler * starting to integrate * simple fix * Fixes from rebasing. * more work on python actors * Improve local scheduler actor handlers. * Pass actor ID to local scheduler when connecting a client. * first working version of actors * fixing actors * fix creating two copies of the same actor * fix actors * remove sleep * get rid of export synchronization * update * insert actor methods into the queue in the right order * remove print statements * make it compile again after rebase * Minor updates. * fix python actor ids * Pass actor_id to start_worker. * add test * Minor changes. * Update actor tests. * Temporary plan for import counter. * Temporarily fix import counters. * Fix some tests. * Fixes. * Make actor creation non-blocking. * Fix test? * Fix actors on Python 2. * fix rare case. * Fix python 2 test. * More tests. * Small fixes. * Linting. * Revert tensorflow version to 0.12.0 temporarily. * Small fix. * Enhance inheritance test.
This commit is contained in:
committed by
Robert Nishihara
parent
072eadd57f
commit
12a68e84d2
@@ -165,5 +165,94 @@ class TaskStatusTest(unittest.TestCase):
|
||||
|
||||
ray.worker.cleanup()
|
||||
|
||||
class ActorTest(unittest.TestCase):
|
||||
|
||||
def testFailedActorInit(self):
|
||||
ray.init(num_workers=0, driver_mode=ray.SILENT_MODE)
|
||||
|
||||
error_message1 = "actor constructor failed"
|
||||
error_message2 = "actor method failed"
|
||||
@ray.actor
|
||||
class FailedActor(object):
|
||||
def __init__(self):
|
||||
raise Exception(error_message1)
|
||||
def get_val(self):
|
||||
return 1
|
||||
def fail_method(self):
|
||||
raise Exception(error_message2)
|
||||
|
||||
a = FailedActor()
|
||||
|
||||
# Make sure that we get errors from a failed constructor.
|
||||
wait_for_errors(b"task", 1)
|
||||
self.assertEqual(len(ray.error_info()), 1)
|
||||
self.assertIn(error_message1, ray.error_info()[0][b"message"].decode("ascii"))
|
||||
|
||||
# Make sure that we get errors from a failed method.
|
||||
a.fail_method()
|
||||
wait_for_errors(b"task", 2)
|
||||
self.assertEqual(len(ray.error_info()), 2)
|
||||
self.assertIn(error_message2, ray.error_info()[1][b"message"].decode("ascii"))
|
||||
|
||||
ray.worker.cleanup()
|
||||
|
||||
def testIncorrectMethodCalls(self):
|
||||
ray.init(num_workers=0, driver_mode=ray.SILENT_MODE)
|
||||
|
||||
@ray.actor
|
||||
class Actor(object):
|
||||
def __init__(self, missing_variable_name):
|
||||
pass
|
||||
def get_val(self, x):
|
||||
pass
|
||||
|
||||
# Make sure that we get errors if we call the constructor incorrectly.
|
||||
# TODO(rkn): These errors should instead be thrown when the method is
|
||||
# called.
|
||||
|
||||
# Create an actor with too few arguments.
|
||||
a = Actor()
|
||||
wait_for_errors(b"task", 1)
|
||||
self.assertEqual(len(ray.error_info()), 1)
|
||||
if sys.version_info >= (3, 0):
|
||||
self.assertIn("missing 1 required", ray.error_info()[0][b"message"].decode("ascii"))
|
||||
else:
|
||||
self.assertIn("takes exactly 2 arguments", ray.error_info()[0][b"message"].decode("ascii"))
|
||||
|
||||
# Create an actor with too many arguments.
|
||||
a = Actor(1, 2)
|
||||
wait_for_errors(b"task", 2)
|
||||
self.assertEqual(len(ray.error_info()), 2)
|
||||
if sys.version_info >= (3, 0):
|
||||
self.assertIn("but 3 were given", ray.error_info()[1][b"message"].decode("ascii"))
|
||||
else:
|
||||
self.assertIn("takes exactly 2 arguments", ray.error_info()[1][b"message"].decode("ascii"))
|
||||
|
||||
# Create an actor the correct number of arguments.
|
||||
a = Actor(1)
|
||||
|
||||
# Call a method with too few arguments.
|
||||
a.get_val()
|
||||
wait_for_errors(b"task", 3)
|
||||
self.assertEqual(len(ray.error_info()), 3)
|
||||
if sys.version_info >= (3, 0):
|
||||
self.assertIn("missing 1 required", ray.error_info()[2][b"message"].decode("ascii"))
|
||||
else:
|
||||
self.assertIn("takes exactly 2 arguments", ray.error_info()[2][b"message"].decode("ascii"))
|
||||
|
||||
# Call a method with too many arguments.
|
||||
a.get_val(1, 2)
|
||||
wait_for_errors(b"task", 4)
|
||||
self.assertEqual(len(ray.error_info()), 4)
|
||||
if sys.version_info >= (3, 0):
|
||||
self.assertIn("but 3 were given", ray.error_info()[3][b"message"].decode("ascii"))
|
||||
else:
|
||||
self.assertIn("takes exactly 2 arguments", ray.error_info()[3][b"message"].decode("ascii"))
|
||||
# Call a method that doesn't exist.
|
||||
with self.assertRaises(AttributeError):
|
||||
a.nonexistent_method()
|
||||
|
||||
ray.worker.cleanup()
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user