-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix connect/pool create cancellation and gc after (#16)
* Fix connect/pool create cancellation and gc after
- Loading branch information
Showing
7 changed files
with
214 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import asyncio | ||
import logging | ||
import socket | ||
import ssl | ||
from typing import List, Tuple, Type, Union | ||
|
||
from .abc import AbcConnection | ||
from .util import parse_url | ||
|
||
|
||
try: | ||
from aioredis.stream import open_connection, open_unix_connection | ||
except ImportError: | ||
from .._aioredis.stream import open_connection, open_unix_connection | ||
try: | ||
from aioredis.connection import MAX_CHUNK_SIZE, RedisConnection | ||
except ImportError: | ||
from .._aioredis.connection import MAX_CHUNK_SIZE, RedisConnection | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
async def create_connection( | ||
address: Union[str, Tuple[str, int], List], | ||
*, | ||
db: int = None, | ||
password: str = None, | ||
ssl: Union[bool, ssl.SSLContext] = None, | ||
encoding: str = None, | ||
parser=None, | ||
timeout: float = None, | ||
connection_cls: Type[AbcConnection] = None, | ||
loop=None, | ||
) -> AbcConnection: | ||
"""Creates redis connection. | ||
Opens connection to Redis server specified by address argument. | ||
Address argument can be one of the following: | ||
* A tuple representing (host, port) pair for TCP connections; | ||
* A string representing either Redis URI or unix domain socket path. | ||
SSL argument is passed through to asyncio.create_connection. | ||
By default SSL/TLS is not used. | ||
By default any timeout is applied at the connection stage, however | ||
you can set a limitted time used trying to open a connection via | ||
the `timeout` Kw. | ||
Encoding argument can be used to decode byte-replies to strings. | ||
By default no decoding is done. | ||
Parser parameter can be used to pass custom Redis protocol parser class. | ||
By default hiredis.Reader is used (unless it is missing or platform | ||
is not CPython). | ||
Return value is RedisConnection instance or a connection_cls if it is | ||
given. | ||
This function is a coroutine. | ||
""" | ||
assert isinstance(address, (tuple, list, str)), "tuple or str expected" | ||
if isinstance(address, str): | ||
address, options = parse_url(address) | ||
logger.debug("Parsed Redis URI %r", address) | ||
db = options.setdefault("db", db) | ||
password = options.setdefault("password", password) | ||
encoding = options.setdefault("encoding", encoding) | ||
timeout = options.setdefault("timeout", timeout) | ||
if "ssl" in options: | ||
assert options["ssl"] or (not options["ssl"] and not ssl), ( | ||
"Conflicting ssl options are set", | ||
options["ssl"], | ||
ssl, | ||
) | ||
ssl = ssl or options["ssl"] | ||
|
||
if timeout is not None and timeout <= 0: | ||
raise ValueError("Timeout has to be None or a number greater than 0") | ||
|
||
if connection_cls: | ||
assert issubclass( | ||
connection_cls, AbcConnection | ||
), "connection_class does not meet the AbcConnection contract" | ||
cls = connection_cls | ||
else: | ||
cls = RedisConnection | ||
|
||
if isinstance(address, (list, tuple)): | ||
host, port = address | ||
logger.debug("Creating tcp connection to %r", address) | ||
reader, writer = await asyncio.wait_for( | ||
open_connection(host, port, limit=MAX_CHUNK_SIZE, ssl=ssl), timeout | ||
) | ||
sock = writer.transport.get_extra_info("socket") | ||
if sock is not None: | ||
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) | ||
address = sock.getpeername() | ||
address = tuple(address[:2]) # type: ignore | ||
else: | ||
logger.debug("Creating unix connection to %r", address) | ||
reader, writer = await asyncio.wait_for( | ||
open_unix_connection(address, ssl=ssl, limit=MAX_CHUNK_SIZE), timeout | ||
) | ||
sock = writer.transport.get_extra_info("socket") | ||
if sock is not None: | ||
address = sock.getpeername() | ||
|
||
conn = cls(reader, writer, encoding=encoding, address=address, parser=parser) | ||
|
||
try: | ||
if password is not None: | ||
await conn.auth(password) | ||
if db is not None: | ||
await conn.select(db) | ||
except (asyncio.CancelledError, Exception): | ||
conn.close() | ||
await conn.wait_closed() | ||
raise | ||
return conn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import asyncio | ||
import ssl | ||
from typing import List, Tuple, Type, Union | ||
|
||
from .abc import AbcConnection, AbcPool | ||
from .util import parse_url | ||
|
||
|
||
try: | ||
from aioredis.pool import ConnectionsPool | ||
except ImportError: | ||
from .._aioredis.pool import ConnectionsPool | ||
|
||
|
||
async def create_pool( | ||
address: Union[str, Tuple[str, int], List], | ||
*, | ||
db: int = None, | ||
password: str = None, | ||
ssl: Union[bool, ssl.SSLContext] = None, | ||
encoding: str = None, | ||
minsize: int = 1, | ||
maxsize: int = 10, | ||
parser=None, | ||
create_connection_timeout: float = None, | ||
pool_cls: Type[AbcPool] = None, | ||
connection_cls: Type[AbcConnection] = None, | ||
loop=None, | ||
): | ||
# FIXME: rewrite docstring | ||
"""Creates Redis Pool. | ||
By default it creates pool of Redis instances, but it is | ||
also possible to create pool of plain connections by passing | ||
``lambda conn: conn`` as commands_factory. | ||
*commands_factory* parameter is deprecated since v0.2.9 | ||
All arguments are the same as for create_connection. | ||
Returns RedisPool instance or a pool_cls if it is given. | ||
""" | ||
if pool_cls: | ||
assert issubclass(pool_cls, AbcPool), "pool_class does not meet the AbcPool contract" | ||
cls = pool_cls | ||
else: | ||
cls = ConnectionsPool | ||
if isinstance(address, str): | ||
address, options = parse_url(address) | ||
db = options.setdefault("db", db) | ||
password = options.setdefault("password", password) | ||
encoding = options.setdefault("encoding", encoding) | ||
create_connection_timeout = options.setdefault("timeout", create_connection_timeout) | ||
if "ssl" in options: | ||
assert options["ssl"] or (not options["ssl"] and not ssl), ( | ||
"Conflicting ssl options are set", | ||
options["ssl"], | ||
ssl, | ||
) | ||
ssl = ssl or options["ssl"] | ||
# TODO: minsize/maxsize | ||
|
||
pool = cls( | ||
address, | ||
db, | ||
password, | ||
encoding, | ||
minsize=minsize, | ||
maxsize=maxsize, | ||
ssl=ssl, | ||
parser=parser, | ||
create_connection_timeout=create_connection_timeout, | ||
connection_cls=connection_cls, | ||
) | ||
try: | ||
await pool._fill_free(override_min=False) | ||
except (asyncio.CancelledError, Exception): | ||
pool.close() | ||
await pool.wait_closed() | ||
raise | ||
return pool |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters