The `delete_expired` method of ResultManager sometimes selects read-only database
jacklinke opened this issue · 0 comments
jacklinke commented
In a django project with a database router and read-only databases, the delete_expired
method may try to perform raw_delete()
using a read-only database, resulting in an Internal Error: "ReadOnlySqlTransaction - cannot execute DELETE in a read-only transaction".
def delete_expired(self, expires):
"""Delete all expired results."""
with transaction.atomic(using=self.db):
raw_delete(queryset=self.get_all_expired(expires))
My Database Router:
import random
from django.conf import settings
class CustomRouter:
def db_for_read(self, model, **hints):
"""
Return either default or one of the replicas
"""
db_read = [
"default",
]
if settings.REPLICA1_URL is not None:
db_read.append("replica1")
if settings.REPLICA2_URL is not None:
db_read.append("replica2")
return random.choice(db_read)
def db_for_write(self, model, **hints):
# Always return the default database
return "default"
def allow_relation(self, obj1, obj2, **hints):
return True
def allow_migrate(self, db, app_label, model_name=None, **hints):
return True
Occasionally, django-celery-results will attempt to conduct delete_expired
using one of my replica databases:
connection: <DatabaseWrapper vendor='postgresql' alias='replica1'>
Recommend changing the using
argument of the atomic transaction in delete_expired
to explicitly use the writable database specified in the router.