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.