def test_task_default_resources(self): task1 = photon.Task(random_driver_id(), random_function_id(), [random_object_id()], 0, random_task_id(), 0) self.assertEqual(task1.required_resources(), [1.0, 0.0]) task2 = photon.Task(random_driver_id(), random_function_id(), [random_object_id()], 0, random_task_id(), 0, photon.ObjectID(NIL_ACTOR_ID), 0, [1.0, 2.0]) self.assertEqual(task2.required_resources(), [1.0, 2.0])
def test_integration_single_task(self): # There should be three db clients, the global scheduler, the local # scheduler, and the plasma manager. self.assertEqual( len(self.redis_client.keys("{}*".format(DB_CLIENT_PREFIX))), 2 * NUM_CLUSTER_NODES + 1) num_return_vals = [0, 1, 2, 3, 5, 10] # There should not be anything else in Redis yet. self.assertEqual(len(self.redis_client.keys("*")), 2 * NUM_CLUSTER_NODES + 1) # Insert the object into Redis. data_size = 0xf1f0 metadata_size = 0x40 plasma_client = self.plasma_clients[0] object_dep, memory_buffer, metadata = create_object(plasma_client, data_size, metadata_size, seal=True) # Sleep before submitting task to photon. time.sleep(0.1) # Submit a task to Redis. task = photon.Task(random_driver_id(), random_function_id(), [photon.ObjectID(object_dep)], num_return_vals[0], random_task_id(), 0) self.photon_clients[0].submit(task) time.sleep(0.1) # There should now be a task in Redis, and it should get assigned to the # local scheduler num_retries = 10 while num_retries > 0: task_entries = self.redis_client.keys("{}*".format(TASK_PREFIX)) self.assertLessEqual(len(task_entries), 1) if len(task_entries) == 1: task_contents = self.redis_client.hgetall(task_entries[0]) task_status = int(task_contents[b"state"]) self.assertTrue(task_status in [ TASK_STATUS_WAITING, TASK_STATUS_SCHEDULED, TASK_STATUS_QUEUED ]) if task_status == TASK_STATUS_QUEUED: break else: print(task_status) print("The task has not been scheduled yet, trying again.") num_retries -= 1 time.sleep(1) if num_retries <= 0 and task_status != TASK_STATUS_QUEUED: # Failed to submit and schedule a single task -- bail. self.tearDown() sys.exit(1)
def get_actor_method_function_id(attr): """Get the function ID corresponding to an actor method. Args: attr (str): The attribute name of the method. Returns: Function ID corresponding to the method. """ function_id = hashlib.sha1() function_id.update(attr.encode("ascii")) return photon.ObjectID(function_id.digest())
def test_equality_comparisons(self): x1 = photon.ObjectID(ID_SIZE * b"a") x2 = photon.ObjectID(ID_SIZE * b"a") y1 = photon.ObjectID(ID_SIZE * b"b") y2 = photon.ObjectID(ID_SIZE * b"b") self.assertEqual(x1, x2) self.assertEqual(y1, y2) self.assertNotEqual(x1, y1) random_strings = [np.random.bytes(ID_SIZE) for _ in range(256)] object_ids1 = [photon.ObjectID(random_strings[i]) for i in range(256)] object_ids2 = [photon.ObjectID(random_strings[i]) for i in range(256)] self.assertEqual(len(set(object_ids1)), 256) self.assertEqual(len(set(object_ids1 + object_ids2)), 256) self.assertEqual(set(object_ids1), set(object_ids2))
def fetch_and_register_actor(key, worker): """Import an actor.""" driver_id, actor_id_str, actor_name, module, pickled_class, class_export_counter = \ worker.redis_client.hmget(key, ["driver_id", "actor_id", "name", "module", "class", "class_export_counter"]) actor_id = photon.ObjectID(actor_id_str) actor_name = actor_name.decode("ascii") module = module.decode("ascii") class_export_counter = int(class_export_counter) try: unpickled_class = pickling.loads(pickled_class) except: raise NotImplemented("TODO(pcm)") else: # TODO(pcm): Why is the below line necessary? unpickled_class.__module__ = module worker.actors[actor_id_str] = unpickled_class.__new__(unpickled_class) for (k, v) in inspect.getmembers( unpickled_class, predicate=( lambda x: inspect.isfunction(x) or inspect.ismethod(x))): function_id = get_actor_method_function_id(k).id() worker.function_names[function_id] = k worker.functions[function_id] = v
def random_function_id(): return photon.ObjectID(np.random.bytes(ID_SIZE))
def random_task_id(): return photon.ObjectID(np.random.bytes(ID_SIZE))
def random_driver_id(): return photon.ObjectID(np.random.bytes(ID_SIZE))
def integration_many_tasks_helper(self, timesync=True): # There should be three db clients, the global scheduler, the local # scheduler, and the plasma manager. self.assertEqual( len(self.redis_client.keys("{}*".format(DB_CLIENT_PREFIX))), 2 * NUM_CLUSTER_NODES + 1) num_return_vals = [0, 1, 2, 3, 5, 10] # Submit a bunch of tasks to Redis. num_tasks = 1000 for _ in range(num_tasks): # Create a new object for each task. data_size = np.random.randint(1 << 20) metadata_size = np.random.randint(1 << 10) plasma_client = self.plasma_clients[0] object_dep, memory_buffer, metadata = create_object(plasma_client, data_size, metadata_size, seal=True) if timesync: # Give 10ms for object info handler to fire (long enough to yield CPU). time.sleep(0.010) task = photon.Task(random_driver_id(), random_function_id(), [photon.ObjectID(object_dep)], num_return_vals[0], random_task_id(), 0) self.photon_clients[0].submit(task) # Check that there are the correct number of tasks in Redis and that they # all get assigned to the local scheduler. num_retries = 10 num_tasks_done = 0 while num_retries > 0: task_entries = self.redis_client.keys("{}*".format(TASK_PREFIX)) self.assertLessEqual(len(task_entries), num_tasks) # First, check if all tasks made it to Redis. if len(task_entries) == num_tasks: task_contents = [ self.redis_client.hgetall(task_entries[i]) for i in range(len(task_entries)) ] task_statuses = [ int(contents[b"state"]) for contents in task_contents ] self.assertTrue( all([ status in [ TASK_STATUS_WAITING, TASK_STATUS_SCHEDULED, TASK_STATUS_QUEUED ] for status in task_statuses ])) num_tasks_done = task_statuses.count(TASK_STATUS_QUEUED) num_tasks_scheduled = task_statuses.count( TASK_STATUS_SCHEDULED) num_tasks_waiting = task_statuses.count(TASK_STATUS_WAITING) print( "tasks in Redis = {}, tasks waiting = {}, tasks scheduled = {}, tasks queued = {}, retries left = {}" .format(len(task_entries), num_tasks_waiting, num_tasks_scheduled, num_tasks_done, num_retries)) if all( [status == TASK_STATUS_QUEUED for status in task_statuses]): # We're done, so pass. break num_retries -= 1 time.sleep(0.1) if num_tasks_done != num_tasks: # At least one of the tasks failed to schedule. self.tearDown() sys.exit(2)
def random_actor_id(): return photon.ObjectID(random_string())