Skip to content

Commit 8a3eb42

Browse files
canonrock16TimPansino
authored andcommitted
fix(aiomysql): avoid wrapping pooled connections multiple times (#1553)
* fix(aiomysql): avoid wrapping pooled connections multiple times * Move and rewrite regression test * Tweak implementation of fix --------- Co-authored-by: Tim Pansino <[email protected]>
1 parent b9efe7e commit 8a3eb42

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

newrelic/hooks/database_aiomysql.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ async def _wrap_pool__acquire(wrapped, instance, args, kwargs):
7878
with FunctionTrace(name=callable_name(wrapped), terminal=True, rollup=rollup, source=wrapped):
7979
connection = await wrapped(*args, **kwargs)
8080
connection_kwargs = getattr(instance, "_conn_kwargs", {})
81+
82+
if hasattr(connection, "__wrapped__"):
83+
return connection
84+
8185
return AsyncConnectionWrapper(connection, dbapi2_module, (((), connection_kwargs)))
8286

8387
return _wrap_pool__acquire

tests/datastore_aiomysql/test_database.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
import inspect
16+
1517
import aiomysql
1618
from testing_support.db_settings import mysql_settings
1719
from testing_support.util import instance_hostname
@@ -150,3 +152,35 @@ async def _test():
150152
await pool.wait_closed()
151153

152154
loop.run_until_complete(_test())
155+
156+
157+
@background_task()
158+
def test_connection_pool_no_double_wrap(loop):
159+
async def _test():
160+
pool = await aiomysql.create_pool(
161+
db=DB_SETTINGS["name"],
162+
user=DB_SETTINGS["user"],
163+
password=DB_SETTINGS["password"],
164+
host=DB_SETTINGS["host"],
165+
port=DB_SETTINGS["port"],
166+
loop=loop,
167+
)
168+
169+
# Retrieve the same connection from the pool twice to see if it gets double wrapped
170+
async with pool.acquire() as first_connection:
171+
first_connection_unwrapped = inspect.unwrap(first_connection)
172+
async with pool.acquire() as second_connection:
173+
second_connection_unwrapped = inspect.unwrap(second_connection)
174+
175+
# Ensure we actually retrieved the same underlying connection object from the pool twice
176+
assert first_connection_unwrapped is second_connection_unwrapped, "Did not get same connection from pool"
177+
178+
# Check that wrapping occurred only once
179+
assert hasattr(first_connection, "__wrapped__"), "first_connection object was not wrapped"
180+
assert hasattr(second_connection, "__wrapped__"), "second_connection object was not wrapped"
181+
assert not hasattr(second_connection.__wrapped__, "__wrapped__"), "second_connection was double wrapped"
182+
183+
pool.close()
184+
await pool.wait_closed()
185+
186+
loop.run_until_complete(_test())

0 commit comments

Comments
 (0)