sentinel.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
  2. from django.core.exceptions import ImproperlyConfigured
  3. from redis.sentinel import SentinelConnectionPool
  4. from .default import DefaultClient
  5. def replace_query(url, query):
  6. return urlunparse((*url[:4], urlencode(query, doseq=True), url[5]))
  7. class SentinelClient(DefaultClient):
  8. """
  9. Sentinel client which uses the single redis URL specified by the CACHE's
  10. LOCATION to create a LOCATION configuration for two connection pools; One
  11. pool for the primaries and another pool for the replicas, and upon
  12. connecting ensures the connection pool factory is configured correctly.
  13. """
  14. def __init__(self, server, params, backend):
  15. if isinstance(server, str):
  16. url = urlparse(server)
  17. primary_query = parse_qs(url.query, keep_blank_values=True)
  18. replica_query = dict(primary_query)
  19. primary_query["is_master"] = [1]
  20. replica_query["is_master"] = [0]
  21. server = [replace_query(url, i) for i in (primary_query, replica_query)]
  22. super().__init__(server, params, backend)
  23. def connect(self, *args, **kwargs):
  24. connection = super().connect(*args, **kwargs)
  25. if not isinstance(connection.connection_pool, SentinelConnectionPool):
  26. raise ImproperlyConfigured(
  27. "Settings DJANGO_REDIS_CONNECTION_FACTORY or "
  28. "CACHE[].OPTIONS.CONNECTION_POOL_CLASS is not configured correctly."
  29. )
  30. return connection