On Thursday, 9 October 2014 16:51:49 UTC+1, Michael Bayer wrote:
>
>
> On Oct 9, 2014, at 6:09 AM, Tom Dalton <tom.d...@fanduel.com <javascript:>> 
> wrote: 
>
> > Using SQLAlchemy 0.9. 
> > 
> > I am writing a server, that's running in gevent. As part of the library 
> code, I am trying to write a session context manager that checks if the 
> session has uncommitted changes when it's exited (this situation represents 
> a logic/programming error, as I expect every server 'request' to finish 
> with a committed or rolled back transaction. Each request has its own 
> session but there may be multiple transactions within that request/session. 
> > 
> > Based on the docs for Session and this question at stackoverflow (
> http://stackoverflow.com/questions/13910576/find-out-how-many-uncommitted-items-are-in-the-session)
>  
> I wrote a context manager like so: 
> > 
> > @contextmanager 
> > def checked_scoped_session(): 
> >     session = get_session() 
> >     try: 
> >         yield session 
> >     except: 
> >         session.rollback() 
> >         raise 
> >     finally: 
> >         if session.new or session.dirty or session.deleted: 
> >             new = len(session.new) 
> >             dirty = len(session.dirty) 
> >             deleted = len(session.deleted) 
> >             msg = "Session left with ({} new, {} dirty, {} deleted) 
> instances"\ 
> >                 " uncommitted".format(new, dirty, deleted) 
> >             raise SessionLeftUnclean(msg) 
> >         session.close() 
> > 
> > While testing, I discovered that session.new, .dirty and .deleted appear 
> to actually be UNFLUSHED instances, and not uncommitted. This is a problem 
> since I am using (and want to keep using) autoflush. I have been reading up 
> on session.transaction, however, it's still not clear to me how I can tell 
> if the transaction has (uncommitted) changes, and this seems to be further 
> complicated by the possibility of sub-transactions. 
> > 
> > Is there an easy way to do what I want? E.g. Ideally I want to do: 
>
> Checking .new, .dirty, and .deleted is not a bad idea because they 
> indicate activity that has occurred on the session subsequent to the last 
> commit().    But if these changes have been flushed, then it’s “clean”, but 
> the transaction may not have been committed yet.   Right now the 
> documentation encourages just using events (eg. after_begin, after_commit, 
> after_rollback) to track the state of the Session regarding connections as 
> you see fit, there’s not a public API method of checking this.   
>
> If you really want to see if the session is linked to a transaction in 
> progress, you could check len(session.transaction._connections), if that’s 
> nonzero, then there’s a DBAPI-level transaction in progress - it means 
> there’s one or more connections that the Session is linked to.   But you 
> could achieve this same information using after_begin as well. 
>

Thanks for the reply. I saw the session transaction events stuff but I'm 
not sure that they help me (correct me if I'm wrong). I believe a 
transaction will exist if I run *any* query, not just one that modifies 
data. Also, the docs imply that a session will effectively always have a 
transaction when using autoflush mode. Finally, the after_begin event only 
fires once. So I'd have no way to tell the difference between the session 
state after the following 3 scenarios:

1. (implicit) begin, select, update, select, (autoflush)
2. (implicit) begin, select, (autoflush)
3. (implicit) begin, select

In my use case, I want to detect the uncommitted (but flushed) changes and 
throw an error, but cases 2 and 3 are 'ok'.

Even disabling autoflush doesn't help, since I'd still be unable to tell if 
the (erroneous/buggy) code had done an explicit flush without a subsequent 
rollback or commit.

I'm feeling a bit stuck, but I assume this information must exist in 
SQLAlchemy somewhere, since if you do:

4. (implicit) begin, select X, update X, flush, rollback

then SQLAlchemy must 'know' which instance's (flushed) changes have been 
rolled back in order to change those instances' state (I think in the above 
example, it would mark X as detached?). The problem is I don't know where 
or how it's maintaining that info...

Any more ideas?

Tom

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to