fix: implement proper database connection context manager
- Created DBConnection class to manage database connections - Each connection is now properly created and closed - Removed global connection pool to fix thread issues
This commit is contained in:
parent
a0533e1d78
commit
a3ecf3a606
|
|
@ -105,17 +105,27 @@ ha_mqtt = HomeAssistantMQTT()
|
||||||
DB_PATH = "gatekeeper.db" # Database file path
|
DB_PATH = "gatekeeper.db" # Database file path
|
||||||
|
|
||||||
# Database connection handling
|
# Database connection handling
|
||||||
async def get_db():
|
class DBConnection:
|
||||||
|
def __init__(self):
|
||||||
|
self.db = None
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
self.db = await aiosqlite.connect(DB_PATH)
|
||||||
|
self.db.row_factory = aiosqlite.Row
|
||||||
|
return self.db
|
||||||
|
|
||||||
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
await self.db.close()
|
||||||
|
|
||||||
|
def get_db():
|
||||||
"""Get a new database connection"""
|
"""Get a new database connection"""
|
||||||
db = await aiosqlite.connect(DB_PATH)
|
return DBConnection()
|
||||||
db.row_factory = aiosqlite.Row
|
|
||||||
return db
|
|
||||||
|
|
||||||
# Set up MQTT event logging
|
# Set up MQTT event logging
|
||||||
async def log_mqtt_event(action: str, success: bool = True):
|
async def log_mqtt_event(action: str, success: bool = True):
|
||||||
"""Log MQTT events to the database and log file"""
|
"""Log MQTT events to the database and log file"""
|
||||||
logger.info(f"MQTT Event - {action} (Success: {success})")
|
logger.info(f"MQTT Event - {action} (Success: {success})")
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
||||||
(datetime.utcnow().isoformat(), action, "MQTT", success)
|
(datetime.utcnow().isoformat(), action, "MQTT", success)
|
||||||
|
|
@ -188,7 +198,7 @@ async def update_gate_status():
|
||||||
logger.info(f"Gate status changed to: {'open' if current_status else 'closed'}")
|
logger.info(f"Gate status changed to: {'open' if current_status else 'closed'}")
|
||||||
logger.debug("Updating database with new status")
|
logger.debug("Updating database with new status")
|
||||||
|
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO gate_status (timestamp) VALUES (?)",
|
"INSERT INTO gate_status (timestamp) VALUES (?)",
|
||||||
(timestamp.isoformat(),)
|
(timestamp.isoformat(),)
|
||||||
|
|
@ -258,7 +268,7 @@ async def check_auto_close():
|
||||||
logger.warning(f"Gate has been open for {time_open:.1f} seconds, auto-closing")
|
logger.warning(f"Gate has been open for {time_open:.1f} seconds, auto-closing")
|
||||||
timestamp = current_time.isoformat()
|
timestamp = current_time.isoformat()
|
||||||
|
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
||||||
(timestamp, "auto-close", "system", True)
|
(timestamp, "auto-close", "system", True)
|
||||||
|
|
@ -314,7 +324,7 @@ async def trigger():
|
||||||
current_status = GPIO.input(settings.gpio.statusPin) == GPIO.HIGH
|
current_status = GPIO.input(settings.gpio.statusPin) == GPIO.HIGH
|
||||||
|
|
||||||
# Log event
|
# Log event
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
||||||
(timestamp, "trigger gate", "api", success)
|
(timestamp, "trigger gate", "api", success)
|
||||||
|
|
@ -333,7 +343,7 @@ async def get_status():
|
||||||
settings = app.state.current_settings or Settings()
|
settings = app.state.current_settings or Settings()
|
||||||
is_open = GPIO.input(settings.gpio.statusPin) == GPIO.HIGH
|
is_open = GPIO.input(settings.gpio.statusPin) == GPIO.HIGH
|
||||||
|
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
cursor = await db.execute(
|
cursor = await db.execute(
|
||||||
"SELECT timestamp FROM gate_status ORDER BY timestamp DESC LIMIT 1"
|
"SELECT timestamp FROM gate_status ORDER BY timestamp DESC LIMIT 1"
|
||||||
)
|
)
|
||||||
|
|
@ -348,7 +358,7 @@ async def get_status():
|
||||||
@app.get("/api/events")
|
@app.get("/api/events")
|
||||||
async def get_events(limit: int = 10, offset: int = 0):
|
async def get_events(limit: int = 10, offset: int = 0):
|
||||||
"""Get recent gate events with pagination"""
|
"""Get recent gate events with pagination"""
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
db.row_factory = aiosqlite.Row
|
db.row_factory = aiosqlite.Row
|
||||||
|
|
||||||
# Get total count
|
# Get total count
|
||||||
|
|
@ -375,7 +385,7 @@ async def get_events(limit: int = 10, offset: int = 0):
|
||||||
@app.get("/api/settings")
|
@app.get("/api/settings")
|
||||||
async def get_settings():
|
async def get_settings():
|
||||||
"""Get current settings"""
|
"""Get current settings"""
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
cursor = await db.execute("SELECT key, value FROM settings")
|
cursor = await db.execute("SELECT key, value FROM settings")
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
settings = {}
|
settings = {}
|
||||||
|
|
@ -408,7 +418,7 @@ async def get_settings():
|
||||||
async def update_settings(settings: Settings):
|
async def update_settings(settings: Settings):
|
||||||
"""Update settings"""
|
"""Update settings"""
|
||||||
try:
|
try:
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
# Update each setting
|
# Update each setting
|
||||||
for key, value in settings.dict().items():
|
for key, value in settings.dict().items():
|
||||||
await db.execute(
|
await db.execute(
|
||||||
|
|
@ -458,7 +468,7 @@ async def update_settings(settings: Settings):
|
||||||
return {"success": True}
|
return {"success": True}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log failure event
|
# Log failure event
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
"INSERT INTO events (timestamp, action, source, success) VALUES (?, ?, ?, ?)",
|
||||||
(
|
(
|
||||||
|
|
@ -503,7 +513,7 @@ def setup_gpio():
|
||||||
# Database functions
|
# Database functions
|
||||||
async def init_db():
|
async def init_db():
|
||||||
"""Initialize the SQLite database"""
|
"""Initialize the SQLite database"""
|
||||||
async with await get_db() as db:
|
async with get_db() as db:
|
||||||
# Create events table
|
# Create events table
|
||||||
await db.execute("""
|
await db.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS events (
|
CREATE TABLE IF NOT EXISTS events (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue