[Checkins] SVN: z3c.zalchemy/trunk/src/z3c/zalchemy/ Changed how the two phase commit works.

Jürgen Kartnaller juergen at kartnaller.at
Sun Mar 11 16:04:02 EDT 2007


Log message for revision 73142:
  Changed how the two phase commit works.
  
  This is how the two phase commit is used in zope.
  
      1. tpc_begin(txn)
      2. commit(txn)
      3. tpc_vote(txn)
      4. tpc_finish(txn)
  
  What zalchemy is doing:
  
    - commit does a session.flush() which actually executes all sql statements.
    - tpc_finish() does a transaction.commit() in the sqlalchemy transaction
    - tpc_abort() does a transaction.rollback() in the sqlalchemy transaction
  
  If commit fails or another DataManager fails, data is not commited to the
  database.
  
  Thanks to Michael Bayer (the author of sqlalchemy) who gave me the hint to
  integrate sqlalchemy correctly into the two phase commit.
  
  

Changed:
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/README.txt
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/datamanager.py
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/tests/TRANSACTION.txt

-=-
Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/README.txt
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/README.txt	2007-03-11 17:56:47 UTC (rev 73141)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/README.txt	2007-03-11 20:04:02 UTC (rev 73142)
@@ -10,7 +10,23 @@
 transaction into the Zope transaction.  This is solved by using a data manager
 which joins the Zope transaction for every newly created thread.
 
+zalchemy uses the two phase commit system from zope.
 
+This is how the two phase commit is used in zope.
+
+    1. tpc_begin(txn)
+    2. commit(txn)
+    3. tpc_vote(txn)
+    4. tpc_finish(txn)
+
+  - commit does a session.flush() which actually executes all sql statements.
+  - tpc_finish() does a transaction.commit() in the sqlalchemy transaction
+  - tpc_abort() does a transaction.rollback() in the sqlalchemy transaction
+
+If commit fails or another DataManager fails data is not commited to the
+database.
+
+
 Important
 =========
 

Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/datamanager.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/datamanager.py	2007-03-11 17:56:47 UTC (rev 73141)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/datamanager.py	2007-03-11 20:04:02 UTC (rev 73142)
@@ -176,6 +176,8 @@
     """
     implements(IDataManager)
 
+    _commitFailed = False
+
     def __init__(self, session):
         self.session = session
         self.transaction = session.create_transaction()
@@ -188,12 +190,13 @@
         pass
 
     def commit(self, trans):
-        self.transaction.commit()
+        self.session.flush()
 
     def tpc_vote(self, trans):
         pass
 
     def tpc_finish(self, trans):
+        self.transaction.commit()
         _dataManagerFinished()
 
     def tpc_abort(self, trans):

Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/tests/TRANSACTION.txt
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/tests/TRANSACTION.txt	2007-03-11 17:56:47 UTC (rev 73141)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/tests/TRANSACTION.txt	2007-03-11 20:04:02 UTC (rev 73142)
@@ -156,3 +156,48 @@
   >>> a.value == v
   True
 
+
+Two Phase Commit With Errors
+----------------------------
+
+zalchemy uses zope's two phase commit by first doing only a flush when commit
+is called. SQLAlchemy's transaction is commited in the second phase of the
+zope transacion.
+
+  >>> session = z3c.zalchemy.getSession(True)
+  >>> aa=A()
+  >>> session.save(aa)
+  >>> aa.value = 3
+
+We create an object with an already existing primary key.
+
+  >>> aa.id = 2
+
+Let's make sure we get an exception when using commit.
+
+  >>> from z3c.zalchemy.datamanager import _storage
+  >>> _storage.dataManager.commit(transaction.manager.get())
+  Traceback (most recent call last):
+  ...
+  SQLError: (IntegrityError) PRIMARY KEY must be unique 'INSERT INTO table2 (id, value) VALUES (?, ?)' [2, 3]
+
+Finally we need to do an abort zope's transaction.
+
+  >>> transaction.abort()
+
+And we do the same using the commit from the transaction.
+
+  >>> session = z3c.zalchemy.getSession(True)
+  >>> aa=A()
+  >>> session.save(aa)
+  >>> aa.value = 3
+  >>> aa.id = 2
+  >>> transaction.commit()
+  Traceback (most recent call last):
+  ...
+  SQLError: (IntegrityError) PRIMARY KEY must be unique 'INSERT INTO table2 (id, value) VALUES (?, ?)' [2, 3]
+
+We need to manually abort the transaction.
+
+  >>> transaction.abort()
+



More information about the Checkins mailing list