Skip to content

Commit 7d24261

Browse files
Stop reusing broken connection
1 parent 6680c85 commit 7d24261

File tree

2 files changed

+15
-37
lines changed

2 files changed

+15
-37
lines changed

clickhouse_backend/driver/pool.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ def push(
105105
raise InterfaceError("trying to put unkeyed client")
106106
if len(self._pool) < self.connections_min and not close:
107107
# TODO: verify connection still valid
108+
109+
# If the connection is currently executing a query, it shouldn't be reused.
110+
# Explicitly disconnect it instead.
111+
if client.connection.is_query_executing:
112+
client.disconnect()
108113
if client.connection.connected:
109114
self._pool.append(client)
110115
else:
Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
from clickhouse_driver.dbapi.errors import (
2-
OperationalError as ch_driver_OperationalError,
3-
)
4-
from clickhouse_driver.errors import PartiallyConsumedQueryError
51
from django.db import connection
6-
from django.db.utils import OperationalError as django_OperationalError
72
from django.test import TestCase
83

94
from clickhouse_backend.driver import connect
@@ -34,41 +29,19 @@ def setUpTestData(cls):
3429
]
3530
)
3631

37-
def test_connection_unusable_when_iteration_interrupted(self):
38-
"""
39-
This test demonstrates that if a queryset is iterated over and the iteration
40-
is interrupted (e.g. via a break statement), the connection used for that
41-
iteration is not cleaned up and is left in a broken state. Any subsequent
42-
queries using that connection will fail.
43-
"""
32+
def test_connection_not_reused_when_iteration_interrupted(self):
4433
pool = connection.connection.pool
45-
connection_count_before = len(pool._pool)
4634

35+
connection_count_before = len(pool._pool)
4736
assert connection_count_before == 1
4837

49-
# Asserts most recent exception is Django OperationalError
50-
with self.assertRaises(django_OperationalError) as ex_context:
51-
# Get queryset
52-
authors = models.Author.objects.all()
53-
# Access iterator, but break after first item
54-
for author in authors.iterator(1):
55-
author = author.name
56-
break
57-
58-
# Assert connection pool size is unchanged despite broken connection
59-
connection_count_after_iterator = len(pool._pool)
60-
assert connection_count_after_iterator == 1
38+
authors = models.Author.objects.all()
39+
for author in authors.iterator(1):
40+
author = author.name
41+
break
6142

62-
# Try to access queryset again, which won't work via same connection
63-
author = authors.get(id=self.a1.id)
43+
connection_count_after_iterator = len(pool._pool)
44+
# Connection was closed and not returned to pool
45+
assert connection_count_after_iterator == 0
6446

65-
# Caused by ch driver driver Operational error
66-
self.assertIsInstance(
67-
ex_context.exception.__cause__, ch_driver_OperationalError
68-
)
69-
70-
# ...The context of which is a PartiallyConsumedQueryError
71-
# https://github.com/mymarilyn/clickhouse-driver/blob/master/clickhouse_driver/connection.py#L801
72-
self.assertIsInstance(
73-
ex_context.exception.__cause__.__context__, PartiallyConsumedQueryError
74-
)
47+
author = authors.get(id=self.a1.id)

0 commit comments

Comments
 (0)