-
Notifications
You must be signed in to change notification settings - Fork 808
Description
We're attempting to migrate our app to use read only db endpoints. In our implementation we decided that the read only endpoint should be the default endpoint i.e. you must explicitly decide you want to write. Which to us seems to make sense. Also we implemented our own database router as follows. Router docs. Which handles the direction of individual models read/writes.
class Router:
def db_for_write(model, **hints):
return "writer"
def db_for_read(model, **hints):
return "default"
This appears to be perfectly fine for areas where transactions are not used. However when transactions are used we get an error.
raise TransactionManagementError('select_for_update cannot be used outside of a transaction.')
django.db.transaction.TransactionManagementError: select_for_update cannot be used outside of a transaction
This emanates from Oauth2Validator.save_bearer_token
which opens a transaction against"default"
and at various points will call select_for_update
. This can also happen when AbstractRefreshToken.revoke
is called as it also opens a transaction.
Since we can't specify the using
argument in the transaction.atomic
we have resorted to implementing our own validator and refresh token model. Overriding the methods and copy pasting the original implementation with one that allows us to specify the using
argument. For obvious reasons (we don't want to have to validate the implementation hasn't changed each oauth toolkit release) this is not ideal.
That all being said my initial questions are
What ways have other users solved this?
Is there a general Django convention for transaction connection management? e.g. assume you can always write against default