Okay, I guess I have fixed it. I say I guess because the solution between my app and a simple test scenario is different. The new test scenario is here:


https://gist.github.com/1366878


Basically the same as before, but now you can vary between using Transaction or SQLAlchemy directly with the two vars at the beginning. What happens is the following:

* The test case in gist:
    - works fine if called standalone and transaction.abort() is not called
- if transaction.abort() is called then the models loaded in outer transaction are expired - if called as Pyramid view (ie. by starting paster serve development.ini) and transaction.abort() is not called, it hangs (using unchanged development.ini as given by pyramid_routesalchemy template)

* My app:
- if transaction.abort() is called, it behaves the same as test case: models are expired, reloading required - if transaction.abort() is NOT called, then InvalidRequestError is issued by SQLAlchemy because of "previous exception during flush". I am not quite sure why it happens in my app and not in the test case.


Solution in my app:

    call session.rollback() instead of transaction.abort()

I have also removed transaction.commit() in the middle of view and am using session.flush() exclusively, now along with session.rollback().



Why I didn't think of this earlier? Transaction complains if you use session.commit() or session.begin_nested() directly, wants you to use transaction.commit() and transaction.savepoint() instead and it just didn't occur to me to try session.rollback() nevertheless (and in my mind transaction.abort() == session.rollback() which now I see is NOT the same), and trying savepoint.rollback() fails, I assumed session.rollback() was called by Transaction since the SQL debug output clearly shows savepoint rollback being emitted, so I went to search for another solution.

Aside from me being silly for not trying this before (and it is even suggested by the InvalidRequestError!), it is a bit illogical to have to use transaction.savepoint() and then use session.rollback() instead of savepoint.rollback().

I am still not sure if using session.rollback() manually is the right solution. My app didn't fail this time, the SQL debug output shows everything as expected (savepoint issued, savepoint rolled back, outer transaction committing without failure and without the need to reload models after rollback) and I still have to test a dozen other parts of the code where IntegrityError handling is being done. I also have to test the scenario where I explicitly must commit the transaction several times in the life of a Pyramid request.

If it matters, relevant pip freeze for the virtualenv used:

Chameleon==2.5.1
Jinja2==2.6
Mako==0.5.0
MarkupSafe==0.15
PIL==1.1.7
Paste==1.7.5.1
PasteDeploy==1.5.0
PasteScript==1.7.4.2
Pygments==1.4
SQLAlchemy==0.7.3
WebOb==1.1.1
WebTest==1.3.1
colander==0.9.3
elementtree==1.2.7-20070827-preview
iso8601==0.1.4
peppercorn==0.3
psycopg2==2.4.2
pyramid==1.2.1
pyramid-debugtoolbar==0.9.4
pyramid-jinja2==1.2
pyramid-tm==0.3
repoze.lru==0.4
requests==0.6.1
simplejson==2.2.1
transaction==1.1.1
translationstring==0.4
venusian==1.0a1
wsgiref==0.1.2
zope.component==3.11.0
zope.deprecation==3.5.0
zope.event==3.5.1
zope.interface==3.8.0
zope.sqlalchemy==0.6.1

Thanks! ;)



.oO V Oo.


On 11/15/2011 05:42 AM, Chris McDonough wrote:
OK.  So I think if we can understand (and fix, if necessary) the
savepoint issue, Vlad will be able to do everything he could do without
zope.sqla in a very similar way then.

- C



--
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to pylons-discuss@googlegroups.com.
To unsubscribe from this group, send email to 
pylons-discuss+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en.

Reply via email to