Add Postgres table adapter with TableRepositoryInterface.
PR Title Check / check-title (pull_request) Successful in 7s
Code Quality Pipeline / code-quality (pull_request) Failing after 19s
Test Python Package / unit-tests (pull_request) Successful in 47s
Test Python Package / integration-tests (pull_request) Successful in 44s
Test Python Package / coverage-report (pull_request) Successful in 11s
PR Title Check / check-title (pull_request) Successful in 7s
Code Quality Pipeline / code-quality (pull_request) Failing after 19s
Test Python Package / unit-tests (pull_request) Successful in 47s
Test Python Package / integration-tests (pull_request) Successful in 44s
Test Python Package / coverage-report (pull_request) Successful in 11s
Introduce PostgresAdapter for dict-based row CRUD via psycopg3, including config, lazy exports, unit/integration tests with testcontainers, and an example UserTableRepository. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
co-authored by
Cursor
parent
f28d3c4844
commit
dc6f8a3e89
@@ -6,10 +6,12 @@ from typing import cast
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import redis
|
||||
import psycopg
|
||||
|
||||
from python_repositories.adapters.minio_adapter import MinioAdapter
|
||||
from python_repositories.adapters.postgres_adapter import PostgresAdapter
|
||||
from python_repositories.adapters.redis_adapter import RedisAdapter
|
||||
from tests.conftest import TEST_MINIO_CONFIG, TEST_REDIS_CONFIG
|
||||
from tests.conftest import TEST_MINIO_CONFIG, TEST_POSTGRES_CONFIG, TEST_REDIS_CONFIG
|
||||
|
||||
|
||||
class TestRedisConnectionHealth:
|
||||
@@ -161,3 +163,74 @@ class TestMinioConnectionHealth:
|
||||
assert reinjected.is_connected()
|
||||
|
||||
assert mock_client.bucket_exists.call_count == 2
|
||||
|
||||
|
||||
class TestPostgresConnectionHealth:
|
||||
def test_not_connected_when_no_client(self) -> None:
|
||||
adapter = PostgresAdapter(config=TEST_POSTGRES_CONFIG)
|
||||
assert not adapter.is_connected()
|
||||
|
||||
def test_connected_when_probe_succeeds(
|
||||
self, postgres_adapter: PostgresAdapter
|
||||
) -> None:
|
||||
assert postgres_adapter.is_connected()
|
||||
cast(MagicMock, postgres_adapter._client).cursor.assert_called()
|
||||
|
||||
def test_stale_connection_when_probe_fails(
|
||||
self, postgres_adapter: PostgresAdapter
|
||||
) -> None:
|
||||
mock_cursor = cast(MagicMock, postgres_adapter._client).cursor.return_value
|
||||
mock_cursor.execute.side_effect = psycopg.OperationalError("connection lost")
|
||||
|
||||
assert not postgres_adapter.is_connected()
|
||||
|
||||
def test_cache_hit_avoids_second_probe(
|
||||
self, postgres_adapter: PostgresAdapter
|
||||
) -> None:
|
||||
mock_client = cast(MagicMock, postgres_adapter._client)
|
||||
|
||||
with patch(
|
||||
"python_repositories.adapters.connection_aware_adapter.time.monotonic",
|
||||
return_value=100.0,
|
||||
):
|
||||
assert postgres_adapter.is_connected()
|
||||
assert postgres_adapter.is_connected()
|
||||
|
||||
assert mock_client.cursor.call_count == 1
|
||||
|
||||
def test_cache_miss_runs_probe_again(
|
||||
self, postgres_adapter: PostgresAdapter
|
||||
) -> None:
|
||||
mock_client = cast(MagicMock, postgres_adapter._client)
|
||||
|
||||
with patch(
|
||||
"python_repositories.adapters.connection_aware_adapter.time.monotonic",
|
||||
side_effect=[100.0, 102.0],
|
||||
):
|
||||
assert postgres_adapter.is_connected()
|
||||
assert postgres_adapter.is_connected()
|
||||
|
||||
assert mock_client.cursor.call_count == 2
|
||||
|
||||
def test_disconnect_clears_cache(self, postgres_adapter: PostgresAdapter) -> None:
|
||||
mock_client = cast(MagicMock, postgres_adapter._client)
|
||||
|
||||
with patch(
|
||||
"python_repositories.adapters.connection_aware_adapter.time.monotonic",
|
||||
return_value=100.0,
|
||||
):
|
||||
assert postgres_adapter.is_connected()
|
||||
|
||||
postgres_adapter.disconnect()
|
||||
reinjected = PostgresAdapter(
|
||||
config=postgres_adapter._config,
|
||||
client=mock_client,
|
||||
)
|
||||
|
||||
with patch(
|
||||
"python_repositories.adapters.connection_aware_adapter.time.monotonic",
|
||||
return_value=100.0,
|
||||
):
|
||||
assert reinjected.is_connected()
|
||||
|
||||
assert mock_client.cursor.call_count == 2
|
||||
|
||||
Reference in New Issue
Block a user