Ejemplo n.º 1
0
async def test_create_actor_pool():
    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)

    async with pool:
        # test global router
        global_router = Router.get_instance()
        # global router should not be the identical one with pool's router
        assert global_router is not pool.router
        assert pool.external_address in global_router._curr_external_addresses
        assert pool.external_address in global_router._mapping

        ctx = get_context()

        # actor on main pool
        actor_ref = await ctx.create_actor(TestActor, uid='test-1',
                                           address=pool.external_address)
        assert await actor_ref.add(3) == 3
        assert await actor_ref.add(1) == 4
        assert (await ctx.has_actor(actor_ref)) is True
        assert (await ctx.actor_ref(actor_ref)) == actor_ref
        # test cancel
        task = asyncio.create_task(actor_ref.sleep(20))
        await asyncio.sleep(0)
        task.cancel()
        assert await task == 5
        await ctx.destroy_actor(actor_ref)
        assert (await ctx.has_actor(actor_ref)) is False
        for f in actor_ref.add, ctx.actor_ref, ctx.destroy_actor:
            with pytest.raises(ActorNotExist):
                await f(actor_ref)

        # actor on sub pool
        actor_ref1 = await ctx.create_actor(TestActor, uid='test-main',
                                            address=pool.external_address)
        actor_ref2 = await ctx.create_actor(TestActor, uid='test-2',
                                            address=pool.external_address,
                                            allocate_strategy=RandomSubPool())
        assert (await ctx.actor_ref(uid='test-2', address=actor_ref2.address)) == actor_ref2
        main_ref = await ctx.actor_ref(uid='test-main', address=actor_ref2.address)
        assert main_ref.address == pool.external_address
        main_ref = await ctx.actor_ref(actor_ref1)
        assert main_ref.address == pool.external_address
        assert actor_ref2.address != actor_ref.address
        assert await actor_ref2.add(3) == 3
        assert await actor_ref2.add(1) == 4
        with pytest.raises(RuntimeError):
            await actor_ref2.return_cannot_unpickle()
        assert (await ctx.has_actor(actor_ref2)) is True
        assert (await ctx.actor_ref(actor_ref2)) == actor_ref2
        # test cancel
        task = asyncio.create_task(actor_ref2.sleep(20))
        start = time.time()
        await asyncio.sleep(0)
        task.cancel()
        assert await task == 5
        assert time.time() - start < 3
        await ctx.destroy_actor(actor_ref2)
        assert (await ctx.has_actor(actor_ref2)) is False

    # after pool shutdown, global router must has been cleaned
    global_router = Router.get_instance()
    assert len(global_router._curr_external_addresses) == 0
    assert len(global_router._mapping) == 0
Ejemplo n.º 2
0
async def test_sub_actor_pool(notify_main_pool):
    notify_main_pool.return_value = None
    config = ActorPoolConfig()

    ext_address0 = f'127.0.0.1:{get_next_port()}'
    ext_address1 = f'127.0.0.1:{get_next_port()}'
    _add_pool_conf(config, 0, 'main', 'unixsocket:///0', ext_address0)
    _add_pool_conf(config, 1, 'sub', 'unixsocket:///1', ext_address1)

    pool = await SubActorPool.create({
        'actor_pool_config': config,
        'process_index': 1
    })
    await pool.start()

    create_actor_message = CreateActorMessage(
        new_message_id(),
        TestActor, b'test', tuple(), dict(),
        AddressSpecified(pool.external_address))
    message = await pool.create_actor(create_actor_message)
    assert message.message_type == MessageType.result
    actor_ref = message.result
    assert actor_ref.address == pool.external_address
    assert actor_ref.uid == b'test'

    has_actor_message = HasActorMessage(
        new_message_id(), actor_ref)
    assert (await pool.has_actor(has_actor_message)).result is True

    actor_ref_message = ActorRefMessage(
        new_message_id(), actor_ref)
    assert (await pool.actor_ref(actor_ref_message)).result == actor_ref

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

    send_message = SendMessage(
        new_message_id(), actor_ref, ('add', 0, (3,), dict()))
    message = await pool.send(send_message)
    assert message.result == 4

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

    send_message = SendMessage(
        new_message_id(), create_actor_ref(actor_ref.address, 'non_exist'),
        ('add', 0, (3,), dict()))
    result = await pool.send(send_message)
    assert isinstance(result.error, ActorNotExist)

    # test send message and cancel it
    send_message = SendMessage(
        new_message_id(), actor_ref, ('sleep', 0, (20,), dict()))
    result_task = asyncio.create_task(pool.send(send_message))
    await asyncio.sleep(0)
    start = time.time()
    cancel_message = CancelMessage(
        new_message_id(), actor_ref.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
    # test time
    assert time.time() - start < 3
    assert result.message_type == MessageType.result
    assert result.result == 5

    # test processing message on background
    async with await pool.router.get_client(pool.external_address) as client:
        send_message = SendMessage(
            new_message_id(), actor_ref, ('add', 0, (5,), dict()))
        await client.send(send_message)
        result = await client.recv()
        assert result.result == 9

        send_message = SendMessage(
            new_message_id(), actor_ref, ('add', 0, ('5',), dict()))
        await client.send(send_message)
        result = await client.recv()
        assert isinstance(result.error, TypeError)

    destroy_actor_message = DestroyActorMessage(
        new_message_id(), actor_ref)
    message = await pool.destroy_actor(destroy_actor_message)
    assert message.result == actor_ref.uid

    # send destroy failed
    message = await pool.destroy_actor(destroy_actor_message)
    assert isinstance(message.error, ActorNotExist)

    message = await pool.has_actor(has_actor_message)
    assert not message.result

    # test sync config
    _add_pool_conf(config, 1, 'sub', 'unixsocket:///1', f'127.0.0.1:{get_next_port()}')
    sync_config_message = ControlMessage(
        new_message_id(), '', 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(), '', 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.router._mapping == Router.get_instance()._mapping
    assert pool.router._curr_external_addresses == \
           Router.get_instance()._curr_external_addresses

    stop_message = ControlMessage(
        new_message_id(), '', ControlMessageType.stop, None)
    message = await pool.handle_control_command(stop_message)
    assert message.result is True

    await pool.join(.05)
    assert pool.stopped