Ejemplo n.º 1
0
async def test_parallel_allocate_idle_label():
    start_method = os.environ.get('POOL_START_METHOD', 'forkserver') \
        if sys.platform != 'win32' else None
    pool = await create_actor_pool('127.0.0.1',
                                   pool_cls=MainActorPool,
                                   n_process=2,
                                   subprocess_start_method=start_method,
                                   labels=[None, 'my_label', 'my_label'])

    class _Actor(Actor):
        def get_pid(self):
            return os.getpid()

    ctx = get_context()
    strategy = IdleLabel('my_label', 'tests')
    tasks = [
        ctx.create_actor(_Actor,
                         allocate_strategy=strategy,
                         address=pool.external_address),
        ctx.create_actor(_Actor,
                         allocate_strategy=strategy,
                         address=pool.external_address),
    ]
    refs = await asyncio.gather(*tasks)
    # outputs identical process ids, while the result should be different
    assert len({await ref.get_pid() for ref in refs}) == 2
Ejemplo n.º 2
0
async def test_slot_kill(actor_pool: ActorPoolType):
    pool, slot_manager_ref = actor_pool

    strategy = IdleLabel('numa-0', 'task_actor')
    task_ref = await mo.create_actor(TaskActor, {},
                                     allocate_strategy=strategy,
                                     address=pool.external_address)

    assert await mo.actor_ref(BandSlotControlActor.gen_uid('numa-0', 0),
                              address=pool.external_address)
    delayed_task = asyncio.create_task(task_ref.queued_call('key', 10))
    await asyncio.sleep(0.1)

    # check if process hosting the actor is closed
    kill_task = asyncio.create_task(slot_manager_ref.kill_slot(0))
    await asyncio.sleep(0)
    kill_task2 = asyncio.create_task(slot_manager_ref.kill_slot(0))

    with pytest.raises(ServerClosed):
        await delayed_task

    # check if slot actor is restored
    await kill_task
    # check if secondary task makes no change
    await kill_task2

    assert await mo.actor_ref(BandSlotControlActor.gen_uid('numa-0', 0),
                              address=pool.external_address)
    assert await mo.actor_ref(task_ref)
Ejemplo n.º 3
0
async def test_cancel_transfer(create_actors, mock_sender, mock_receiver):
    worker_address_1, worker_address_2 = create_actors

    strategy = IdleLabel('io', 'mock_sender')
    quota_refs = {StorageLevel.MEMORY: await mo.actor_ref(
        StorageQuotaActor, StorageLevel.MEMORY, 5 * 1024 * 1024,
        address=worker_address_2, uid=StorageQuotaActor.gen_uid(StorageLevel.MEMORY))}

    await mo.create_actor(
        mock_sender, uid=mock_sender.default_uid(),
        address=worker_address_1, allocate_strategy=strategy)
    await mo.create_actor(
        mock_receiver, quota_refs, uid=mock_receiver.default_uid(),
        address=worker_address_2, allocate_strategy=strategy)

    data1 = np.random.rand(10, 10)
    storage_handler1 = await mo.actor_ref(
        uid=StorageHandlerActor.default_uid(),
        address=worker_address_1)
    storage_handler2 = await mo.actor_ref(
        uid=StorageHandlerActor.default_uid(),
        address=worker_address_2)
    await storage_handler1.put('mock', 'data_key1',
                               data1, StorageLevel.MEMORY)

    sender_actor = await mo.actor_ref(address=worker_address_1,
                                      uid=mock_sender.default_uid())
    used_before = (await quota_refs[StorageLevel.MEMORY].get_quota())[1]

    send_task = asyncio.create_task(sender_actor.send_data(
        'mock', 'data_key1', worker_address_2, StorageLevel.MEMORY))

    await asyncio.sleep(0.5)
    send_task.cancel()

    try:
        await send_task
    except asyncio.CancelledError:
        pass

    used = (await quota_refs[StorageLevel.MEMORY].get_quota())[1]
    assert used == used_before

    with pytest.raises(DataNotExist):
        await storage_handler2.get('mock', 'data_key1')

    send_task = asyncio.create_task(sender_actor.send_data(
        'mock', 'data_key1', worker_address_2, StorageLevel.MEMORY))
    await send_task
    get_data = await storage_handler2.get('mock', 'data_key1')
    np.testing.assert_array_equal(data1, get_data)
Ejemplo n.º 4
0
async def test_logging_config(logging_conf):
    start_method = os.environ.get('POOL_START_METHOD', 'forkserver') \
        if sys.platform != 'win32' else None
    pool = await create_actor_pool('127.0.0.1',
                                   pool_cls=MainActorPool,
                                   n_process=1,
                                   subprocess_start_method=start_method,
                                   labels=[None, 'my_label'],
                                   logging_conf=logging_conf)

    class _Actor(Actor):
        def get_logger_level(self):
            logger = logging.getLogger(__name__)
            return logger.getEffectiveLevel()

    async with pool:
        ctx = get_context()
        strategy = IdleLabel('my_label', 'tests')
        ref = await ctx.create_actor(_Actor,
                                     allocate_strategy=strategy,
                                     address=pool.external_address)
        assert await ref.get_logger_level() == logging.DEBUG
Ejemplo n.º 5
0
async def test_slot_restart(actor_pool: ActorPoolType):
    pool, slot_manager_ref = actor_pool

    strategy = IdleLabel('numa-0', 'task_actor')
    task_refs = []
    for idx in range(3):
        ref = await mo.create_actor(TaskActor, {},
                                    slot_id=idx,
                                    allocate_strategy=strategy,
                                    address=pool.external_address)
        await ref.queued_call('idx', idx)
        task_refs.append(ref)

    await slot_manager_ref.acquire_free_slot(('session_id', 'subtask_id1'))
    slot_id2 = await slot_manager_ref.acquire_free_slot(
        ('session_id', 'subtask_id2'))
    await slot_manager_ref.release_free_slot(slot_id2)

    async def record_finish_time(coro):
        await coro
        return time.time()

    restart_task1 = asyncio.create_task(
        record_finish_time(slot_manager_ref.restart_free_slots()))
    await asyncio.sleep(0)
    restart_task2 = asyncio.create_task(
        record_finish_time(slot_manager_ref.restart_free_slots()))
    acquire_task = asyncio.create_task(
        record_finish_time(
            slot_manager_ref.acquire_free_slot(('session_id', 'subtask_id3'))))

    await asyncio.gather(restart_task1, restart_task2, acquire_task)

    # check only slots with running records are restarted
    assert len(await task_refs[0].get_call_logs()) > 0
    assert len(await task_refs[1].get_call_logs()) == 0
    assert len(await task_refs[2].get_call_logs()) > 0

    assert abs(restart_task1.result() - acquire_task.result()) < 0.1
Ejemplo n.º 6
0
def test_idle_label():
    strategy = IdleLabel('test', 'my_mark')
    addresses = config.get_external_addresses(label='test')
    assert len(addresses) == 2
    allocated = {
        addresses[0]: {
            create_actor_ref(addresses[0], b'id1'): (strategy, None)
        }
    }
    assert strategy.get_allocated_address(config, allocated) == addresses[1]

    strategy2 = IdleLabel('test', 'my_mark')
    allocated = {
        addresses[0]: {
            create_actor_ref(addresses[0], b'id1'): (strategy, None),
            create_actor_ref(addresses[0], b'id2'): (RandomLabel('test'), None)
        },
        addresses[1]: {
            create_actor_ref(addresses[1], b'id3'): (strategy2, None)
        }
    }
    with pytest.raises(NoIdleSlot):
        strategy2.get_allocated_address(config, allocated)
Ejemplo n.º 7
0
async def test_main_actor_pool():
    config = ActorPoolConfig()
    my_label = 'computation'
    main_address = f'127.0.0.1:{get_next_port()}'
    _add_pool_conf(config, 0, 'main', 'unixsocket:///0', main_address)
    _add_pool_conf(config,
                   1,
                   my_label,
                   'unixsocket:///1',
                   f'127.0.0.1:{get_next_port()}',
                   env={'my_env': '1'})
    _add_pool_conf(config, 2, my_label, 'unixsocket:///2',
                   f'127.0.0.1:{get_next_port()}')

    strategy = IdleLabel(my_label, 'my_test')

    async with await MainActorPool.create({'actor_pool_config':
                                           config}) as pool:
        create_actor_message = CreateActorMessage(new_message_id(), TestActor,
                                                  b'test', tuple(), dict(),
                                                  MainPool())
        message = await pool.create_actor(create_actor_message)
        actor_ref = message.result
        assert actor_ref.address == main_address

        create_actor_message1 = CreateActorMessage(new_message_id(), TestActor,
                                                   b'test1', tuple(), dict(),
                                                   strategy)
        message1 = await pool.create_actor(create_actor_message1)
        actor_ref1 = message1.result
        assert actor_ref1.address in config.get_external_addresses(my_label)

        create_actor_message2 = CreateActorMessage(new_message_id(), TestActor,
                                                   b'test2', tuple(), dict(),
                                                   strategy)
        message2 = await pool.create_actor(create_actor_message2)
        actor_ref2 = message2.result
        assert actor_ref2.address in config.get_external_addresses(my_label)
        assert actor_ref2.address != actor_ref1.address

        create_actor_message3 = CreateActorMessage(new_message_id(), TestActor,
                                                   b'test3', tuple(), dict(),
                                                   strategy)
        message3 = await pool.create_actor(create_actor_message3)
        # no slot to allocate the same label
        assert isinstance(message3.error, NoIdleSlot)

        has_actor_message = HasActorMessage(
            new_message_id(), create_actor_ref(main_address, b'test2'))
        assert (await pool.has_actor(has_actor_message)).result is True

        actor_ref_message = ActorRefMessage(
            new_message_id(), create_actor_ref(main_address, b'test2'))
        assert (await pool.actor_ref(actor_ref_message)).result == actor_ref2

        # tell
        tell_message = TellMessage(new_message_id(), actor_ref1,
                                   ('add', 0, (2, ), dict()))
        message = await pool.tell(tell_message)
        assert message.result is None

        # send
        send_message = SendMessage(new_message_id(), actor_ref1,
                                   ('add', 0, (4, ), dict()))
        assert (await pool.send(send_message)).result == 6

        # test error message
        # type mismatch
        send_message = SendMessage(new_message_id(), actor_ref1,
                                   ('add', 0, ('3', ), dict()))
        result = await pool.send(send_message)
        assert isinstance(result.error, TypeError)

        # send and tell to main process
        tell_message = TellMessage(new_message_id(), actor_ref,
                                   ('add', 0, (2, ), dict()))
        message = await pool.tell(tell_message)
        assert message.result is None
        send_message = SendMessage(new_message_id(), actor_ref,
                                   ('add', 0, (4, ), dict()))
        assert (await pool.send(send_message)).result == 6

        # send and cancel
        send_message = SendMessage(new_message_id(), actor_ref1,
                                   ('sleep', 0, (20, ), dict()))
        result_task = asyncio.create_task(pool.send(send_message))
        start = time.time()
        cancel_message = CancelMessage(new_message_id(), actor_ref1.address,
                                       send_message.message_id)
        cancel_task = asyncio.create_task(pool.cancel(cancel_message))
        result = await asyncio.wait_for(cancel_task, 3)
        assert result.message_type == MessageType.result
        assert result.result is True
        result = await result_task
        assert time.time() - start < 3
        assert result.message_type == MessageType.result
        assert result.result == 7

        # destroy
        destroy_actor_message = DestroyActorMessage(new_message_id(),
                                                    actor_ref1)
        message = await pool.destroy_actor(destroy_actor_message)
        assert message.result == actor_ref1.uid

        tell_message = TellMessage(new_message_id(), actor_ref1,
                                   ('add', 0, (2, ), dict()))
        message = await pool.tell(tell_message)
        assert isinstance(message, ErrorMessage)

        # destroy via connecting to sub pool directly
        async with await pool.router.get_client(
            config.get_external_addresses()[-1]) as client:
            destroy_actor_message = DestroyActorMessage(
                new_message_id(), actor_ref2)
            await client.send(destroy_actor_message)
            result = await client.recv()
            assert result.result == actor_ref2.uid

        # test sync config
        config.add_pool_conf(3, 'sub', 'unixsocket:///3',
                             f'127.0.0.1:{get_next_port()}')
        sync_config_message = ControlMessage(new_message_id(),
                                             pool.external_address,
                                             ControlMessageType.sync_config,
                                             config)
        message = await pool.handle_control_command(sync_config_message)
        assert message.result is True

        # test get config
        get_config_message = ControlMessage(new_message_id(),
                                            config.get_external_addresses()[1],
                                            ControlMessageType.get_config,
                                            None)
        message = await pool.handle_control_command(get_config_message)
        config2 = message.result
        assert config.as_dict() == config2.as_dict()

    assert pool.stopped
Ejemplo n.º 8
0
async def test_cancel_transfer(create_actors, mock_sender, mock_receiver):
    worker_address_1, worker_address_2 = create_actors

    quota_refs = {
        StorageLevel.MEMORY:
        await
        mo.actor_ref(StorageQuotaActor,
                     StorageLevel.MEMORY,
                     5 * 1024 * 1024,
                     address=worker_address_2,
                     uid=StorageQuotaActor.gen_uid('numa-0',
                                                   StorageLevel.MEMORY))
    }
    data_manager_ref = await mo.actor_ref(uid=DataManagerActor.default_uid(),
                                          address=worker_address_1)
    storage_handler1 = await mo.actor_ref(
        uid=StorageHandlerActor.gen_uid('numa-0'), address=worker_address_1)
    storage_handler2 = await mo.actor_ref(
        uid=StorageHandlerActor.gen_uid('numa-0'), address=worker_address_2)

    sender_actor = await mo.create_actor(mock_sender,
                                         data_manager_ref=data_manager_ref,
                                         uid=mock_sender.default_uid(),
                                         address=worker_address_1,
                                         allocate_strategy=IdleLabel(
                                             'io', 'mock_sender'))
    await mo.create_actor(mock_receiver,
                          quota_refs,
                          uid=mock_receiver.default_uid(),
                          address=worker_address_2,
                          allocate_strategy=IdleLabel('io', 'mock_receiver'))

    data1 = np.random.rand(10, 10)
    await storage_handler1.put('mock', 'data_key1', data1, StorageLevel.MEMORY)
    data2 = pd.DataFrame(np.random.rand(100, 100))
    await storage_handler1.put('mock', 'data_key2', data2, StorageLevel.MEMORY)

    used_before = (await quota_refs[StorageLevel.MEMORY].get_quota())[1]

    send_task = asyncio.create_task(
        sender_actor.send_batch_data('mock', ['data_key1'], worker_address_2,
                                     StorageLevel.MEMORY))

    await asyncio.sleep(0.5)
    send_task.cancel()

    with pytest.raises(asyncio.CancelledError):
        await send_task

    used = (await quota_refs[StorageLevel.MEMORY].get_quota())[1]
    assert used == used_before

    with pytest.raises(DataNotExist):
        await storage_handler2.get('mock', 'data_key1')

    send_task = asyncio.create_task(
        sender_actor.send_batch_data('mock', ['data_key1'], worker_address_2,
                                     StorageLevel.MEMORY))
    await send_task
    get_data = await storage_handler2.get('mock', 'data_key1')
    np.testing.assert_array_equal(data1, get_data)

    # cancel when fetch the same data Simultaneously
    if mock_sender is MockSenderManagerActor:
        send_task1 = asyncio.create_task(
            sender_actor.send_batch_data('mock', ['data_key2'],
                                         worker_address_2,
                                         StorageLevel.MEMORY))
        send_task2 = asyncio.create_task(
            sender_actor.send_batch_data('mock', ['data_key2'],
                                         worker_address_2,
                                         StorageLevel.MEMORY))
        await asyncio.sleep(0.5)
        send_task1.cancel()
        with pytest.raises(asyncio.CancelledError):
            await send_task1
        await send_task2
        get_data2 = await storage_handler2.get('mock', 'data_key2')
        pd.testing.assert_frame_equal(get_data2, data2)