Add db connection pooling

This commit is contained in:
Peter Stockings
2025-07-23 21:58:43 +10:00
parent b5acb9e93e
commit a4c29e0d8f
3 changed files with 47 additions and 32 deletions

4
app.py
View File

@@ -204,3 +204,7 @@ if __name__ == '__main__':
# Bind to PORT if defined, otherwise default to 5000. # Bind to PORT if defined, otherwise default to 5000.
port = int(os.environ.get('PORT', 5000)) port = int(os.environ.get('PORT', 5000))
app.run(host='127.0.0.1', port=port) app.run(host='127.0.0.1', port=port)
@app.teardown_appcontext
def teardown_db(exception):
db.close_conn()

74
db.py
View File

@@ -1,52 +1,62 @@
import json import json
import os import os
import psycopg2 import psycopg2
from psycopg2 import pool
from psycopg2.extras import RealDictCursor from psycopg2.extras import RealDictCursor
from urllib.parse import urlparse from urllib.parse import urlparse
from flask import g from flask import g
class DataBase(): class DataBase():
def __init__(self, app=None): def __init__(self):
self.pool = None
def init_app(self, app):
db_url = urlparse(os.environ['DATABASE_URL']) db_url = urlparse(os.environ['DATABASE_URL'])
# if db_url is null then throw error
if not db_url: if not db_url:
raise Exception("No DATABASE_URL environment variable set") raise Exception("No DATABASE_URL environment variable set")
self.pool = psycopg2.pool.SimpleConnectionPool(
1, 20,
database=db_url.path[1:],
user=db_url.username,
password=db_url.password,
host=db_url.hostname,
port=db_url.port
)
app.teardown_appcontext(self.close_conn)
def getDB(self): def get_conn(self):
db = getattr(g, 'database', None) if 'db_conn' not in g:
if db is None: g.db_conn = self.pool.getconn()
db_url = urlparse(os.environ['DATABASE_URL']) return g.db_conn
g.database = psycopg2.connect(
database=db_url.path[1:],
user=db_url.username,
password=db_url.password,
host=db_url.hostname,
port=db_url.port
)
db = g.database
return db
def close_connection(exception): def close_conn(self, e=None):
db = getattr(g, 'database', None) db_conn = g.pop('db_conn', None)
if db is not None: if db_conn is not None:
db.close() self.pool.putconn(db_conn)
def close_all_connections(self):
if self.pool:
self.pool.closeall()
def execute(self, query, args=(), one=False, commit=False): def execute(self, query, args=(), one=False, commit=False):
conn = self.getDB() conn = self.get_conn()
cur = conn.cursor(cursor_factory=RealDictCursor) cur = conn.cursor(cursor_factory=RealDictCursor)
cur.execute(query, args) try:
rv = None cur.execute(query, args)
if cur.description is not None: rv = None
rv = cur.fetchall() if cur.description is not None:
if commit: rv = cur.fetchall()
try: if commit:
conn.commit() conn.commit()
except: return (rv[0] if rv else None) if one else rv
conn.rollback() except Exception as e:
cur.close() conn.rollback()
raise e
return (rv[0] if rv else None) if one else rv finally:
cur.close()
def get_http_functions_for_user(self, user_id): def get_http_functions_for_user(self, user_id):
http_functions = self.execute( http_functions = self.execute(
'SELECT id, user_id, NAME, script_content, invoked_count, environment_info, is_public, log_request, log_response, version_number FROM http_functions WHERE user_id=%s ORDER by id DESC', [user_id]) 'SELECT id, user_id, NAME, script_content, invoked_count, environment_info, is_public, log_request, log_response, version_number FROM http_functions WHERE user_id=%s ORDER by id DESC', [user_id])

View File

@@ -16,6 +16,7 @@ environment = Environment(
def init_app(app): def init_app(app):
htmx.init_app(app) htmx.init_app(app)
db.init_app(app)
# Add all Flask's default Jinja2 globals and filters # Add all Flask's default Jinja2 globals and filters
environment.globals.update( environment.globals.update(