fix(danding_points): improve conn management in api.py
- Read methods (get_balance/get_transactions/get_ranking): add try/except/finally - Write methods (add/spend/set_points): add rollback() before early return conn.close() - Prevents connection leaks on exceptions and early returns
This commit is contained in:
@@ -59,6 +59,7 @@ class PointsAPI:
|
||||
new_balance = current_balance + amount
|
||||
if self.config.POINTS_MAX_BALANCE > 0:
|
||||
if new_balance > self.config.POINTS_MAX_BALANCE:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
return False, current_balance
|
||||
|
||||
@@ -130,6 +131,7 @@ class PointsAPI:
|
||||
|
||||
# Check sufficient balance
|
||||
if current_balance < amount:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
return False, current_balance
|
||||
|
||||
@@ -198,6 +200,7 @@ class PointsAPI:
|
||||
|
||||
# If new value equals old value, return without writing
|
||||
if current_balance == amount:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
return True, amount
|
||||
|
||||
@@ -250,20 +253,25 @@ class PointsAPI:
|
||||
|
||||
def _get():
|
||||
conn = self.db.get_connection()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, user_id, amount, balance_after, source, reason, created_at
|
||||
FROM point_transactions
|
||||
WHERE user_id = ?
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
""",
|
||||
(user_id, limit, offset),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
return [dict(row) for row in rows]
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, user_id, amount, balance_after, source, reason, created_at
|
||||
FROM point_transactions
|
||||
WHERE user_id = ?
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
""",
|
||||
(user_id, limit, offset),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
except Exception as e:
|
||||
logger.error(f"get_transactions failed for {user_id}: {e}")
|
||||
return []
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
return await asyncio.to_thread(_get)
|
||||
|
||||
@@ -281,23 +289,27 @@ class PointsAPI:
|
||||
|
||||
def _get():
|
||||
conn = self.db.get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
order_column = "points" if order_by == "points" else "total_earned"
|
||||
query = f"""
|
||||
SELECT
|
||||
RANK() OVER (ORDER BY {order_column} DESC) as rank,
|
||||
user_id,
|
||||
points,
|
||||
total_earned,
|
||||
total_spent
|
||||
FROM user_points
|
||||
ORDER BY {order_column} DESC, user_id ASC
|
||||
LIMIT ?
|
||||
"""
|
||||
cursor.execute(query, (limit,))
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
return [dict(row) for row in rows]
|
||||
try:
|
||||
cursor = conn.cursor()
|
||||
order_column = "points" if order_by == "points" else "total_earned"
|
||||
query = f"""
|
||||
SELECT
|
||||
RANK() OVER (ORDER BY {order_column} DESC) as rank,
|
||||
user_id,
|
||||
points,
|
||||
total_earned,
|
||||
total_spent
|
||||
FROM user_points
|
||||
ORDER BY {order_column} DESC, user_id ASC
|
||||
LIMIT ?
|
||||
"""
|
||||
cursor.execute(query, (limit,))
|
||||
rows = cursor.fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
except Exception as e:
|
||||
logger.error(f"get_ranking failed: {e}")
|
||||
return []
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
return await asyncio.to_thread(_get)
|
||||
|
||||
Reference in New Issue
Block a user