Example #1
0
class BaseClient(Generic[SessionT], HookableMixin, metaclass=abc.ABCMeta):
    '''Base client.'''
    class ClientEvent(enum.Enum):
        new_session = 'new_session'

    def __init__(self, connection_pool: Optional[ConnectionPool] = None):
        '''
        Args:
            connection_pool: Connection pool.
        '''
        super().__init__()
        if connection_pool is not None:
            self._connection_pool = connection_pool
        else:
            self._connection_pool = ConnectionPool()

        self.event_dispatcher.register(self.ClientEvent.new_session)

    @abc.abstractmethod
    def _session_class(self) -> Callable[[], SessionT]:
        '''Return session class.'''
        return BaseSession  # return something for code checkers

    def session(self) -> SessionT:
        '''Return a new session.'''
        session = self._session_class()(
            connection_pool=self._connection_pool, )
        self.event_dispatcher.notify(self.ClientEvent.new_session, session)
        return session

    def close(self):
        '''Close the connection pool.'''
        _logger.debug('Client closing.')
        self._connection_pool.close()
Example #2
0
    def test_multiple_hosts(self):
        pool = ConnectionPool(max_host_count=5, max_count=20)

        for port in range(10):
            session = yield from pool.session('localhost', port)

            with session as connection:
                self.assertTrue(connection)
Example #3
0
    def test_host_max_limit(self):
        pool = ConnectionPool(max_host_count=2)

        yield from pool.acquire('localhost', self.get_http_port())
        yield from pool.acquire('localhost', self.get_http_port())

        with self.assertRaises(asyncio.TimeoutError):
            yield from asyncio.wait_for(
                pool.acquire('localhost', self.get_http_port()), 0.1)
Example #4
0
    def test_clean(self):
        pool = ConnectionPool(max_host_count=2)

        conn1 = yield from pool.acquire('localhost', self.get_http_port())
        conn2 = yield from pool.acquire('localhost', self.get_http_port())

        yield from pool.release(conn1)
        yield from pool.release(conn2)
        yield from pool.clean()

        self.assertEqual(0, len(pool.host_pools))
Example #5
0
    def __init__(self, connection_pool: Optional[ConnectionPool] = None):
        '''
        Args:
            connection_pool: Connection pool.
        '''
        super().__init__()
        if connection_pool is not None:
            self._connection_pool = connection_pool
        else:
            self._connection_pool = ConnectionPool()

        self.event_dispatcher.register(self.ClientEvent.new_session)
Example #6
0
    def test_session(self):
        pool = ConnectionPool()

        for dummy in range(10):
            session = yield from \
                pool.session('localhost', self.get_http_port())
            with session as connection:
                if connection.closed():
                    yield from connection.connect()

        self.assertEqual(1, len(pool.host_pools))
        host_pool = list(pool.host_pools.values())[0]
        self.assertIsInstance(host_pool, HostPool)
        self.assertEqual(1, host_pool.count())
Example #7
0
    def test_connection_pool_release_clean_race_condition(self):
        pool = ConnectionPool(max_host_count=1)

        connection = yield from pool.acquire('127.0.0.1', 1234)
        connection_2_task = asyncio. async (pool.acquire('127.0.0.1', 1234))
        yield from asyncio.sleep(0.01)
        pool.no_wait_release(connection)
        yield from pool.clean(force=True)
        connection_2 = yield from connection_2_task

        # This line should not KeyError crash:
        yield from pool.release(connection_2)
Example #8
0
    def __init__(self, connection_pool: Optional[ConnectionPool]=None):
        '''
        Args:
            connection_pool: Connection pool.
        '''
        super().__init__()
        if connection_pool is not None:
            self._connection_pool = connection_pool
        else:
            self._connection_pool = ConnectionPool()

        self.event_dispatcher.register(self.ClientEvent.new_session)
Example #9
0
class BaseClient(Generic[SessionT], HookableMixin, metaclass=abc.ABCMeta):
    '''Base client.'''

    class ClientEvent(enum.Enum):
        new_session = 'new_session'

    def __init__(self, connection_pool: Optional[ConnectionPool]=None):
        '''
        Args:
            connection_pool: Connection pool.
        '''
        super().__init__()
        if connection_pool is not None:
            self._connection_pool = connection_pool
        else:
            self._connection_pool = ConnectionPool()

        self.event_dispatcher.register(self.ClientEvent.new_session)

    @abc.abstractmethod
    def _session_class(self) -> Callable[[], SessionT]:
        '''Return session class.'''
        return BaseSession  # return something for code checkers

    def session(self) -> SessionT:
        '''Return a new session.'''
        session = self._session_class()(
            connection_pool=self._connection_pool,
        )
        self.event_dispatcher.notify(self.ClientEvent.new_session, session)
        return session

    def close(self):
        '''Close the connection pool.'''
        _logger.debug('Client closing.')
        self._connection_pool.close()
Example #10
0
    def test_client_exception_recovery(self):
        connection_factory = functools.partial(Connection, timeout=2.0)
        connection_pool = ConnectionPool(connection_factory=connection_factory)
        client = Client(connection_pool=connection_pool)

        for dummy in range(7):
            with self.assertRaises(NetworkError), client.session() as session:
                request = Request(self.get_url('/header_early_close'))
                yield from session.start(request)

        for dummy in range(7):
            with client.session() as session:
                request = Request(self.get_url('/'))
                response = yield from session.start(request)
                self.assertEqual(200, response.status_code)
                yield from session.download()
                self.assertTrue(session.done())
Example #11
0
    def test_basic_acquire(self):
        pool = ConnectionPool(max_host_count=2)

        conn1 = yield from pool.acquire('localhost', self.get_http_port())
        conn2 = yield from pool.acquire('localhost', self.get_http_port())

        yield from pool.release(conn1)
        yield from pool.release(conn2)

        conn3 = yield from pool.acquire('localhost', self.get_http_port())
        conn4 = yield from pool.acquire('localhost', self.get_http_port())

        yield from pool.release(conn3)
        yield from pool.release(conn4)
Example #12
0
    def test_over_host_max_limit_cycling(self):
        pool = ConnectionPool(max_host_count=10, max_count=10)

        @asyncio.coroutine
        def con_fut():
            session = yield from \
                pool.session('localhost', self.get_http_port())

            with session as connection:
                if connection.closed():
                    yield from connection.connect()

        futs = [con_fut() for dummy in range(20)]

        yield from asyncio.wait(futs)

        self.assertEqual(1, len(pool.host_pools))
        connection_pool_entry = list(pool.host_pools.values())[0]
        self.assertIsInstance(connection_pool_entry, HostPool)
        self.assertGreaterEqual(10, connection_pool_entry.count())
Example #13
0
    def test_happy_eyeballs(self):
        connection_factory = functools.partial(Connection, connect_timeout=10)
        resolver = Resolver()
        pool = ConnectionPool(resolver=resolver,
                              connection_factory=connection_factory)

        conn1 = yield from pool.acquire('google.com', 80)
        conn2 = yield from pool.acquire('google.com', 80)

        yield from conn1.connect()
        yield from conn2.connect()
        conn1.close()
        conn2.close()

        yield from pool.release(conn1)
        yield from pool.release(conn2)

        conn3 = yield from pool.acquire('google.com', 80)

        yield from conn3.connect()
        conn3.close()

        yield from pool.release(conn3)