File: sentinel.py

package info (click to toggle)
django-redis 5.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 476 kB
  • sloc: python: 2,904; makefile: 6; sh: 6
file content (41 lines) | stat: -rw-r--r-- 1,543 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse

from django.core.exceptions import ImproperlyConfigured
from redis.sentinel import SentinelConnectionPool

from .default import DefaultClient


def replace_query(url, query):
    return urlunparse((*url[:4], urlencode(query, doseq=True), url[5]))


class SentinelClient(DefaultClient):
    """
    Sentinel client which uses the single redis URL specified by the CACHE's
    LOCATION to create a LOCATION configuration for two connection pools; One
    pool for the primaries and another pool for the replicas, and upon
    connecting ensures the connection pool factory is configured correctly.
    """

    def __init__(self, server, params, backend):
        if isinstance(server, str):
            url = urlparse(server)
            primary_query = parse_qs(url.query, keep_blank_values=True)
            replica_query = dict(primary_query)
            primary_query["is_master"] = [1]
            replica_query["is_master"] = [0]

            server = [replace_query(url, i) for i in (primary_query, replica_query)]

        super().__init__(server, params, backend)

    def connect(self, *args, **kwargs):
        connection = super().connect(*args, **kwargs)
        if not isinstance(connection.connection_pool, SentinelConnectionPool):
            raise ImproperlyConfigured(
                "Settings DJANGO_REDIS_CONNECTION_FACTORY or "
                "CACHE[].OPTIONS.CONNECTION_POOL_CLASS is not configured correctly."
            )

        return connection