Merge lp:~jamesh/storm/bug-374909 into lp:storm

Proposed by James Henstridge
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jamesh/storm/bug-374909
Merge into: lp:storm
Diff against target: 123 lines
To merge this branch: bzr merge lp:~jamesh/storm/bug-374909
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Thomas Herve (community) Approve
Review via email: mp+6606@code.launchpad.net
To post a comment you must log in.
Revision history for this message
James Henstridge (jamesh) wrote :

Produce DisconnectionError exceptions if we detect that the connection has been dropped after the fact.

This can happen if code is using the raw connection outside of the control of Storm, such as with the Django ORM integration, or some bits of legacy code in Launchpad.

The branch also links storm.exceptions.InterfaceError to the database module's InterfaceError, which was not being done previously.

Revision history for this message
Thomas Herve (therve) wrote :

+ def test_wb_catch_already_disconnected(self):
+ """If Storm detects connections that have already been disconnected.

The sentence looks incomplete.

+1!

review: Approve
lp:~jamesh/storm/bug-374909 updated
308. By James Henstridge

Fix docstring problem pointed out in therve's review.

Revision history for this message
James Henstridge (jamesh) wrote :

> + def test_wb_catch_already_disconnected(self):
> + """If Storm detects connections that have already been disconnected.
>
> The sentence looks incomplete.

The "If" at the beginning shouldn't have been there. I've fixed that now.

Revision history for this message
Stuart Bishop (stub) wrote :

Looks good to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'storm/database.py'
2--- storm/database.py 2009-05-08 17:27:18 +0000
3+++ storm/database.py 2009-07-01 03:20:12 +0000
4@@ -28,7 +28,8 @@
5 from storm.expr import Expr, State, compile
6 from storm.tracer import trace
7 from storm.variables import Variable
8-from storm.exceptions import ClosedError, DatabaseError, DisconnectionError
9+from storm.exceptions import (
10+ ClosedError, DatabaseError, DisconnectionError, Error)
11 from storm.uri import URI
12 import storm
13
14@@ -273,7 +274,7 @@
15
16 @return: The dbapi cursor object, as fetched from L{build_raw_cursor}.
17 """
18- raw_cursor = self.build_raw_cursor()
19+ raw_cursor = self._check_disconnect(self.build_raw_cursor)
20 self._check_disconnect(
21 trace, "connection_raw_execute", self, raw_cursor,
22 statement, params or ())
23@@ -326,7 +327,7 @@
24 """Run the given function, checking for database disconnections."""
25 try:
26 return function(*args, **kwargs)
27- except DatabaseError, exc:
28+ except Error, exc:
29 if self.is_disconnection_error(exc):
30 self._state = STATE_DISCONNECTED
31 self._raw_connection = None
32
33=== modified file 'storm/databases/postgres.py'
34--- storm/databases/postgres.py 2008-08-18 19:44:51 +0000
35+++ storm/databases/postgres.py 2009-07-01 03:20:12 +0000
36@@ -36,7 +36,7 @@
37 from storm.variables import Variable, ListVariable, RawStrVariable
38 from storm.database import Database, Connection, Result
39 from storm.exceptions import (
40- install_exceptions, DatabaseError, DatabaseModuleError,
41+ install_exceptions, DatabaseError, DatabaseModuleError, InterfaceError,
42 OperationalError, ProgrammingError, TimeoutError)
43 from storm.tracer import TimeoutTracer
44
45@@ -285,17 +285,20 @@
46 yield param
47
48 def is_disconnection_error(self, exc):
49- if not isinstance(exc, (OperationalError, ProgrammingError)):
50+ if not isinstance(exc, (InterfaceError, OperationalError,
51+ ProgrammingError)):
52 return False
53
54 # XXX: 2007-09-17 jamesh
55- # I have no idea why I am seeing the last exception message
56- # after upgrading to Gutsy.
57+ # The last message is for the benefit of old versions of
58+ # psycopg2 (prior to 2.0.7) which have a bug related to
59+ # stripping the error severity from the message.
60 msg = str(exc)
61 return ("server closed the connection unexpectedly" in msg or
62 "could not connect to server" in msg or
63 "no connection to the server" in msg or
64 "connection not open" in msg or
65+ "connection already closed" in msg or
66 "losed the connection unexpectedly" in msg)
67
68
69
70=== modified file 'storm/exceptions.py'
71--- storm/exceptions.py 2008-01-31 21:29:55 +0000
72+++ storm/exceptions.py 2009-07-01 03:20:12 +0000
73@@ -130,7 +130,7 @@
74 def install_exceptions(module):
75 for exception in (Error, Warning, DatabaseError, InternalError,
76 OperationalError, ProgrammingError, IntegrityError,
77- DataError, NotSupportedError):
78+ DataError, NotSupportedError, InterfaceError):
79 module_exception = getattr(module, exception.__name__, None)
80 if module_exception is not None:
81 module_exception.__bases__ += (exception,)
82
83=== modified file 'tests/databases/base.py'
84--- tests/databases/base.py 2008-10-10 05:44:35 +0000
85+++ tests/databases/base.py 2009-07-01 03:20:12 +0000
86@@ -33,7 +33,7 @@
87 from storm.database import *
88 from storm.event import EventSystem
89 from storm.exceptions import (
90- DatabaseModuleError, DisconnectionError, OperationalError)
91+ DatabaseError, DatabaseModuleError, DisconnectionError, OperationalError)
92
93 from tests.databases.proxy import ProxyTCPServer
94 from tests.helper import MakePath
95@@ -515,6 +515,28 @@
96 self.proxy.restart()
97 self.assertRaises(DisconnectionError, self.connection.commit)
98
99+ def test_wb_catch_already_disconnected(self):
100+ """Storm detects connections that have already been disconnected.
101+
102+ If the connection is being used outside of Storm's control,
103+ then it is possible that Storm won't see the disconnection.
104+ It should be able to recover from this situation though.
105+ """
106+ result = self.connection.execute("SELECT 1")
107+ self.assertTrue(result.get_one())
108+ self.proxy.restart()
109+ # Perform an action that should result in a disconnection.
110+ try:
111+ cursor = self.connection._raw_connection.cursor()
112+ cursor.execute("SELECT 1")
113+ cursor.fetchone()
114+ except DatabaseError, exc:
115+ self.assertTrue(self.connection.is_disconnection_error(exc))
116+ else:
117+ self.fail("Disconnection was not caught.")
118+ self.assertRaises(DisconnectionError,
119+ self.connection.execute, "SELECT 1")
120+
121 def test_connection_stays_disconnected_in_transaction(self):
122 """Test that connection does not immediately reconnect."""
123 result = self.connection.execute("SELECT 1")

Subscribers

People subscribed via source and target branches

to status/vote changes: