authentik.tenants.db

 1from random import choice
 2
 3from django.conf import settings
 4from django.db import DEFAULT_DB_ALIAS, connections
 5
 6
 7class FailoverRouter:
 8    """Support an primary/read-replica PostgreSQL setup (reading from replicas
 9    and write to primary only)"""
10
11    def __init__(self) -> None:
12        super().__init__()
13        self.database_aliases = set(settings.DATABASES.keys())
14        self.read_replica_aliases = list(self.database_aliases - {DEFAULT_DB_ALIAS})
15        self.replica_enabled = len(self.read_replica_aliases) > 0
16
17    def db_for_read(self, model, **hints):
18        if not self.replica_enabled:
19            return DEFAULT_DB_ALIAS
20        # Stay on primary for the entire transaction to maintain consistency.
21        # Reading from a replica mid-transaction would give a different snapshot,
22        # breaking transactional semantics (not just read-your-writes, but the
23        # entire consistent point-in-time view that a transaction provides).
24        if connections[DEFAULT_DB_ALIAS].in_atomic_block:
25            return DEFAULT_DB_ALIAS
26        return choice(self.read_replica_aliases)  # nosec
27
28    def db_for_write(self, model, **hints):
29        return DEFAULT_DB_ALIAS
30
31    def allow_relation(self, obj1, obj2, **hints):
32        """Relations between objects are allowed if both objects are
33        in the primary/replica pool."""
34        if obj1._state.db in self.database_aliases and obj2._state.db in self.database_aliases:
35            return True
36        return None
class FailoverRouter:
 8class FailoverRouter:
 9    """Support an primary/read-replica PostgreSQL setup (reading from replicas
10    and write to primary only)"""
11
12    def __init__(self) -> None:
13        super().__init__()
14        self.database_aliases = set(settings.DATABASES.keys())
15        self.read_replica_aliases = list(self.database_aliases - {DEFAULT_DB_ALIAS})
16        self.replica_enabled = len(self.read_replica_aliases) > 0
17
18    def db_for_read(self, model, **hints):
19        if not self.replica_enabled:
20            return DEFAULT_DB_ALIAS
21        # Stay on primary for the entire transaction to maintain consistency.
22        # Reading from a replica mid-transaction would give a different snapshot,
23        # breaking transactional semantics (not just read-your-writes, but the
24        # entire consistent point-in-time view that a transaction provides).
25        if connections[DEFAULT_DB_ALIAS].in_atomic_block:
26            return DEFAULT_DB_ALIAS
27        return choice(self.read_replica_aliases)  # nosec
28
29    def db_for_write(self, model, **hints):
30        return DEFAULT_DB_ALIAS
31
32    def allow_relation(self, obj1, obj2, **hints):
33        """Relations between objects are allowed if both objects are
34        in the primary/replica pool."""
35        if obj1._state.db in self.database_aliases and obj2._state.db in self.database_aliases:
36            return True
37        return None

Support an primary/read-replica PostgreSQL setup (reading from replicas and write to primary only)

database_aliases
read_replica_aliases
replica_enabled
def db_for_read(self, model, **hints):
18    def db_for_read(self, model, **hints):
19        if not self.replica_enabled:
20            return DEFAULT_DB_ALIAS
21        # Stay on primary for the entire transaction to maintain consistency.
22        # Reading from a replica mid-transaction would give a different snapshot,
23        # breaking transactional semantics (not just read-your-writes, but the
24        # entire consistent point-in-time view that a transaction provides).
25        if connections[DEFAULT_DB_ALIAS].in_atomic_block:
26            return DEFAULT_DB_ALIAS
27        return choice(self.read_replica_aliases)  # nosec
def db_for_write(self, model, **hints):
29    def db_for_write(self, model, **hints):
30        return DEFAULT_DB_ALIAS
def allow_relation(self, obj1, obj2, **hints):
32    def allow_relation(self, obj1, obj2, **hints):
33        """Relations between objects are allowed if both objects are
34        in the primary/replica pool."""
35        if obj1._state.db in self.database_aliases and obj2._state.db in self.database_aliases:
36            return True
37        return None

Relations between objects are allowed if both objects are in the primary/replica pool.