Skip to content

Commit

Permalink
refactor: update Redis configuration (#2312)
Browse files Browse the repository at this point in the history
Refactor the Redis configuration in the base settings file. The changes include adding support for Redis Sentinel for high availability and failover. The `REDIS_SENTINELS`, `REDIS_SENTINEL_MASTER_NAME`, and `REDIS_SENTINEL_KWARGS` environment variables are used to configure the Redis Sentinel settings. The `DJANGO_SENTINELS` and `CACHES` options are updated accordingly. Additionally, the Celery broker transport options are updated to handle retries when connecting to RabbitMQ.

Related issue: #2312 #4360

base.py
  • Loading branch information
daddyy committed Oct 8, 2024
1 parent 5cf382a commit 879d908
Showing 1 changed file with 51 additions and 5 deletions.
56 changes: 51 additions & 5 deletions engine/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ class DatabaseTypes:
REDIS_PORT = os.getenv("REDIS_PORT", 6379)
REDIS_DATABASE = os.getenv("REDIS_DATABASE", 1)
REDIS_PROTOCOL = os.getenv("REDIS_PROTOCOL", "redis")
REDIS_KEY_PREFIX = os.getenv("REDIS_KEY_PREFIX", None)

REDIS_URI = os.getenv("REDIS_URI")
if not REDIS_URI:
Expand Down Expand Up @@ -248,6 +249,7 @@ class DatabaseTypes:
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_URI,
"KEY_PREFIX": REDIS_KEY_PREFIX,
"OPTIONS": {
"DB": REDIS_DATABASE,
"PARSER_CLASS": "redis.connection._HiredisParser",
Expand All @@ -263,6 +265,41 @@ class DatabaseTypes:
},
}

REDIS_SENTINELS = os.getenv("REDIS_SENTINELS", None)

if REDIS_SENTINELS:
REDIS_SENTINEL_MASTER_NAME = os.getenv("REDIS_SENTINEL_MASTER_NAME", None)
REDIS_SENTINEL_USERNAME = os.getenv("REDIS_SENTINEL_USERNAME", None)
REDIS_SENTINEL_PASSWORD = os.getenv("REDIS_SENTINEL_PASSWORD", None)
REDIS_SENTINEL_KWARGS = {"password": REDIS_SENTINEL_PASSWORD, "username": REDIS_SENTINEL_USERNAME}

DJANGO_SENTINELS = [tuple(sentinel.split(":")) for sentinel in REDIS_SENTINELS.split(",")]
DJANGO_SENTINELS = [(host, int(port)) for host, port in DJANGO_SENTINELS]

DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.SentinelConnectionFactory'

CACHES["default"] = {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"redis://{REDIS_USERNAME}@{REDIS_SENTINEL_MASTER_NAME}/{REDIS_DATABASE}",
"KEY_PREFIX": REDIS_KEY_PREFIX,
"OPTIONS": {
"PARSER_CLASS": "redis.connection._HiredisParser",
"CLIENT_CLASS": "django_redis.client.SentinelClient",
"CONNECTION_POOL_CLASS": "redis.sentinel.SentinelConnectionPool",
"SENTINELS": DJANGO_SENTINELS,
"MASTER_NAME": REDIS_SENTINEL_MASTER_NAME,
"PASSWORD": REDIS_PASSWORD,
"SENTINEL_KWARGS": REDIS_SENTINEL_KWARGS,
"CONNECTION_POOL_CLASS_KWARGS": REDIS_SSL_CONFIG
| {
"max_connections": 50,
"timeout": 20,
},
"MAX_CONNECTIONS": 1000,
"PICKLE_VERSION": -1,
},
}

# Application definition

INSTALLED_APPS = [
Expand Down Expand Up @@ -498,6 +535,11 @@ class BrokerTypes:
RABBITMQ = "rabbitmq"
REDIS = "redis"

# By default, apply_async will just hang indefinitely trying to reach to RabbitMQ even if RabbitMQ is down.
# This makes apply_async retry 3 times trying to reach to RabbitMQ, with some extra info on periods between retries.
# https://docs.celeryproject.org/en/stable/userguide/configuration.html#std-setting-broker_transport_options
# Note that max_retries is not related to task retries, but to rabbitmq specific kombu settings.
CELERY_BROKER_TRANSPORT_OPTIONS = {"max_retries": 3, "interval_start": 0, "interval_step": 0.2, "interval_max": 0.5}

BROKER_TYPE = os.getenv("BROKER_TYPE", BrokerTypes.RABBITMQ).lower()
assert BROKER_TYPE in {BrokerTypes.RABBITMQ, BrokerTypes.REDIS}
Expand All @@ -506,16 +548,20 @@ class BrokerTypes:
CELERY_BROKER_URL = RABBITMQ_URI
elif BROKER_TYPE == BrokerTypes.REDIS:
CELERY_BROKER_URL = REDIS_URI
if REDIS_KEY_PREFIX:
CELERY_BROKER_TRANSPORT_OPTIONS["global_keyprefix"] = REDIS_KEY_PREFIX
if REDIS_USE_SSL:
CELERY_BROKER_USE_SSL = REDIS_SSL_CONFIG
if REDIS_SENTINELS:
CELERY_BROKER_URL = ";".join([f"sentinel://{REDIS_USERNAME}:{REDIS_PASSWORD}@{sentinel}/{REDIS_DATABASE}" for sentinel in REDIS_SENTINELS.split(",")])
if REDIS_SENTINEL_MASTER_NAME:
CELERY_BROKER_TRANSPORT_OPTIONS["master_name"] = REDIS_SENTINEL_MASTER_NAME
if REDIS_SENTINEL_KWARGS:
CELERY_BROKER_TRANSPORT_OPTIONS["sentinel_kwargs"] = REDIS_SENTINEL_KWARGS
else:
raise ValueError(f"Invalid BROKER_TYPE env variable: {BROKER_TYPE}")

# By default, apply_async will just hang indefinitely trying to reach to RabbitMQ even if RabbitMQ is down.
# This makes apply_async retry 3 times trying to reach to RabbitMQ, with some extra info on periods between retries.
# https://docs.celeryproject.org/en/stable/userguide/configuration.html#std-setting-broker_transport_options
# Note that max_retries is not related to task retries, but to rabbitmq specific kombu settings.
CELERY_BROKER_TRANSPORT_OPTIONS = {"max_retries": 3, "interval_start": 0, "interval_step": 0.2, "interval_max": 0.5}
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True

CELERY_IGNORE_RESULT = True
CELERY_ACKS_LATE = True
Expand Down

0 comments on commit 879d908

Please sign in to comment.