OpenSlides/openslides/utils/redis.py
2019-12-03 12:30:31 +01:00

62 lines
1.9 KiB
Python

from typing import Any
from django.conf import settings
from . import logging
logger = logging.getLogger(__name__)
try:
import aioredis
except ImportError:
use_redis = False
use_read_only_redis = False
else:
from .redis_connection_pool import ConnectionPool
# set use_redis to true, if there is a value for REDIS_ADDRESS in the settings
redis_address = getattr(settings, "REDIS_ADDRESS", "")
use_redis = bool(redis_address)
if use_redis:
logger.info(f"Redis address {redis_address}")
pool = ConnectionPool({"address": redis_address})
redis_read_only_address = getattr(settings, "REDIS_READ_ONLY_ADDRESS", "")
use_read_only_redis = bool(redis_read_only_address)
if use_read_only_redis:
logger.info(f"Redis read only address {redis_read_only_address}")
read_only_pool = ConnectionPool({"address": redis_read_only_address})
else:
logger.info("Redis is not configured.")
# TODO: contextlib.asynccontextmanager can be used in python 3.7
class RedisConnectionContextManager:
"""
Async context manager for connections
"""
def __init__(self, read_only: bool) -> None:
self.pool = read_only_pool if read_only and use_read_only_redis else pool
async def __aenter__(self) -> "aioredis.RedisConnection":
self.conn = await self.pool.pop()
return self.conn
async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
if exc:
logger.warn(f"Redis Exception: {exc}. Do not reuse connection...")
self.pool.conn_error(self.conn)
else:
self.pool.push(self.conn)
self.conn = None
def get_connection(read_only: bool = False) -> RedisConnectionContextManager:
"""
Returns contextmanager for a redis connection.
"""
return RedisConnectionContextManager(read_only)