src.offers.postgresql_offers_repository_adapter
PostgreSQL adapter for the offers repository.
1"""PostgreSQL adapter for the offers repository.""" 2 3from typing import cast, override 4 5import psycopg2 6from psycopg2.extensions import connection as _connection 7 8from src.offers.models import Offer 9from src.offers.offers_repository_port import OffersRepositoryPort 10 11class PostgreSQLOffersRepositoryAdapter(OffersRepositoryPort): 12 """Adapter that stores offers in a PostgreSQL database.""" 13 14 _conn: _connection 15 _connection_string: str 16 17 def __init__(self, connection_string: str) -> None: 18 """Initialise with a PostgreSQL connection string. 19 20 Args: 21 connection_string: PostgreSQL connection string. 22 """ 23 self._connection_string = connection_string 24 self._conn = psycopg2.connect(connection_string) 25 self._init_db() 26 27 def close_db(self) -> None: 28 """Close the database connection.""" 29 self._conn.close() 30 31 def _init_db(self) -> None: 32 """Initialize the database table for offers.""" 33 with self._conn.cursor() as cursor: 34 cursor.execute( 35 """ 36 CREATE TABLE IF NOT EXISTS offers ( 37 offer_id TEXT PRIMARY KEY, 38 award_id TEXT NOT NULL 39 ) 40 """ 41 # TODO add indexes for offer_id and award_id 42 ) 43 self._conn.commit() 44 45 @override 46 def store(self, offer: Offer) -> None: 47 """Persist an offer in PostgreSQL. 48 49 Args: 50 offer: The offer to store. 51 """ 52 with self._conn.cursor() as cursor: 53 cursor.execute( 54 """ 55 INSERT INTO offers (offer_id, award_id) 56 VALUES (%s, %s) 57 ON CONFLICT (offer_id) DO UPDATE 58 SET award_id = EXCLUDED.award_id 59 """, 60 ( 61 offer.offer_id, 62 offer.award_id, 63 ), 64 ) 65 self._conn.commit() 66 67 @override 68 def get(self, offer_id: str) -> Offer: 69 """Retrieve an offer by its identifier. 70 71 Args: 72 offer_id: The unique offer identifier. 73 74 Returns: 75 The matching Offer. 76 77 Raises: 78 KeyError: When no offer with the given id exists. 79 """ 80 with self._conn.cursor() as cursor: 81 cursor.execute( 82 """ 83 SELECT offer_id, award_id 84 FROM offers 85 WHERE offer_id = %s 86 """, 87 (offer_id,), 88 ) 89 row = cursor.fetchone() 90 self._conn.commit() 91 92 if row is None: 93 raise KeyError(f"Offer with id {offer_id} not found") 94 return Offer( 95 offer_id=cast(str, row[0]), 96 award_id=cast(str, row[1]), 97 uri=None 98 )
12class PostgreSQLOffersRepositoryAdapter(OffersRepositoryPort): 13 """Adapter that stores offers in a PostgreSQL database.""" 14 15 _conn: _connection 16 _connection_string: str 17 18 def __init__(self, connection_string: str) -> None: 19 """Initialise with a PostgreSQL connection string. 20 21 Args: 22 connection_string: PostgreSQL connection string. 23 """ 24 self._connection_string = connection_string 25 self._conn = psycopg2.connect(connection_string) 26 self._init_db() 27 28 def close_db(self) -> None: 29 """Close the database connection.""" 30 self._conn.close() 31 32 def _init_db(self) -> None: 33 """Initialize the database table for offers.""" 34 with self._conn.cursor() as cursor: 35 cursor.execute( 36 """ 37 CREATE TABLE IF NOT EXISTS offers ( 38 offer_id TEXT PRIMARY KEY, 39 award_id TEXT NOT NULL 40 ) 41 """ 42 # TODO add indexes for offer_id and award_id 43 ) 44 self._conn.commit() 45 46 @override 47 def store(self, offer: Offer) -> None: 48 """Persist an offer in PostgreSQL. 49 50 Args: 51 offer: The offer to store. 52 """ 53 with self._conn.cursor() as cursor: 54 cursor.execute( 55 """ 56 INSERT INTO offers (offer_id, award_id) 57 VALUES (%s, %s) 58 ON CONFLICT (offer_id) DO UPDATE 59 SET award_id = EXCLUDED.award_id 60 """, 61 ( 62 offer.offer_id, 63 offer.award_id, 64 ), 65 ) 66 self._conn.commit() 67 68 @override 69 def get(self, offer_id: str) -> Offer: 70 """Retrieve an offer by its identifier. 71 72 Args: 73 offer_id: The unique offer identifier. 74 75 Returns: 76 The matching Offer. 77 78 Raises: 79 KeyError: When no offer with the given id exists. 80 """ 81 with self._conn.cursor() as cursor: 82 cursor.execute( 83 """ 84 SELECT offer_id, award_id 85 FROM offers 86 WHERE offer_id = %s 87 """, 88 (offer_id,), 89 ) 90 row = cursor.fetchone() 91 self._conn.commit() 92 93 if row is None: 94 raise KeyError(f"Offer with id {offer_id} not found") 95 return Offer( 96 offer_id=cast(str, row[0]), 97 award_id=cast(str, row[1]), 98 uri=None 99 )
Adapter that stores offers in a PostgreSQL database.
PostgreSQLOffersRepositoryAdapter(connection_string: str)
18 def __init__(self, connection_string: str) -> None: 19 """Initialise with a PostgreSQL connection string. 20 21 Args: 22 connection_string: PostgreSQL connection string. 23 """ 24 self._connection_string = connection_string 25 self._conn = psycopg2.connect(connection_string) 26 self._init_db()
Initialise with a PostgreSQL connection string.
Args: connection_string: PostgreSQL connection string.
46 @override 47 def store(self, offer: Offer) -> None: 48 """Persist an offer in PostgreSQL. 49 50 Args: 51 offer: The offer to store. 52 """ 53 with self._conn.cursor() as cursor: 54 cursor.execute( 55 """ 56 INSERT INTO offers (offer_id, award_id) 57 VALUES (%s, %s) 58 ON CONFLICT (offer_id) DO UPDATE 59 SET award_id = EXCLUDED.award_id 60 """, 61 ( 62 offer.offer_id, 63 offer.award_id, 64 ), 65 ) 66 self._conn.commit()
Persist an offer in PostgreSQL.
Args: offer: The offer to store.
68 @override 69 def get(self, offer_id: str) -> Offer: 70 """Retrieve an offer by its identifier. 71 72 Args: 73 offer_id: The unique offer identifier. 74 75 Returns: 76 The matching Offer. 77 78 Raises: 79 KeyError: When no offer with the given id exists. 80 """ 81 with self._conn.cursor() as cursor: 82 cursor.execute( 83 """ 84 SELECT offer_id, award_id 85 FROM offers 86 WHERE offer_id = %s 87 """, 88 (offer_id,), 89 ) 90 row = cursor.fetchone() 91 self._conn.commit() 92 93 if row is None: 94 raise KeyError(f"Offer with id {offer_id} not found") 95 return Offer( 96 offer_id=cast(str, row[0]), 97 award_id=cast(str, row[1]), 98 uri=None 99 )
Retrieve an offer by its identifier.
Args: offer_id: The unique offer identifier.
Returns: The matching Offer.
Raises: KeyError: When no offer with the given id exists.