Example #1
0
 def _post_teardown(self):
     _post_teardown(self)
     super(TransactionQueryCacheBase, self)._post_teardown()
     if transaction.is_dirty():
         transaction.rollback()
     if is_managed():
         managed(False)
Example #2
0
    def test_savepoint_localstore_flush(self):
        """
        This is a very simple test to see if savepoints will actually
        be committed, i.e. flushed out from localstore into cache.
        """
        transaction.enter_transaction_management()
        managed()

        TABLE_NAME = 'test_table'
        cache_backend = cache.get_backend()
        cache_backend.patch()
        keyhandler = cache_backend.keyhandler
        keygen = keyhandler.keygen

        tm = cache_backend.cache_backend

        # First, we set one key-val pair generated for our non-existing table.
        table_key = keygen.gen_table_key(TABLE_NAME)
        tm.set(table_key, 'val1')

        # Then we create a savepoint.
        # The key-value pair is moved into 'trans_sids' item of localstore.
        tm._create_savepoint('savepoint1')

        # We then commit all the savepoints (i.e. only one in this case)
        # The items stored in 'trans_sids' should be moved back to the
        # top-level dictionary of our localstore
        tm._commit_all_savepoints()
        # And this checks if it actually happened.
        self.assertTrue(table_key in tm.local)
Example #3
0
    def test_savepoint_localstore_flush(self):
        """
        This is a very simple test to see if savepoints will actually
        be committed, i.e. flushed out from localstore into cache.
        """
        transaction.enter_transaction_management()
        managed()

        TABLE_NAME = 'test_table'
        cache_backend = cache.get_backend()
        cache_backend.patch()
        keyhandler = cache_backend.keyhandler
        keygen = keyhandler.keygen
        
        tm = cache_backend.cache_backend
        
        # First, we set one key-val pair generated for our non-existing table.
        table_key = keygen.gen_table_key(TABLE_NAME)
        tm.set(table_key, 'val1')

        # Then we create a savepoint.
        # The key-value pair is moved into 'trans_sids' item of localstore.
        tm._create_savepoint('savepoint1')
        
        # We then commit all the savepoints (i.e. only one in this case)
        # The items stored in 'trans_sids' should be moved back to the
        # top-level dictionary of our localstore
        tm._commit_all_savepoints()
        # And this checks if it actually happened.
        self.assertTrue(table_key in tm.local)
Example #4
0
    def test_savepoint_rollback(self):
        """Tests rollbacks of savepoints"""
        if not connection.features.uses_savepoints or connection.vendor == 'sqlite':
            return
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        managed()

        g = Genre.objects.get(pk=1)
        start_title = g.title
        g.title = "Adventures in Savepoint World"
        g.save()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "Adventures in Savepoint World")
        sid = transaction.savepoint()
        g.title = "In the Void"
        g.save()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "In the Void")
        transaction.savepoint_rollback(sid)
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "Adventures in Savepoint World")
        transaction.rollback()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, start_title)
Example #5
0
 def _post_teardown(self):
     _post_teardown(self)
     super(TransactionQueryCacheBase, self)._post_teardown()
     if transaction.is_dirty():
         transaction.rollback()
     if is_managed():
         managed(False)
Example #6
0
    def test_savepoint_rollback(self):
        """Tests rollbacks of savepoints"""
        if not connection.features.uses_savepoints:
            return
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        managed()
        transaction.enter_transaction_management()

        g = Genre.objects.get(pk=1)
        start_title = g.title
        g.title = "Adventures in Savepoint World"
        g.save()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "Adventures in Savepoint World")
        sid = transaction.savepoint()
        g.title = "In the Void"
        g.save()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "In the Void")
        transaction.savepoint_rollback(sid)
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, "Adventures in Savepoint World")
        transaction.rollback()
        g = Genre.objects.get(pk=1)
        self.assertEqual(g.title, start_title)
Example #7
0
    def test_transaction_rollback(self):
        """Tests johnny's handling of transaction rollbacks.

        Similar to the commit, this sets up a write to a db in a transaction,
        reads from it (to force a cache write of sometime), then rolls back."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)

        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        # perform a READ inside the transaction;  this should hit the localstore
        # but not the outside!
        nowlen = len(cache.local)
        start2 = Genre.objects.get(id=1)
        self.assertEqual(start2.title, start.title)
        self.assertTrue(len(cache.local) > nowlen)
        transaction.rollback()
        # we rollback, and flush all johnny keys related to this transaction
        # subsequent gets should STILL hit the cache in the other thread
        # and indeed, in this thread.

        self.assertFalse(transaction.is_dirty())
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        start = Genre.objects.get(id=1)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Example #8
0
    def test_transaction_rollback(self):
        """Tests johnny's handling of transaction rollbacks.

        Similar to the commit, this sets up a write to a db in a transaction,
        reads from it (to force a cache write of sometime), then rolls back."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)

        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        # perform a READ inside the transaction;  this should hit the localstore
        # but not the outside!
        nowlen = len(cache.local)
        start2 = Genre.objects.get(id=1)
        self.assertEqual(start2.title, start.title)
        self.assertTrue(len(cache.local) > nowlen)
        transaction.rollback()
        # we rollback, and flush all johnny keys related to this transaction
        # subsequent gets should STILL hit the cache in the other thread
        # and indeed, in this thread.

        self.assertFalse(transaction.is_dirty())
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        start = Genre.objects.get(id=1)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Example #9
0
    def test_transaction_commit(self):
        """Test transaction support in Johnny."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)
        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        transaction.commit()
        # now that we commit, we push the localstore keys out;  this should be
        # a cache miss, because we never read it inside the previous transaction
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertFalse(hit)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Example #10
0
    def test_transaction_commit(self):
        """Test transaction support in Johnny."""
        if not is_multithreading_safe(db_using='default'):
            print("\n  Skipping test requiring multiple threads.")
            return

        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        cache.local.clear()
        q = Queue()
        other = lambda x: self._run_threaded(x, q)
        # load some data
        start = Genre.objects.get(id=1)
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        # these should be the same and should have hit cache
        self.assertTrue(hit)
        self.assertEqual(ostart, start)
        # enter manual transaction management
        transaction.enter_transaction_management()
        managed()
        start.title = 'Jackie Chan Novels'
        # local invalidation, this key should hit the localstore!
        nowlen = len(cache.local)
        start.save()
        self.assertNotEqual(nowlen, len(cache.local))
        # perform a read OUTSIDE this transaction... it should still see the
        # old gen key, and should still find the "old" data
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertNotEqual(ostart.title, start.title)
        transaction.commit()
        # now that we commit, we push the localstore keys out;  this should be
        # a cache miss, because we never read it inside the previous transaction
        other('Genre.objects.get(id=1)')
        hit, ostart = q.get()
        self.assertFalse(hit)
        self.assertEqual(ostart.title, start.title)
        managed(False)
        transaction.leave_transaction_management()
Example #11
0
 def test_savepoint_commit(self):
     """Tests a transaction commit (release)
     The release actually pushes the savepoint back into the dirty stack,
     but at the point it was saved in the transaction"""
     if not connection.features.uses_savepoints:
         return
     self.assertFalse(is_managed())
     self.assertFalse(transaction.is_dirty())
     cache.local.clear()
     transaction.enter_transaction_management()
     managed()
     g = Genre.objects.get(pk=1)
     start_title = g.title
     g.title = "Adventures in Savepoint World"
     g.save()
     g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "Adventures in Savepoint World")
     sid = transaction.savepoint()
     g.title = "In the Void"
     g.save()
     #should be a database hit because of save in savepoint
     with self.assertNumQueries(1):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     transaction.savepoint_commit(sid)
     #should be a cache hit against the dirty store
     with self.assertNumQueries(0):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     transaction.commit()
     #should have been pushed up to cache store
     with self.assertNumQueries(0):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     managed(False)
     transaction.leave_transaction_management()
Example #12
0
 def test_savepoint_commit(self):
     """Tests a transaction commit (release)
     The release actually pushes the savepoint back into the dirty stack,
     but at the point it was saved in the transaction"""
     if not connection.features.uses_savepoints:
         return
     self.assertFalse(is_managed())
     self.assertFalse(transaction.is_dirty())
     cache.local.clear()
     transaction.enter_transaction_management()
     managed()
     g = Genre.objects.get(pk=1)
     start_title = g.title
     g.title = "Adventures in Savepoint World"
     g.save()
     g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "Adventures in Savepoint World")
     sid = transaction.savepoint()
     g.title = "In the Void"
     g.save()
     #should be a database hit because of save in savepoint
     with self.assertNumQueries(1):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     transaction.savepoint_commit(sid)
     #should be a cache hit against the dirty store
     with self.assertNumQueries(0):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     transaction.commit()
     #should have been pushed up to cache store
     with self.assertNumQueries(0):
         g = Genre.objects.get(pk=1)
     self.assertEqual(g.title, "In the Void")
     managed(False)
     transaction.leave_transaction_management()
Example #13
0
 def tearDown(self):
     if is_managed():
         if transaction.is_dirty():
             transaction.rollback()
         managed(False)
         transaction.leave_transaction_management()
Example #14
0
 def setUp(self):
     super(TransactionSupportTest, self).setUp()
     managed(False)
Example #15
0
    def test_savepoints(self):
        """tests savepoints for multiple db's"""
        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for name, db in settings.DATABASES.items():
            con = connections[name]
            if not con.features.uses_savepoints:
                print("\n  Skipping test requiring savepoints.")
                return

        # sanity check 
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        g1 = Genre.objects.using("default").get(pk=1)
        start_g1 = g1.title
        g2 = Genre.objects.using("second").get(pk=1)

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Rollback savepoint"
        g1.save()

        g2.title = "Committed savepoint"
        g2.save(using="second")
        sid2 = transaction.savepoint(using="second")

        sid = transaction.savepoint(using="default")
        g1.title = "Dirty text"
        g1.save()

        #other thread should see the original key and cache object from memcache,
        #not the local cache version
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)
        #should not be a hit due to rollback
        transaction.savepoint_rollback(sid, using="default")
        g1 = Genre.objects.using("default").get(pk=1)

        # i think it should be "Rollback Savepoint" here
        self.assertEqual(g1.title, start_g1)

        #will be pushed to dirty in commit
        g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")
        transaction.savepoint_commit(sid2, using="second")

        #other thread should still see original version even 
        #after savepoint commit
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        transaction.commit(using="second")
        managed(False, using='second')

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")

        #now committed and cached, other thread should reflect new title
        #without a hit to the db
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        managed(False, 'default')
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Example #16
0
 def tearDown(self):
     if is_managed():
         if transaction.is_dirty():
             transaction.rollback()
         managed(False)
Example #17
0
 def tearDown(self):
     if is_managed():
         managed(False)
Example #18
0
 def tearDown(self):
     if is_managed():
         managed(False)
Example #19
0
    def test_savepoints(self):
        """tests savepoints for multiple db's"""
        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for name, db in settings.DATABASES.items():
            con = connections[name]
            if not con.features.uses_savepoints:
                print("\n  Skipping test requiring savepoints.")
                return

        # sanity check
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        g1 = Genre.objects.using("default").get(pk=1)
        start_g1 = g1.title
        g2 = Genre.objects.using("second").get(pk=1)
        start_g2 = g2.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Rollback savepoint"
        g1.save()

        g2.title = "Committed savepoint"
        g2.save(using="second")
        sid2 = transaction.savepoint(using="second")

        sid = transaction.savepoint(using="default")
        g1.title = "Dirty text"
        g1.save()

        #other thread should see the original key and cache object from memcache,
        #not the local cache version
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g1)
        #should not be a hit due to rollback
        transaction.savepoint_rollback(sid, using="default")
        g1 = Genre.objects.using("default").get(pk=1)

        # i think it should be "Rollback Savepoint" here
        self.assertEqual(g1.title, start_g1)

        #will be pushed to dirty in commit
        g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")
        transaction.savepoint_commit(sid2, using="second")

        #other thread should still see original version even
        #after savepoint commit
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertTrue(hit)
        self.assertEqual(ostart.title, start_g2)

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        transaction.commit(using="second")
        managed(False, using='second')

        with self.assertNumQueries(0, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)
        self.assertEqual(g2.title, "Committed savepoint")

        #now committed and cached, other thread should reflect new title
        #without a hit to the db
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        transaction.commit(using="default")
        managed(False, 'default')
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Example #20
0
 def setUp(self):
     super(TransactionSupportTest, self).setUp()
     if is_managed():
         managed(False)
Example #21
0
    def test_transactions(self):
        """Tests transaction rollbacks and local cache for multiple dbs"""

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for conname in connections:
            con = connections[conname]
            if not base.supports_transactions(con):
                print("\n  Skipping test requiring transactions.")
                return

        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})


        # sanity check 
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        # this should seed this fetch in the global cache
        g1 = Genre.objects.using("default").get(pk=1)
        g2 = Genre.objects.using("second").get(pk=1)
        start_g1 = g1.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Testing a rollback"
        g2.title = "Testing a commit"
        g1.save()
        g2.save()

        # test outside of transaction, should be cache hit and 
        # not contain the local changes
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        transaction.rollback(using='default')
        transaction.commit(using='second')
        managed(False, using='default')
        managed(False, using='second')

        #other thread should have seen rollback
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        #should be a cache hit due to rollback
        with self.assertNumQueries(0, using='default'):
            g1 = Genre.objects.using("default").get(pk=1)
        #should be a db hit due to commit
        with self.assertNumQueries(1, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        #other thread sould now be accessing the cache after the get
        #from the commit.
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        self.assertEqual(g1.title, start_g1)
        self.assertEqual(g2.title, "Testing a commit")
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")
Example #22
0
    def test_transactions(self):
        """Tests transaction rollbacks and local cache for multiple dbs"""

        if len(getattr(settings, "DATABASES", [])) <= 1:
            print("\n  Skipping multi database tests")
            return

        if not is_multithreading_safe():
            print("\n  Skipping test requiring multiple threads.")
            return

        for conname in connections:
            con = connections[conname]
            if not base.supports_transactions(con):
                print("\n  Skipping test requiring transactions.")
                return

        q = Queue()
        other = lambda x: self._run_threaded(x, q, {'Genre': Genre})

        # sanity check
        self.assertFalse(is_managed())
        self.assertFalse(transaction.is_dirty())
        self.assertTrue("default" in getattr(settings, "DATABASES"))
        self.assertTrue("second" in getattr(settings, "DATABASES"))

        # this should seed this fetch in the global cache
        g1 = Genre.objects.using("default").get(pk=1)
        g2 = Genre.objects.using("second").get(pk=1)
        start_g1 = g1.title

        transaction.enter_transaction_management(using='default')
        managed(using='default')
        transaction.enter_transaction_management(using='second')
        managed(using='second')

        g1.title = "Testing a rollback"
        g2.title = "Testing a commit"
        g1.save()
        g2.save()

        # test outside of transaction, should be cache hit and
        # not contain the local changes
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        transaction.rollback(using='default')
        transaction.commit(using='second')
        managed(False, using='default')
        managed(False, using='second')

        #other thread should have seen rollback
        other("Genre.objects.using('default').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, start_g1)
        self.assertTrue(hit)

        #should be a cache hit due to rollback
        with self.assertNumQueries(0, using='default'):
            g1 = Genre.objects.using("default").get(pk=1)
        #should be a db hit due to commit
        with self.assertNumQueries(1, using='second'):
            g2 = Genre.objects.using("second").get(pk=1)

        #other thread sould now be accessing the cache after the get
        #from the commit.
        other("Genre.objects.using('second').get(pk=1)")
        hit, ostart = q.get()
        self.assertEqual(ostart.title, g2.title)
        self.assertTrue(hit)

        self.assertEqual(g1.title, start_g1)
        self.assertEqual(g2.title, "Testing a commit")
        transaction.leave_transaction_management("default")
        transaction.leave_transaction_management("second")