1+ import logging
12import os
3+ from contextlib import contextmanager
24from typing import Optional , BinaryIO , Dict , Any , Tuple , List
35
46import boto3
5- import psycopg2
67import psycopg2 .extras
78from botocore .client import Config
89from botocore .exceptions import ClientError
10+ from sqlalchemy import create_engine
11+ from sqlalchemy .orm import sessionmaker , class_mapper
12+
13+ from database .db_models import Base
14+
15+ logger = logging .getLogger ("database.client" )
916
1017
1118class PostgresClient :
@@ -21,22 +28,22 @@ def __init__(self):
2128 self .host = os .getenv ('POSTGRES_HOST' , 'localhost' )
2229 self .user = os .getenv ('POSTGRES_USER' )
2330 self .password = os .getenv ('POSTGRES_PASSWORD' )
24- self .database = os .getenv ('POSTGRES_DB' , 'agent_engine ' )
31+ self .database = os .getenv ('POSTGRES_DB' , 'nexent ' )
2532 self .port = os .getenv ('POSTGRES_PORT' , 5432 )
26-
27- def get_connection ( self ):
28- """Get database connection"""
29- try :
30- conn = psycopg2 . connect ( host = self . host , user = self . user , password = self . password , dbname = self .database ,
31- port = self .port )
32- return conn
33- except Exception as e :
34- raise Exception ( f"Database connection failed: { str ( e ) } " )
35-
36- def close_connection ( self , conn ):
37- """Close database connection"""
38- if conn :
39- conn . close ( )
33+ self . engine = create_engine ( "postgresql://" ,
34+ connect_args = {
35+ "host" : self . host ,
36+ "user" : self . user ,
37+ " password" : self .password ,
38+ "database" : self .database ,
39+ "port" : self . port ,
40+ "client_encoding" : "utf8"
41+ },
42+ echo = True ,
43+ pool_size = 10 ,
44+ pool_pre_ping = True ,
45+ pool_timeout = 30 )
46+ self . session_maker = sessionmaker ( bind = self . engine )
4047
4148 def clean_string_values (self , data : Dict [str , Any ]) -> Dict [str , Any ]:
4249 """Ensure all strings are UTF-8 encoded"""
@@ -211,3 +218,23 @@ def delete_file(self, object_name: str, bucket: Optional[str] = None) -> Tuple[b
211218
212219# Create global MinIO client instance
213220minio_client = MinioClient ()
221+
222+ @contextmanager
223+ def get_db_session ():
224+ """Provide a transactional scope around a series of operations."""
225+ session = db_client .session_maker ()
226+ try :
227+ yield session
228+ session .commit ()
229+ except Exception as e :
230+ session .rollback ()
231+ logger .error (f"Database operation failed: { str (e )} " )
232+ raise e
233+ finally :
234+ session .close ()
235+
236+ def as_dict (obj ):
237+ if isinstance (obj , Base ):
238+ return {c .key : getattr (obj , c .key ) for c in class_mapper (obj .__class__ ).columns }
239+ # noinspection PyProtectedMember
240+ return dict (obj ._mapping )
0 commit comments