Show More
@@ -40,6 +40,8 b' import uuid' | |||||
40 | import pygments.lexers |
|
40 | import pygments.lexers | |
41 | import sqlalchemy |
|
41 | import sqlalchemy | |
42 | import sqlalchemy.engine.url |
|
42 | import sqlalchemy.engine.url | |
|
43 | import sqlalchemy.exc | |||
|
44 | import sqlalchemy.sql | |||
43 | import webob |
|
45 | import webob | |
44 | import routes.util |
|
46 | import routes.util | |
45 |
|
47 | |||
@@ -314,6 +316,41 b' def find_calling_context(ignore_modules=' | |||||
314 | return None |
|
316 | return None | |
315 |
|
317 | |||
316 |
|
318 | |||
|
319 | def ping_connection(connection, branch): | |||
|
320 | if branch: | |||
|
321 | # "branch" refers to a sub-connection of a connection, | |||
|
322 | # we don't want to bother pinging on these. | |||
|
323 | return | |||
|
324 | ||||
|
325 | # turn off "close with result". This flag is only used with | |||
|
326 | # "connectionless" execution, otherwise will be False in any case | |||
|
327 | save_should_close_with_result = connection.should_close_with_result | |||
|
328 | connection.should_close_with_result = False | |||
|
329 | ||||
|
330 | try: | |||
|
331 | # run a SELECT 1. use a core select() so that | |||
|
332 | # the SELECT of a scalar value without a table is | |||
|
333 | # appropriately formatted for the backend | |||
|
334 | connection.scalar(sqlalchemy.sql.select([1])) | |||
|
335 | except sqlalchemy.exc.DBAPIError as err: | |||
|
336 | # catch SQLAlchemy's DBAPIError, which is a wrapper | |||
|
337 | # for the DBAPI's exception. It includes a .connection_invalidated | |||
|
338 | # attribute which specifies if this connection is a "disconnect" | |||
|
339 | # condition, which is based on inspection of the original exception | |||
|
340 | # by the dialect in use. | |||
|
341 | if err.connection_invalidated: | |||
|
342 | # run the same SELECT again - the connection will re-validate | |||
|
343 | # itself and establish a new connection. The disconnect detection | |||
|
344 | # here also causes the whole connection pool to be invalidated | |||
|
345 | # so that all stale connections are discarded. | |||
|
346 | connection.scalar(sqlalchemy.sql.select([1])) | |||
|
347 | else: | |||
|
348 | raise | |||
|
349 | finally: | |||
|
350 | # restore "close with result" | |||
|
351 | connection.should_close_with_result = save_should_close_with_result | |||
|
352 | ||||
|
353 | ||||
317 | def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): |
|
354 | def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): | |
318 | """Custom engine_from_config functions.""" |
|
355 | """Custom engine_from_config functions.""" | |
319 | log = logging.getLogger('sqlalchemy.engine') |
|
356 | log = logging.getLogger('sqlalchemy.engine') | |
@@ -345,6 +382,8 b' def engine_from_config(configuration, pr' | |||||
345 | parameters, context, executemany): |
|
382 | parameters, context, executemany): | |
346 | delattr(conn, 'query_start_time') |
|
383 | delattr(conn, 'query_start_time') | |
347 |
|
384 | |||
|
385 | sqlalchemy.event.listen(engine, "engine_connect", | |||
|
386 | ping_connection) | |||
348 | sqlalchemy.event.listen(engine, "before_cursor_execute", |
|
387 | sqlalchemy.event.listen(engine, "before_cursor_execute", | |
349 | before_cursor_execute) |
|
388 | before_cursor_execute) | |
350 | sqlalchemy.event.listen(engine, "after_cursor_execute", |
|
389 | sqlalchemy.event.listen(engine, "after_cursor_execute", |
General Comments 0
You need to be logged in to leave comments.
Login now