Viernes
Viernes
error connecting in 'pool-230': connection failed: FATAL: sorry, too many clients
already
error connecting in 'pool-276': connection failed: FATAL: sorry, too many clients
already
reconnection attempt in pool 'pool-276' failed after 30 sec
error connecting in 'pool-296': connection failed: FATAL: sorry, too many clients
already
error connecting in 'pool-278': connection failed: FATAL: sorry, too many clients
already
reconnection attempt in pool 'pool-278' failed after 30 sec
error connecting in 'pool-290': connection failed: FATAL: sorry, too many clients
already
reconnection attempt in pool 'pool-290' failed after 30 sec
error connecting in 'pool-310': connection failed: FATAL: sorry, too many clients
already
reconnection attempt in pool 'pool-310' failed after 30 sec
import sys, os
import logging, subprocess
from contextlib import contextmanager
from psycopg_pool import ConnectionPool
log = logging.getLogger()
def __init__(
self,
environment: str,
user_id: str,
*,
host: Optional[str] = None,
port: Optional[str] = None,
user: Optional[str] = None,
password: Optional[str] = None,
database: Optional[str] = None,
) -> None:
cfg = config().get(environment)
if not cfg:
raise Exception(f"invalid configuration for environment {environment}")
def query(self, query: str, schema: str = "public", fetch: bool = True):
# Connect to an existing database
with self.pool.connection() as conn:
# Open a cursor to perform database operations
with conn.cursor() as cur:
# Execute a command: this creates a new table
cur.execute(f"SET search_path TO \"{schema}\";")
cur.execute(query)
conn.commit()
try:
out = cur.fetchall() if fetch else None
except psycopg.ProgrammingError as e:
log.warning(f"Couldn't fetch results. Reason: {e}")
out = None
# finally:
# if not cur.closed:
# cur.close()
return out
try:
out = cur.fetchall() if fetch else None
except psycopg.ProgrammingError as e:
log.warning(f"Couldn't fetch results. Reason: {e}")
out = None
finally:
if not cur.closed:
cur.close()
return out
@contextmanager
def transaction(self, debug: bool = False):
if debug:
log.info("""
#############################################
# Transaction in Debug Mode #
#############################################""")
else:
log.info("""
#############################################
# Starting Postgres transaction #
#############################################""")
with self.pool.connection() as conn:
with conn.cursor() as cursor:
try:
self.cursor = cursor
yield self
if not debug:
conn.commit()
log.debug("Transaction committed!")
else:
conn.rollback()
log.info("""
#############################################
# Transaction rollbacked #
#############################################""")
except:
conn.rollback()
log.debug("Transaction rollbacked!")
raise
finally:
self.cursor = None
@contextmanager
def cli(self) -> Iterator[psycopg.Cursor]:
# no crea una transaccion, es lo mas parecido a tirar comandos desde la cli
de postgres sin abrir transaccion.
# util para comandos sobre databases que no puedan estar dentro de una
transaccion
with self.pool.connection() as conn:
try:
cursor = conn.cursor()
try:
yield cursor
finally:
if cursor:
cursor.close()
finally:
if conn:
conn.close()
class PgUtils:
if pg_dump.returncode != 0:
raise Exception(f"failed to dump database: {pg_dump.returncode}
{pg_dump.stderr} {pg_dump.stdout}")
if pg_restore.returncode != 0:
raise Exception(f"failed to restore database: {pg_restore.returncode}
{pg_restore.stderr} {pg_restore.stdout}")
@staticmethod
def assert_secure_password(p: str):
if not os.getenv("PGPASSWORD") == p:
raise Exception("environment variable PGPASSWORD must be set in order
to use postgres clients safely")