proxy: refactor how and when connections are returned to the pool (#5095)

## Problem

Transactions break connections in the pool

fixes #4698 

## Summary of changes

* Pool `Client`s are smart object that return themselves to the pool
* Pool `Client`s can be 'discard'ed
* Pool `Client`s are discarded when certain errors are encountered.
* Pool `Client`s are discarded when ReadyForQuery returns a non-idle
state.
This commit is contained in:
Conrad Ludgate
2023-10-17 14:55:52 +01:00
committed by GitHub
parent ea648cfbc6
commit f775928dfc
6 changed files with 284 additions and 136 deletions

View File

@@ -7,6 +7,8 @@ import pytest
import requests
from fixtures.neon_fixtures import PSQL, NeonProxy, VanillaPostgres
GET_CONNECTION_PID_QUERY = "SELECT pid FROM pg_stat_activity WHERE state = 'active'"
def test_proxy_select_1(static_proxy: NeonProxy):
"""
@@ -353,7 +355,7 @@ def test_sql_over_http_pool(static_proxy: NeonProxy):
def get_pid(status: int, pw: str) -> Any:
return static_proxy.http_query(
"SELECT pid FROM pg_stat_activity WHERE state = 'active'",
GET_CONNECTION_PID_QUERY,
[],
user="http_auth",
password=pw,
@@ -387,7 +389,6 @@ def test_sql_over_http_pool(static_proxy: NeonProxy):
# Beginning a transaction should not impact the next query,
# which might come from a completely different client.
@pytest.mark.xfail(reason="not implemented")
def test_http_pool_begin(static_proxy: NeonProxy):
static_proxy.safe_psql("create user http_auth with password 'http' superuser")
@@ -403,3 +404,21 @@ def test_http_pool_begin(static_proxy: NeonProxy):
query(200, "BEGIN;")
query(400, "garbage-lol(&(&(&(&") # Intentional error to break the transaction
query(200, "SELECT 1;") # Query that should succeed regardless of the transaction
def test_sql_over_http_pool_idle(static_proxy: NeonProxy):
static_proxy.safe_psql("create user http_auth2 with password 'http' superuser")
def query(status: int, query: str) -> Any:
return static_proxy.http_query(
query,
[],
user="http_auth2",
password="http",
expected_code=status,
)
pid1 = query(200, GET_CONNECTION_PID_QUERY)["rows"][0]["pid"]
query(200, "BEGIN")
pid2 = query(200, GET_CONNECTION_PID_QUERY)["rows"][0]["pid"]
assert pid1 != pid2