Skip to content

Commit 164a47c

Browse files
committed
Add cursor.closed check for rollback operations
1 parent 6b2db0c commit 164a47c

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

aiopg/transaction.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,15 @@ async def commit(self):
127127

128128
async def rollback(self):
129129
self._check_commit_rollback()
130-
await self._cursor.execute(self._isolation.rollback())
130+
if not self._cursor.closed:
131+
await self._cursor.execute(self._isolation.rollback())
131132
self._is_begin = False
132133

133134
async def rollback_savepoint(self):
134135
self._check_release_rollback()
135-
await self._cursor.execute(
136-
self._isolation.rollback_savepoint(self._unique_id))
136+
if not self._cursor.closed:
137+
await self._cursor.execute(
138+
self._isolation.rollback_savepoint(self._unique_id))
137139
self._unique_id = None
138140

139141
async def release_savepoint(self):

tests/test_transaction.py

+60
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncio
2+
13
import psycopg2
24
import pytest
35

@@ -181,3 +183,61 @@ async def test_transaction_point_oldstyle(engine):
181183
(3, 'data')]
182184

183185
await tr.commit()
186+
187+
188+
async def test_timeout_in_transaction_context_manager(make_engine):
189+
engine = await make_engine(timeout=1)
190+
with pytest.raises(asyncio.TimeoutError):
191+
async with engine.acquire() as connection:
192+
async with Transaction(connection, IsolationLevel.read_committed):
193+
await connection.execute("SELECT pg_sleep(10)")
194+
195+
engine.terminate()
196+
await engine.wait_closed()
197+
198+
199+
async def test_timeout_in_savepoint_context_manager(make_engine):
200+
engine = await make_engine(timeout=1)
201+
with pytest.raises(asyncio.TimeoutError):
202+
async with engine.acquire() as connection:
203+
async with Transaction(
204+
connection, IsolationLevel.read_committed
205+
) as transaction:
206+
async with transaction.point():
207+
await connection.execute("SELECT pg_sleep(10)")
208+
209+
engine.terminate()
210+
await engine.wait_closed()
211+
212+
213+
async def test_cancel_in_transaction_context_manager(engine, loop):
214+
with pytest.raises(asyncio.CancelledError):
215+
async with engine.acquire() as connection:
216+
async with Transaction(connection, IsolationLevel.read_committed):
217+
task = loop.create_task(
218+
connection.execute("SELECT pg_sleep(10)"))
219+
220+
async def cancel_soon():
221+
await asyncio.sleep(1)
222+
task.cancel()
223+
224+
loop.create_task(cancel_soon())
225+
await task
226+
227+
228+
async def test_cancel_in_savepoint_context_manager(engine, loop):
229+
with pytest.raises(asyncio.CancelledError):
230+
async with engine.acquire() as connection:
231+
async with Transaction(
232+
connection, IsolationLevel.read_committed
233+
) as transaction:
234+
async with transaction.point():
235+
task = loop.create_task(
236+
connection.execute("SELECT pg_sleep(10)"))
237+
238+
async def cancel_soon():
239+
await asyncio.sleep(1)
240+
task.cancel()
241+
242+
loop.create_task(cancel_soon())
243+
await task

0 commit comments

Comments
 (0)