feat: enhance error handling and configuration validation
Some checks failed
CI / lint-and-test (push) Failing after 27s
Some checks failed
CI / lint-and-test (push) Failing after 27s
- Added a global exception handler to log unhandled exceptions and return a generic 500 JSON response without exposing details to the client. - Updated the configuration to validate the `DATABASE_URL` format, ensuring it starts with `sqlite://` or `postgresql://`, and log warnings for invalid formats. - Introduced safe parsing for numeric environment variables (`HTTP_PORT`, `INIT_DATA_MAX_AGE_SECONDS`) with defaults on invalid values, including logging warnings for out-of-range values. - Enhanced the duty schedule parser to enforce limits on the number of schedule rows and the length of full names and duty strings, raising appropriate errors when exceeded. - Updated internationalization messages to include generic error responses for import failures and parsing issues, improving user experience. - Added unit tests to verify the new error handling and configuration validation behaviors.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Import duty-schedule: /import_duty_schedule (admin only). Two steps: handover time -> JSON file."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import duty_teller.config as config
|
||||
from telegram import Update
|
||||
@@ -16,6 +17,8 @@ from duty_teller.importers.duty_schedule import (
|
||||
from duty_teller.services.import_service import run_import
|
||||
from duty_teller.utils.handover import parse_handover_time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def import_duty_schedule_cmd(
|
||||
update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
@@ -80,9 +83,10 @@ async def handle_duty_schedule_document(
|
||||
try:
|
||||
result = parse_duty_schedule(raw)
|
||||
except DutyScheduleParseError as e:
|
||||
logger.warning("Duty schedule parse error: %s", e, exc_info=True)
|
||||
context.user_data.pop("awaiting_duty_schedule_file", None)
|
||||
context.user_data.pop("handover_utc_time", None)
|
||||
await update.message.reply_text(t(lang, "import.parse_error", error=str(e)))
|
||||
await update.message.reply_text(t(lang, "import.parse_error_generic"))
|
||||
return
|
||||
|
||||
def run_import_with_scope():
|
||||
@@ -95,7 +99,8 @@ async def handle_duty_schedule_document(
|
||||
None, run_import_with_scope
|
||||
)
|
||||
except Exception as e:
|
||||
await update.message.reply_text(t(lang, "import.import_error", error=str(e)))
|
||||
logger.exception("Import failed: %s", e)
|
||||
await update.message.reply_text(t(lang, "import.import_error_generic"))
|
||||
else:
|
||||
total = num_duty + num_unavailable + num_vacation
|
||||
unavailable_suffix = (
|
||||
|
||||
Reference in New Issue
Block a user