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)
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
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.