Skip to content

Multi database setup w/ read only endpoints #868

@Amertz08

Description

@Amertz08

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions