Skip to content

Commit

Permalink
Add a StickyMasterSlaveRouter that pins a request to the master after…
Browse files Browse the repository at this point in the history
… a write.
  • Loading branch information
James Socol committed Jun 11, 2010
1 parent 8eeef71 commit 9fe1baa
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions multidb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import random

from django.conf import settings
from django.utils.thread_support import currentThread
from django.core.signals import post_save, post_delete, request_started


DEFAULT_DB_ALIAS = 'default'
Expand All @@ -53,6 +55,29 @@ def get_slave():
return slaves.next()


_requests = {}


def get_written():
return _requests.get(currentThread())


def set_written():
_requests[currentThread()] = True


def clear_written():
try:
del _requests[currentThread()]
except KeyError:
pass


request_started.connections(clear_written)
post_save.connect(set_written)
post_delete.connect(set_written)


class MasterSlaveRouter(object):
"""Router that sends all reads to a slave, all writes to default."""

Expand All @@ -71,3 +96,16 @@ def allow_relation(self, obj1, obj2, **hints):
def allow_syncdb(self, db, model):
"""Only allow syncdb on the master."""
return db == DEFAULT_DB_ALIAS


class StickyMasterSlaveRouter(MasterSlaveRouter):
"""Sends all reads to a slave unless there has already been a write,
then sends reads to the master for the remainder of the request."""

def db_for_read(self, model, **hints):
"""Send reads to slaves in round-robin, unless there has been a
write."""

if get_written():
return DEFAULT_DB_ALIAS
return get_slave()

0 comments on commit 9fe1baa

Please sign in to comment.