Merge pull request #5495 from FinnStutzenstein/redisConnectionError

Ping redis connection when popped from pool
This commit is contained in:
Emanuel Schütze 2020-08-12 17:00:13 +02:00 committed by GitHub
commit a40657e153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 2 deletions

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ bower_components/*
# OS3+ # OS3+
/server/ /server/
/haproxy/
# Local user data (settings, database, media, search index, static files) # Local user data (settings, database, media, search index, static files)
personal_data/* personal_data/*

View File

@ -1,5 +1,5 @@
import asyncio import asyncio
from typing import Any, Dict, List from typing import Any, Dict, List, Optional
import aioredis import aioredis
from channels_redis.core import ConnectionPool as ChannelRedisConnectionPool from channels_redis.core import ConnectionPool as ChannelRedisConnectionPool
@ -13,6 +13,10 @@ connection_pool_limit = getattr(settings, "CONNECTION_POOL_LIMIT", 100)
logger.info(f"CONNECTION_POOL_LIMIT={connection_pool_limit}") logger.info(f"CONNECTION_POOL_LIMIT={connection_pool_limit}")
class InvalidConnection(Exception):
pass
class ConnectionPool(ChannelRedisConnectionPool): class ConnectionPool(ChannelRedisConnectionPool):
""" Adds a trivial, soft limit for the pool """ """ Adds a trivial, soft limit for the pool """
@ -27,7 +31,34 @@ class ConnectionPool(ChannelRedisConnectionPool):
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
self.counter += 1 self.counter += 1
return await super().pop(*args, **kwargs) return await self.pop_ensured_connection(*args, **kwargs)
async def pop_ensured_connection(
self, *args: List[Any], **kwargs: Dict[str, Any]
) -> aioredis.commands.Redis:
redis: Optional[aioredis.commands.Redis] = None
while redis is None:
redis = await super().pop(*args, **kwargs)
try:
await self.try_ping(redis)
except InvalidConnection:
if redis is not None:
super().conn_error(redis)
redis = None
return redis
async def try_ping(self, redis: aioredis.commands.Redis) -> None:
try:
pong = await redis.ping()
if pong != b"PONG":
logger.info("Redis connection invalid, did not recieve PONG")
raise InvalidConnection()
except (ConnectionRefusedError, ConnectionResetError):
logger.info("Redis connection invalid, connection is bad")
raise InvalidConnection()
def push(self, conn: aioredis.commands.Redis) -> None: def push(self, conn: aioredis.commands.Redis) -> None:
super().push(conn) super().push(conn)