|
6 | 6 | from datetime import datetime, timedelta, timezone |
7 | 7 | import time |
8 | 8 | import base64 |
| 9 | +import traceback |
9 | 10 |
|
10 | 11 | from flask import Flask, render_template, request, redirect, url_for, jsonify, session, flash |
11 | 12 | from flask_pymongo import PyMongo |
|
16 | 17 | from pymongo.errors import PyMongoError |
17 | 18 |
|
18 | 19 | app = Flask(__name__) |
19 | | -app.config["MONGODB_URI"] = os.getenv("MONGODB_URI") |
20 | | -app.config['SESSION_TYPE'] = 'mongodb' |
| 20 | + |
| 21 | +# Load and validate MongoDB URI |
| 22 | +mongodb_uri = os.getenv("MONGODB_URI") |
| 23 | +if not mongodb_uri: |
| 24 | + print("ERROR: MONGODB_URI not found in environment variables") |
| 25 | + print("Available environment variables:") |
| 26 | + for key in sorted(os.environ.keys()): |
| 27 | + if 'MONGO' in key.upper() or 'DB' in key.upper(): |
| 28 | + print(f" {key}: {os.environ[key][:30]}...") |
| 29 | + raise ValueError("MONGODB_URI is required") |
| 30 | + |
| 31 | +print(f"MongoDB URI loaded: {mongodb_uri[:50]}...") |
| 32 | +app.config["MONGO_URI"] = mongodb_uri |
| 33 | +app.config['SESSION_TYPE'] = 'filesystem' # Changed from 'mongodb' to 'filesystem' to avoid session store issues |
21 | 34 | app.secret_key = os.getenv("SECRET_KEY", "traders_arena_secret_key") |
22 | | -mongo = PyMongo(app) |
| 35 | + |
| 36 | +# Initialize MongoDB |
| 37 | +try: |
| 38 | + mongo = PyMongo(app) |
| 39 | + print("PyMongo initialized successfully") |
| 40 | +except Exception as e: |
| 41 | + print(f"Error initializing PyMongo: {e}") |
| 42 | + raise |
| 43 | + |
23 | 44 | server_name = os.getenv("SERVER_NAME") |
24 | 45 | if server_name: |
25 | 46 | app.config["SERVER_NAME"] = server_name |
| 47 | + |
| 48 | +# Initialize Flask-Session after MongoDB |
26 | 49 | Session(app) |
27 | 50 |
|
28 | 51 | # MongoDB Collection Schemas and Validators |
@@ -74,65 +97,86 @@ def get_team_validator(): |
74 | 97 |
|
75 | 98 | # Initialize MongoDB collections with schemas and indexes |
76 | 99 | def init_mongodb(): |
| 100 | + with app.app_context(): |
| 101 | + try: |
| 102 | + # Test the connection first |
| 103 | + if mongo.db is None: |
| 104 | + raise Exception("MongoDB database connection is None - check your MONGO_URI") |
| 105 | + |
| 106 | + # Test basic connectivity |
| 107 | + result = mongo.db.command('ping') |
| 108 | + print(f"MongoDB ping successful: {result}") |
| 109 | + print(f"Connected to database: {mongo.db.name}") |
| 110 | + |
| 111 | + # Create collections with validation |
| 112 | + db = mongo.db |
| 113 | + |
| 114 | + # Competitions |
| 115 | + if "competitions" not in db.list_collection_names(): |
| 116 | + db.create_collection("competitions") |
| 117 | + db.command("collMod", "competitions", validator=get_competition_validator()) |
| 118 | + db.competitions.create_index([("competitionName", ASCENDING)], unique=True) |
| 119 | + db.competitions.create_index([("timeOfCreation", DESCENDING)]) |
| 120 | + |
| 121 | + # Stocks |
| 122 | + if "stocks" not in db.list_collection_names(): |
| 123 | + db.create_collection("stocks") |
| 124 | + db.command("collMod", "stocks", validator=get_stock_validator()) |
| 125 | + db.stocks.create_index([("competition_id", ASCENDING), ("name", ASCENDING)], unique=True) |
| 126 | + |
| 127 | + # Teams |
| 128 | + if "teams" not in db.list_collection_names(): |
| 129 | + db.create_collection("teams") |
| 130 | + db.command("collMod", "teams", validator=get_team_validator()) |
| 131 | + db.teams.create_index([("participant_id", ASCENDING)], unique=True) |
| 132 | + db.teams.create_index([("competition_id", ASCENDING), ("teamName", ASCENDING)], unique=True) |
| 133 | + |
| 134 | + # Rounds |
| 135 | + if "rounds" not in db.list_collection_names(): |
| 136 | + db.create_collection("rounds") |
| 137 | + db.rounds.create_index([ |
| 138 | + ("competition_id", ASCENDING), |
| 139 | + ("stock_id", ASCENDING), |
| 140 | + ("round_number", ASCENDING) |
| 141 | + ]) |
| 142 | + |
| 143 | + # Transactions |
| 144 | + if "transactions" not in db.list_collection_names(): |
| 145 | + db.create_collection("transactions") |
| 146 | + db.transactions.create_index([("competition_id", ASCENDING), ("timeOfTransaction", DESCENDING)]) |
| 147 | + db.transactions.create_index([("buyer_team", ASCENDING)]) |
| 148 | + db.transactions.create_index([("seller_team", ASCENDING)]) |
| 149 | + |
| 150 | + # Stock Purchases |
| 151 | + if "stock_purchases" not in db.list_collection_names(): |
| 152 | + db.create_collection("stock_purchases") |
| 153 | + db.stock_purchases.create_index([("competition_id", ASCENDING)]) |
| 154 | + db.stock_purchases.create_index([("team", ASCENDING)]) |
| 155 | + db.stock_purchases.create_index([("timeIssued", DESCENDING)]) |
| 156 | + |
| 157 | + # Stock News |
| 158 | + if "stock_news" not in db.list_collection_names(): |
| 159 | + db.create_collection("stock_news") |
| 160 | + db.stock_news.create_index([("competition_id", ASCENDING), ("roundNumber", ASCENDING)]) |
| 161 | + |
| 162 | + print("MongoDB initialized successfully with schemas and indexes") |
| 163 | + except PyMongoError as e: |
| 164 | + print(f"Error initializing MongoDB: {e}") |
| 165 | + raise |
| 166 | + |
| 167 | +# Initialize MongoDB on startup - wrap in a function to handle errors gracefully |
| 168 | +def initialize_app(): |
77 | 169 | try: |
78 | | - # Create collections with validation |
79 | | - db = mongo.db |
80 | | - |
81 | | - # Competitions |
82 | | - if "competitions" not in db.list_collection_names(): |
83 | | - db.create_collection("competitions") |
84 | | - db.command("collMod", "competitions", validator=get_competition_validator()) |
85 | | - db.competitions.create_index([("competitionName", ASCENDING)], unique=True) |
86 | | - db.competitions.create_index([("timeOfCreation", DESCENDING)]) |
87 | | - |
88 | | - # Stocks |
89 | | - if "stocks" not in db.list_collection_names(): |
90 | | - db.create_collection("stocks") |
91 | | - db.command("collMod", "stocks", validator=get_stock_validator()) |
92 | | - db.stocks.create_index([("competition_id", ASCENDING), ("name", ASCENDING)], unique=True) |
93 | | - |
94 | | - # Teams |
95 | | - if "teams" not in db.list_collection_names(): |
96 | | - db.create_collection("teams") |
97 | | - db.command("collMod", "teams", validator=get_team_validator()) |
98 | | - db.teams.create_index([("participant_id", ASCENDING)], unique=True) |
99 | | - db.teams.create_index([("competition_id", ASCENDING), ("teamName", ASCENDING)], unique=True) |
100 | | - |
101 | | - # Rounds |
102 | | - if "rounds" not in db.list_collection_names(): |
103 | | - db.create_collection("rounds") |
104 | | - db.rounds.create_index([ |
105 | | - ("competition_id", ASCENDING), |
106 | | - ("stock_id", ASCENDING), |
107 | | - ("round_number", ASCENDING) |
108 | | - ]) |
109 | | - |
110 | | - # Transactions |
111 | | - if "transactions" not in db.list_collection_names(): |
112 | | - db.create_collection("transactions") |
113 | | - db.transactions.create_index([("competition_id", ASCENDING), ("timeOfTransaction", DESCENDING)]) |
114 | | - db.transactions.create_index([("buyer_team", ASCENDING)]) |
115 | | - db.transactions.create_index([("seller_team", ASCENDING)]) |
116 | | - |
117 | | - # Stock Purchases |
118 | | - if "stock_purchases" not in db.list_collection_names(): |
119 | | - db.create_collection("stock_purchases") |
120 | | - db.stock_purchases.create_index([("competition_id", ASCENDING)]) |
121 | | - db.stock_purchases.create_index([("team", ASCENDING)]) |
122 | | - db.stock_purchases.create_index([("timeIssued", DESCENDING)]) |
123 | | - |
124 | | - # Stock News |
125 | | - if "stock_news" not in db.list_collection_names(): |
126 | | - db.create_collection("stock_news") |
127 | | - db.stock_news.create_index([("competition_id", ASCENDING), ("roundNumber", ASCENDING)]) |
128 | | - |
129 | | - print("MongoDB initialized successfully with schemas and indexes") |
130 | | - except PyMongoError as e: |
131 | | - print(f"Error initializing MongoDB: {e}") |
132 | | - raise |
| 170 | + init_mongodb() |
| 171 | + print("Application initialized successfully") |
| 172 | + except Exception as e: |
| 173 | + print(f"Warning: Could not initialize MongoDB collections: {e}") |
| 174 | + print("Application will continue to run, but database features may not work properly") |
| 175 | + print("Please check your MONGODB_URI and internet connectivity") |
133 | 176 |
|
134 | | -# Initialize MongoDB on startup |
135 | | -init_mongodb() |
| 177 | +# Call initialization only when not in debug/reloader mode |
| 178 | +if not os.environ.get('WERKZEUG_RUN_MAIN'): |
| 179 | + initialize_app() |
136 | 180 |
|
137 | 181 | def generate_team_id(): |
138 | 182 | """Generate a random 6-character alphanumeric ID""" |
@@ -1055,7 +1099,6 @@ def results(competition_id): |
1055 | 1099 | except Exception as e: |
1056 | 1100 | print(f"Error in results: {e}") |
1057 | 1101 | print(f"Error type: {type(e)}") |
1058 | | - import traceback |
1059 | 1102 | traceback.print_exc() |
1060 | 1103 | flash(f"An error occurred: {str(e)}", "error") |
1061 | 1104 | return render_template( |
@@ -1223,7 +1266,6 @@ def transactions(competition_id): |
1223 | 1266 | except Exception as e: |
1224 | 1267 | print(f"Error in trading page: {e}") |
1225 | 1268 | print(f"Error type: {type(e)}") |
1226 | | - import traceback |
1227 | 1269 | traceback.print_exc() |
1228 | 1270 | flash(f"An error occurred: {str(e)}", "error") |
1229 | 1271 | # Render the template with error instead of redirecting |
@@ -1357,7 +1399,6 @@ def stocksIssue(competition_id): |
1357 | 1399 | except Exception as e: |
1358 | 1400 | print(f"Error recording stock purchase: {e}") |
1359 | 1401 | print(f"Error type: {type(e)}") |
1360 | | - import traceback |
1361 | 1402 | traceback.print_exc() |
1362 | 1403 |
|
1363 | 1404 | # Update portfolio trend |
@@ -1398,7 +1439,6 @@ def stocksIssue(competition_id): |
1398 | 1439 | except Exception as e: |
1399 | 1440 | print(f"Error in initial buying: {e}") |
1400 | 1441 | print(f"Error type: {type(e)}") |
1401 | | - import traceback |
1402 | 1442 | traceback.print_exc() |
1403 | 1443 | flash(f"An error occurred: {str(e)}", "error") |
1404 | 1444 | return render_template( |
@@ -1527,7 +1567,6 @@ def complete_competition(): |
1527 | 1567 | except Exception as e: |
1528 | 1568 | print(f"Error completing competition: {e}") |
1529 | 1569 | print(f"Error type: {type(e)}") |
1530 | | - import traceback |
1531 | 1570 | traceback.print_exc() |
1532 | 1571 | flash(f"Failed to complete competition: {str(e)}", "error") |
1533 | 1572 | return redirect("/dashboard") |
@@ -1676,7 +1715,6 @@ def next_round(): |
1676 | 1715 | except Exception as e: |
1677 | 1716 | print(f"Error advancing round: {e}") |
1678 | 1717 | print(f"Error type: {type(e)}") |
1679 | | - import traceback |
1680 | 1718 | traceback.print_exc() |
1681 | 1719 | flash(f"Failed to advance to next round: {str(e)}", "error") |
1682 | 1720 | return redirect("/dashboard") |
|
0 commit comments