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:
2026-05-09 23:34:07 +08:00
parent e94161e802
commit 14397ab645

View File

@@ -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)