django_replicated icon indicating copy to clipboard operation
django_replicated copied to clipboard

Context leakage when using decorators

Open partizaans opened this issue 5 months ago • 0 comments

Issue

We faced a strange problem. Some of the queries inside of some views that are not decorated with the @use_slave were getting routed to the slave db instances. After a couple of hours spent debugging found the reproduction routine.

Reproduce

Consider:

@use_slave
def v1(request, *args, **kwargs):
    raise Exception('!')
    ...


def v2(request, *args, **kwargs):
    print(Model2.objects.all()) # <--- Routed to the slave
    ...

Decorators are using ReplicationMiddleware but ReplicationMiddleware is not implementing process_exception and if the exception is not handled, the ReplicationMiddleware#process_response and routers.reset() are not called at all. Hence, the _context on the router remains dirty. So any v2 call that is happening after the v1 raising an exception get routed to the slave instances.

Fix

Just wrapped the django_replicated decorator just like:

def use_replicas(function_based_view):
    def inner(*args, **kwargs):
        from django_replicated.decorators import use_slave
        from django_replicated.utils import routers

        try:
            return use_slave(function_based_view)(*args, **kwargs)
        except Exception as e:
            routers.reset()
            raise e

    return inner

partizaans avatar Sep 10 '24 11:09 partizaans