Skip to content

Commit fe13b6e

Browse files
authored
Merge pull request #9 from fapulito/csv_output
Database Pooling Improved
2 parents bb2fbdd + 918ce46 commit fe13b6e

2 files changed

Lines changed: 61 additions & 13 deletions

File tree

api/index.py

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@
77
import json
88
import datetime
99
import stripe
10+
import logging
1011
from functools import wraps
11-
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash
12+
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, send_from_directory
1213
from flask_login import LoginManager, current_user, login_required, login_user, logout_user, UserMixin
1314
from flask_sqlalchemy import SQLAlchemy
1415
from dotenv import load_dotenv
1516
from botocore.client import Config
1617

18+
# Reduce AWS SDK logging noise
19+
logging.getLogger('botocore').setLevel(logging.WARNING)
20+
logging.getLogger('boto3').setLevel(logging.WARNING)
21+
logging.getLogger('urllib3').setLevel(logging.WARNING)
22+
1723
# --- 1. Initialize Extensions (globally) ---
1824
db = SQLAlchemy()
1925
login_manager = LoginManager()
@@ -43,6 +49,15 @@ def create_app():
4349
app.secret_key = os.environ.get('SECRET_KEY')
4450
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL')
4551
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
52+
# Add connection pool settings for better reliability
53+
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
54+
'pool_pre_ping': True, # Verify connections before use
55+
'pool_recycle': 300, # Recycle connections every 5 minutes
56+
'connect_args': {
57+
'connect_timeout': 10,
58+
'sslmode': 'require'
59+
}
60+
}
4661
# Stripe configuration
4762
stripe.api_key = os.environ.get('STRIPE_SECRET_KEY')
4863
STRIPE_WEBHOOK_SECRET = os.environ.get('STRIPE_WEBHOOK_SECRET')
@@ -196,18 +211,36 @@ def callback():
196211

197212
print(f"Creating/finding user: {users_email}")
198213

199-
user = User.query.filter_by(google_id=unique_id).first()
200-
if not user:
201-
print("Creating new user")
202-
user = User(google_id=unique_id, name=users_name, email=users_email)
203-
db.session.add(user)
204-
db.session.commit()
205-
else:
206-
print("User found, logging in")
207-
208-
login_user(user)
209-
print("User logged in successfully, redirecting to index")
210-
return redirect(url_for("index"))
214+
# Database operations with retry logic for connection issues
215+
max_retries = 3
216+
for attempt in range(max_retries):
217+
try:
218+
user = User.query.filter_by(google_id=unique_id).first()
219+
if not user:
220+
print("Creating new user")
221+
user = User(google_id=unique_id, name=users_name, email=users_email)
222+
db.session.add(user)
223+
db.session.commit()
224+
else:
225+
print("User found, logging in")
226+
227+
login_user(user)
228+
print("User logged in successfully, redirecting to index")
229+
return redirect(url_for("index"))
230+
231+
except Exception as db_error:
232+
print(f"Database attempt {attempt + 1} failed: {db_error}")
233+
if attempt < max_retries - 1:
234+
# Rollback and retry
235+
db.session.rollback()
236+
import time
237+
time.sleep(1) # Wait 1 second before retry
238+
continue
239+
else:
240+
# Final attempt failed
241+
db.session.rollback()
242+
print(f"All database attempts failed for user {users_email}")
243+
return "Database temporarily unavailable. Please try signing in again in a moment.", 503
211244

212245
print("Email not verified by Google")
213246
return "User email not available or not verified by Google.", 400
@@ -243,6 +276,17 @@ def decorated_function(*args, **kwargs):
243276
return decorated_function
244277

245278
# --- Core Application Routes ---
279+
@app.route('/favicon.ico')
280+
def favicon():
281+
"""Serve favicon from root directory"""
282+
try:
283+
# Try to serve from root directory (one level up from api/)
284+
return send_from_directory(os.path.join(app.root_path, '..'), 'favicon.ico', mimetype='image/vnd.microsoft.icon')
285+
except Exception as e:
286+
print(f"Favicon error: {e}")
287+
# Return a 204 No Content response to prevent browser errors
288+
return '', 204
289+
246290
@app.route('/')
247291
@login_required
248292
def index():

vercel.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
}
77
],
88
"routes": [
9+
{
10+
"src": "/favicon.ico",
11+
"dest": "/favicon.ico"
12+
},
913
{
1014
"src": "/(.*)",
1115
"dest": "api/index.py"

0 commit comments

Comments
 (0)