Re: [sqlalchemy] session lifecycle and wsgi

2010-05-04 Thread Chris Withers

Michael Bayer wrote:


(I'm guessing session.merge will whine if handed an object that is 
already in another session?)


mm no merge() leaves the original unaffected.  it copies state to an 
instance internal to the session.   this is very clear here: 
 http://www.sqlalchemy.org/docs/session.html#merging


Gotcha.

So putting non-expunged objects in something like a beaker cache would 
be a no-no, correct? (would .close() or .remove() fix the problem if 
the objects are already in the cache by the time the .close() or 
.remove() is called?)


in most cases its actually fine.file, memcached, reldb, dbm backends 
all serialize the given object, which means you're only storing a copy. 
   If the cache is storing things locally to the current session (see 
examples/beaker_cache/local_session_caching.py), then you dont want to 
expunge the object since you'd like it to be in the session at the same 
time.  only in-memory, non-session-scoped caches have this limitation, 
such as if you were using a memory backend with beaker.


OK, thanks. Where can I find good examples of the various ways Beaker 
can be used with a multi-threaded wsgi app?


Does the ORM check if the attributes of the cached object are correct 
or would you end up in a situation where you do a query but end up 
using the cached attributes rather than the ones just returned from 
the db?


that all depends how you get the object from a cache back into your 
session.usually not since having to hit the DB to verify attributes 
defeats the purpose of a cache.   pretty much only if you used merge() 
with load=True.


I wasn't quite clear, let me try again. So, I've merged an object with 
load=False. I then do a session.query(ThatObjectsClass).all() which 
should include that object. Will the object have the correct attributes 
or the stale cached ones?


- They don't explain what happens to transactions and connections. The 
points for both remove() and close() say all of its 
transactional/connection resources are closed out; does this mean 
database connections or closed or just returned to the pool? (I hope 
the latter!)


closed out means rolled back and returned to thoe pool.



- The point for .commit() states The full state of the session is 
expired, so that when the next web request is started, all data will 
be reloaded but your last reply implied this wouldn't always be the case.


The instantiated objects that are in the session still stay around as 
long as they are referenced externally.  but all their attributes are 
gone, as well as the new and deleted collections are empty.   so all 
data will be reloaded.




Also, is it fair game to assume that session.close() rolls back any 
open database transaction? Is there any difference between that 
rollback and calling session.rollback() explicitly?


i think the rollback which close() might get to the point more directly 
internallybut from a connection point of view there's no different.


Thanks for the clarification :-)

Finally, in nosing around session.py, I notice that 
SessionTransactions can be used as context managers. Where can I find 
good examples of this?


you'd be saying with session.begin():


...and then the session would be committed or rolled back depending on 
whether an exception was raised in the with block or not?


If so, cool :-)

Chris

--
Simplistix - Content Management, Batch Processing  Python Consulting
- http://www.simplistix.co.uk

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-05-04 Thread Michael Bayer

On May 4, 2010, at 1:59 PM, Chris Withers wrote:

 So putting non-expunged objects in something like a beaker cache would be a 
 no-no, correct? (would .close() or .remove() fix the problem if the objects 
 are already in the cache by the time the .close() or .remove() is called?)
 in most cases its actually fine.file, memcached, reldb, dbm backends all 
 serialize the given object, which means you're only storing a copy.If 
 the cache is storing things locally to the current session (see 
 examples/beaker_cache/local_session_caching.py), then you dont want to 
 expunge the object since you'd like it to be in the session at the same 
 time.  only in-memory, non-session-scoped caches have this limitation, such 
 as if you were using a memory backend with beaker.
 
 OK, thanks. Where can I find good examples of the various ways Beaker can be 
 used with a multi-threaded wsgi app?

those *are* the examples ...  examples/beaker_cache.   multithreaded doesn't 
change any of the code

 
 Does the ORM check if the attributes of the cached object are correct or 
 would you end up in a situation where you do a query but end up using the 
 cached attributes rather than the ones just returned from the db?
 that all depends how you get the object from a cache back into your session. 
usually not since having to hit the DB to verify attributes defeats the 
 purpose of a cache.   pretty much only if you used merge() with load=True.
 
 I wasn't quite clear, let me try again. So, I've merged an object with 
 load=False. I then do a session.query(ThatObjectsClass).all() which should 
 include that object. Will the object have the correct attributes or the stale 
 cached ones?

it will have whatever you merged in from the outside (yes, the cache).  
merge(load=False) copies the incoming attributes unconditionally.  whatever 
attributes aren't present on the incoming will be loaded from the DB when 
accessed.

 
 - They don't explain what happens to transactions and connections. The 
 points for both remove() and close() say all of its 
 transactional/connection resources are closed out; does this mean database 
 connections or closed or just returned to the pool? (I hope the latter!)
 closed out means rolled back and returned to thoe pool.
 
 - The point for .commit() states The full state of the session is expired, 
 so that when the next web request is started, all data will be reloaded 
 but your last reply implied this wouldn't always be the case.
 The instantiated objects that are in the session still stay around as long 
 as they are referenced externally.  but all their attributes are gone, as 
 well as the new and deleted collections are empty.   so all data will be 
 reloaded.
 
 Also, is it fair game to assume that session.close() rolls back any open 
 database transaction? Is there any difference between that rollback and 
 calling session.rollback() explicitly?
 i think the rollback which close() might get to the point more directly 
 internallybut from a connection point of view there's no different.
 
 Thanks for the clarification :-)
 
 Finally, in nosing around session.py, I notice that SessionTransactions can 
 be used as context managers. Where can I find good examples of this?
 you'd be saying with session.begin():
 
 ...and then the session would be committed or rolled back depending on 
 whether an exception was raised in the with block or not?

well, it wouldn't be very useful if it didn't check for an exception, so yes, 
it does what you'd expect.


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



Re: [sqlalchemy] session lifecycle and wsgi

2010-05-02 Thread Michael Bayer

On Apr 29, 2010, at 3:21 AM, Chris Withers wrote:

 Michael Bayer wrote:
 if your application keeps a handle on objects after the request is
 complete, and then passed them somewhere else, like a background thread or
 something, then the subsequent request is going to be potentially touching
 those objects at the same time.  This would all be pretty poor practice as
 individual threads should always have their own sessions.
 
 Right, you should either be .close() or .remove()'ing the session here or 
 manually expunging the objects you want to shift to the other thread, correct?
 
 (I'm guessing session.merge will whine if handed an object that is already in 
 another session?)

mm no merge() leaves the original unaffected.  it copies state to an instance 
internal to the session.   this is very clear here:  
http://www.sqlalchemy.org/docs/session.html#merging

 
 Or maybe you
 loaded those objects into a globally-scoped in-memory cache of some kind -
 you probably don't want the next request touching them directly as once
 they're in a global cache of some kind, other threads would be calling
 upon them to copy their state locally.
 
 So putting non-expunged objects in something like a beaker cache would be a 
 no-no, correct? (would .close() or .remove() fix the problem if the objects 
 are already in the cache by the time the .close() or .remove() is called?)

in most cases its actually fine.file, memcached, reldb, dbm backends all 
serialize the given object, which means you're only storing a copy.If the 
cache is storing things locally to the current session (see 
examples/beaker_cache/local_session_caching.py), then you dont want to expunge 
the object since you'd like it to be in the session at the same time.  only 
in-memory, non-session-scoped caches have this limitation, such as if you were 
using a memory backend with beaker.


 
 On the other hand, you might load the objects into a session-local cache
 of some kind that you've created.Now, when the next request comes in
 and calls upon those same rows, the ORM doesn't need to re-instantiate the
 objects, they are already present in the cache.
 
 Does the ORM check if the attributes of the cached object are correct or 
 would you end up in a situation where you do a query but end up using the 
 cached attributes rather than the ones just returned from the db?

that all depends how you get the object from a cache back into your session.
usually not since having to hit the DB to verify attributes defeats the purpose 
of a cache.   pretty much only if you used merge() with load=True.

 
 This is a use case
 where you'd want to keep the same session from one request to the next.  
 
 It looks like this is what zope.sqlalchemy does. The last thing it does in a 
 logical transaction (ie: a http://pypi.python.org/pypi/transaction 
 transaction) is call .close().
 Should it be calling .remove()? 
 http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-session 
 would seem to imply that the .close() alone is fine?

close() alone should be fine. 

 
 the bulletpoints at
 http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-session
 are the best I can do here, I'm really just repeating myself over and over
 in these threads
 
 Well, except the info you've given in this thread, at least, goes way above 
 what's in that list ;-)
 
 A few comments on the bullets:
 
 - They don't explain what happens to transactions and connections. The points 
 for both remove() and close() say all of its transactional/connection 
 resources are closed out; does this mean database connections or closed or 
 just returned to the pool? (I hope the latter!)

closed out means rolled back and returned to thoe pool.

 
 - The point for .commit() states The full state of the session is expired, 
 so that when the next web request is started, all data will be reloaded but 
 your last reply implied this wouldn't always be the case.

The instantiated objects that are in the session still stay around as long as 
they are referenced externally.  but all their attributes are gone, as well as 
the new and deleted collections are empty.   so all data will be reloaded.

 
 Also, is it fair game to assume that session.close() rolls back any open 
 database transaction? Is there any difference between that rollback and 
 calling session.rollback() explicitly?

i think the rollback which close() might get to the point more directly 
internallybut from a connection point of view there's no different.

 
 Finally, in nosing around session.py, I notice that SessionTransactions can 
 be used as context managers. Where can I find good examples of this?

you'd be saying with session.begin():

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For 

Re: [sqlalchemy] session lifecycle and wsgi

2010-04-29 Thread Chris Withers

Michael Bayer wrote:

if your application keeps a handle on objects after the request is
complete, and then passed them somewhere else, like a background thread or
something, then the subsequent request is going to be potentially touching
those objects at the same time.  This would all be pretty poor practice as
individual threads should always have their own sessions.


Right, you should either be .close() or .remove()'ing the session here 
or manually expunging the objects you want to shift to the other thread, 
correct?


(I'm guessing session.merge will whine if handed an object that is 
already in another session?)



Or maybe you
loaded those objects into a globally-scoped in-memory cache of some kind -
you probably don't want the next request touching them directly as once
they're in a global cache of some kind, other threads would be calling
upon them to copy their state locally.


So putting non-expunged objects in something like a beaker cache would 
be a no-no, correct? (would .close() or .remove() fix the problem if the 
objects are already in the cache by the time the .close() or .remove() 
is called?)



On the other hand, you might load the objects into a session-local cache
of some kind that you've created.Now, when the next request comes in
and calls upon those same rows, the ORM doesn't need to re-instantiate the
objects, they are already present in the cache.


Does the ORM check if the attributes of the cached object are correct or 
would you end up in a situation where you do a query but end up using 
the cached attributes rather than the ones just returned from the db?



This is a use case
where you'd want to keep the same session from one request to the next.  


It looks like this is what zope.sqlalchemy does. The last thing it does 
in a logical transaction (ie: a 
http://pypi.python.org/pypi/transaction transaction) is call .close().
Should it be calling .remove()? 
http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-session 
would seem to imply that the .close() alone is fine?



the bulletpoints at
http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-session
are the best I can do here, I'm really just repeating myself over and over
in these threads


Well, except the info you've given in this thread, at least, goes way 
above what's in that list ;-)


A few comments on the bullets:

- They don't explain what happens to transactions and connections. The 
points for both remove() and close() say all of its 
transactional/connection resources are closed out; does this mean 
database connections or closed or just returned to the pool? (I hope the 
latter!)


- The point for .commit() states The full state of the session is 
expired, so that when the next web request is started, all data will be 
reloaded but your last reply implied this wouldn't always be the case.


Also, is it fair game to assume that session.close() rolls back any open 
database transaction? Is there any difference between that rollback and 
calling session.rollback() explicitly?


Finally, in nosing around session.py, I notice that SessionTransactions 
can be used as context managers. Where can I find good examples of this?


Chris

--
Simplistix - Content Management, Batch Processing  Python Consulting
   - http://www.simplistix.co.uk

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



RE: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread King Simon-NFHD78
 -Original Message-
 From: sqlalchemy@googlegroups.com 
 [mailto:sqlalch...@googlegroups.com] On Behalf Of Chris Withers
 Sent: 28 April 2010 14:37
 To: sqlalchemy@googlegroups.com
 Subject: [sqlalchemy] session lifecycle and wsgi
 
 Hi All,
 
 I'm still trying to get an answer on this...
 
 Am I right in understanding that the basic session lifecycle 
 should be:
 
 try:
  use session
  session.commit()
 except:
 log()
 session.rollback()
 finally:
 session.remove()
 
 The structure I've traditionally used with transactions has been:
 
 try:
  use session
 except:
 log()
 session.rollback()
 else:
 session.commit()
 
 Is this okay? Why would the first setup be preferable?
 (ie: what's wrong with my location of the commit() call?)
 What happens when the remove() call is omitted()?
 

Have you read
http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-ses
sion - it describes typical usage of a scoped session in a web
application.

In your traditional structure, you could get an exception during
session.commit() which would not be handled in your exception handler. I
believe (but I'm not certain) that after any kind of database exception,
it is recommended that you roll back the existing transaction, as it is
likely to be invalid anyway.

Session.remove() ensures that the current session is removed from the
scoped session registry. If you don't do this, I think that the next
time this thread calls Session(), it'll get the old session back again,
rather than creating a new one.

Simon

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Diana Clarke
Hi Chris:

I'm a bit hesitant to share what I've done, b/c it's still a work in
progress etc, but here goes:

MySQL MyISAM, wait_timeout=28800
SQLAlchemy 0.5.6, pool_recycle=3600

I've written a few decorators (mostly stolen from SQLAlchemy docs 
examples):

def with_query_write(fn):
def go(self, *args, **kw):
try:
result = fn(self, *args, **kw)
self.session.commit()
return result
except:
self.session.rollback()
raise
return go

def with_query_read(fn):
def go(self, *args, **kw):
try:
return fn(self, *args, **kw)
except:
self.session.rollback()
raise
return go

def with_session_write(fn):
def go(*args, **kw):
try:
result = fn(*args, **kw)
session.commit()
return result
except:
session.rollback()
raise
return go

All session writes go through base_dao.py, and are decorated with
@with_session_write. This way the code isn't littered with session.add(),
session.commit(), session.rollback() etc.

@with_session_write
def save(self, instance):
session.add(instance)
...

We've also extended Query (for reasons other than framing -- code omitted)
and added @with_query_write and @with_query_read decorators. I don't love
how I extended Query, and as of PyCon I know a better way to do this, but I
haven't had a chance to re-implement it.

Anyhoo, we pass the custom query class to the sessionmaker:

session = orm.scoped_session(orm.sessionmaker(query_cls=FooQuery))

The custom query class:

class FooQuery(Query):

def __init__(self, *arg, **kw):
Query.__init__(self, *arg, **kw)
...

@with_query_read
def all(self):
return Query.all(self)

@with_query_write
def delete(self):
return Query.delete(self)

...

Finally, we're using pylons and are removing the contextual session in the
finally clause of the base controller's __call__ method.

class BaseController(WSGIController):

def __call__(self, environ, start_response):
try:
...
finally:
session.remove()

We only ever see 'MySQL server has gone away' on our idle failover app
instances, as the only traffic they get are occasional pings from nagios. I
would have thought a combination of wait_timeout  pool_recycle would
prevent this... but I'm probably missing some piece of the big picture.

OperationalError: (OperationalError) (2006, 'MySQL server has gone
away')

I do wonder how possible it would be wrt the open session in view etc to
implement a reconnect on is_dissconect() in _handle_dbapi_exception()...

I also wonder if there's some app out there using SQLAlchemy with an
exemplary data access layer that we could all learn from. I should try a few
code search engines... I went with DAOs (one per mapped table) which extend
a base DAO that know how to do pagination, saves, deletes, etc. I dunno...

Thanks fro asking Chris. I'm watching the answers to these threads too.

--diana

On Wed, Apr 28, 2010 at 9:37 AM, Chris Withers ch...@simplistix.co.ukwrote:

 Hi All,

 I'm still trying to get an answer on this...

 Am I right in understanding that the basic session lifecycle should be:

 try:
use session
session.commit()
 except:
   log()
   session.rollback()
 finally:
   session.remove()

 The structure I've traditionally used with transactions has been:

 try:
use session
 except:
   log()
   session.rollback()
 else:
   session.commit()



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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Chris Withers

Diana Clarke wrote:
I'm a bit hesitant to share what I've done, b/c it's still a work in 
progress etc, but here goes:


MySQL MyISAM, wait_timeout=28800


You have no transactions, so I'm not sure why you're worrying about 
them... Switch to InnoDB if you want transactions...


Finally, we're using pylons and are removing the contextual session in 
the finally clause of the base controller's __call__ method.


class BaseController(WSGIController):

def __call__(self, environ, start_response):
try:
...
finally:
session.remove()


Yeah, I'm trying to find out if this .remove() is actually necessary.

We only ever see 'MySQL server has gone away' on our idle failover app 
instances, as the only traffic they get are occasional pings from 
nagios. I would have thought a combination of wait_timeout  
pool_recycle would prevent this... but I'm probably missing some piece 
of the big picture.


OperationalError: (OperationalError) (2006, 'MySQL server has gone 
away')


Indeed, I would have thought so too...

I do wonder how possible it would be wrt the open session in view etc to 
implement a reconnect on is_dissconect() in _handle_dbapi_exception()...


I can't see this as being safe, the state of your app may be 
inconsistent, you should probably retry the whole wsgi request from 
scratch when that happens...


...and I know Michael doesn't like that idea either ;-)

Chris

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread jason kirtland
On Wed, Apr 28, 2010 at 7:52 AM, Chris Withers ch...@simplistix.co.uk wrote:
 Diana Clarke wrote:

 Finally, we're using pylons and are removing the contextual session in the
 finally clause of the base controller's __call__ method.

 class BaseController(WSGIController):

    def __call__(self, environ, start_response):
        try:
            ...
        finally:
            session.remove()

 Yeah, I'm trying to find out if this .remove() is actually necessary.

.remove() as the final operation in a request ensures that no session
state leaks from one web request to another. The next request in that
thread or scoping context will get an entirely fresh session to work
with.

If finishing with a .remove() is a big deal in your environment, which
it seems like it is, you could do a .remove() at the start of the
request instead.

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Diana Clarke
Yup, no transactions (legacy, can't switch anytime soon) which is why
I didn't originally write any rollback framing... but I was still
getting the following error after MySQL raised a 2006 (until app
restart), and a quick peek at _handle_dbapi_exception seemed to
suggest that I needed to issue rollbacks even for non-transactional
database engines.

InvalidRequestError: Can't reconnect until invalid transaction is
rolled back

It goes without saying, but perhaps I've misunderstood something...

--diana

On Wed, Apr 28, 2010 at 10:52 AM, Chris Withers ch...@simplistix.co.uk wrote:

    MySQL MyISAM, wait_timeout=28800

 You have no transactions, so I'm not sure why you're worrying about them... 
 Switch to InnoDB if you want transactions...


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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Chris Withers

jason kirtland wrote:

On Wed, Apr 28, 2010 at 7:52 AM, Chris Withers ch...@simplistix.co.uk wrote:

Diana Clarke wrote:

Finally, we're using pylons and are removing the contextual session in the
finally clause of the base controller's __call__ method.

class BaseController(WSGIController):

   def __call__(self, environ, start_response):
   try:
   ...
   finally:
   session.remove()

Yeah, I'm trying to find out if this .remove() is actually necessary.


.remove() as the final operation in a request ensures that no session
state leaks from one web request to another. The next request in that
thread or scoping context will get an entirely fresh session to work
with.


Okay, would .close() be equivalent here?


If finishing with a .remove() is a big deal in your environment, which
it seems like it is, you could do a .remove() at the start of the
request instead.


What happens if you call .remove() on a virgin session?

cheers,

Chris

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread jason kirtland
On Wed, Apr 28, 2010 at 8:55 AM, Chris Withers ch...@simplistix.co.uk wrote:
 jason kirtland wrote:

 On Wed, Apr 28, 2010 at 7:52 AM, Chris Withers ch...@simplistix.co.uk
 wrote:

 Diana Clarke wrote:

 Finally, we're using pylons and are removing the contextual session in
 the
 finally clause of the base controller's __call__ method.

 class BaseController(WSGIController):

   def __call__(self, environ, start_response):
       try:
           ...
       finally:
           session.remove()

 Yeah, I'm trying to find out if this .remove() is actually necessary.

 .remove() as the final operation in a request ensures that no session
 state leaks from one web request to another. The next request in that
 thread or scoping context will get an entirely fresh session to work
 with.

 Okay, would .close() be equivalent here?

Not really, .close is a Session method.  See below.

 If finishing with a .remove() is a big deal in your environment, which
 it seems like it is, you could do a .remove() at the start of the
 request instead.

 What happens if you call .remove() on a virgin session?

.remove() is specific to the ScopedSession container.  It's not a
Session method.  It will .close() the session for the current scope,
if any (which is effectively a no-op if there is a session but it
hasn't performed any work), then remove that session from the scope.
The next access to the ScopedSession container will produce a fresh
session.

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Michael Bayer
jason kirtland wrote:
 On Wed, Apr 28, 2010 at 7:52 AM, Chris Withers ch...@simplistix.co.uk
 wrote:
 Diana Clarke wrote:

 Finally, we're using pylons and are removing the contextual session in
 the
 finally clause of the base controller's __call__ method.

 class BaseController(WSGIController):

    def __call__(self, environ, start_response):
        try:
            ...
        finally:
            session.remove()

 Yeah, I'm trying to find out if this .remove() is actually necessary.

 .remove() as the final operation in a request ensures that no session
 state leaks from one web request to another. The next request in that
 thread or scoping context will get an entirely fresh session to work
 with.

 If finishing with a .remove() is a big deal in your environment, which
 it seems like it is, you could do a .remove() at the start of the
 request instead.

You really don't need the remove() if you have definitely called
commit() or rollback() last, and you have expire_on_commit=True.  In most
cases the session will be empty on the next request.




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



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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Michael Bayer
Diana Clarke wrote:
 Yup, no transactions (legacy, can't switch anytime soon) which is why
 I didn't originally write any rollback framing... but I was still
 getting the following error after MySQL raised a 2006 (until app
 restart), and a quick peek at _handle_dbapi_exception seemed to
 suggest that I needed to issue rollbacks even for non-transactional
 database engines.

 InvalidRequestError: Can't reconnect until invalid transaction is
 rolled back

 It goes without saying, but perhaps I've misunderstood something...

the database transaction is almost secondary to all the other things in
memory that correspond to the transaction.   Three FAQ entries below,
and by the third the question should begin to be answered, hopefully...

http://www.sqlalchemy.org/trac/wiki/FAQ#Thetransactionisinactiveduetoarollbackinasubtransaction



 --diana

 On Wed, Apr 28, 2010 at 10:52 AM, Chris Withers ch...@simplistix.co.uk
 wrote:

    MySQL MyISAM, wait_timeout=28800

 You have no transactions, so I'm not sure why you're worrying about
 them... Switch to InnoDB if you want transactions...


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



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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Chris Withers

Michael Bayer wrote:

If finishing with a .remove() is a big deal in your environment, which
it seems like it is, you could do a .remove() at the start of the
request instead.


You really don't need the remove() if you have definitely called
commit() or rollback() last, and you have expire_on_commit=True.  In most
cases the session will be empty on the next request.


When could it not be empty and would that matter?

Are there any other implications of calling neither .remove() nor 
.close()? I have a (hopefully) paranoid worry about connections not 
being returned to the pool and/or going away in typical MySQL style...


Chris

--
Simplistix - Content Management, Batch Processing  Python Consulting
   - http://www.simplistix.co.uk

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



Re: [sqlalchemy] session lifecycle and wsgi

2010-04-28 Thread Michael Bayer
Chris Withers wrote:
 Michael Bayer wrote:
 If finishing with a .remove() is a big deal in your environment, which
 it seems like it is, you could do a .remove() at the start of the
 request instead.

 You really don't need the remove() if you have definitely called
 commit() or rollback() last, and you have expire_on_commit=True.  In
 most
 cases the session will be empty on the next request.

 When could it not be empty

if GC has not removed objects from it yet, or you otherwise are still
referencing those objects after you've finished your request.

 and would that matter?

if your application keeps a handle on objects after the request is
complete, and then passed them somewhere else, like a background thread or
something, then the subsequent request is going to be potentially touching
those objects at the same time.  This would all be pretty poor practice as
individual threads should always have their own sessions.   Or maybe you
loaded those objects into a globally-scoped in-memory cache of some kind -
you probably don't want the next request touching them directly as once
they're in a global cache of some kind, other threads would be calling
upon them to copy their state locally.

On the other hand, you might load the objects into a session-local cache
of some kind that you've created.Now, when the next request comes in
and calls upon those same rows, the ORM doesn't need to re-instantiate the
objects, they are already present in the cache.This is a use case
where you'd want to keep the same session from one request to the next.  
Its not one I use, but there is anotherORM like thing, somewhere on
the webwhere I'm pretty sure they use a scheme like this.



 Are there any other implications of calling neither .remove() nor
 .close()? I have a (hopefully) paranoid worry about connections not
 being returned to the pool and/or going away in typical MySQL style...

the bulletpoints at
http://www.sqlalchemy.org/docs/session.html#lifespan-of-a-contextual-session
are the best I can do here, I'm really just repeating myself over and over
in these threads




 Chris

 --
 Simplistix - Content Management, Batch Processing  Python Consulting
 - http://www.simplistix.co.uk

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



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