Potentially fixed daily report
This commit is contained in:
@@ -299,6 +299,22 @@ async def lifespan(app: FastAPI):
|
||||
report_scheduler.set_stats_collector(stats_collector.collect_stats)
|
||||
_LOGGER.info("Stats collector initialized and hooked up to report scheduler")
|
||||
|
||||
# Send a test daily report on startup for testing
|
||||
_LOGGER.info("Sending test daily report on startup")
|
||||
try:
|
||||
stats = await stats_collector.collect_stats()
|
||||
success = await email_service.send_daily_report(
|
||||
recipients=report_scheduler.recipients,
|
||||
stats=stats,
|
||||
errors=None,
|
||||
)
|
||||
if success:
|
||||
_LOGGER.info("Test daily report sent successfully on startup")
|
||||
else:
|
||||
_LOGGER.error("Failed to send test daily report on startup")
|
||||
except Exception:
|
||||
_LOGGER.exception("Error sending test daily report on startup")
|
||||
|
||||
# Start daily report scheduler
|
||||
report_scheduler.start()
|
||||
_LOGGER.info("Daily report scheduler started")
|
||||
@@ -320,6 +336,11 @@ async def lifespan(app: FastAPI):
|
||||
email_handler.close()
|
||||
_LOGGER.info("Email alert handler closed")
|
||||
|
||||
# Shutdown email service thread pool
|
||||
if email_service:
|
||||
email_service.shutdown()
|
||||
_LOGGER.info("Email service shut down")
|
||||
|
||||
# Dispose engine
|
||||
await engine.dispose()
|
||||
_LOGGER.info("Application shutdown complete")
|
||||
@@ -711,6 +732,9 @@ async def process_generic_webhook_submission(
|
||||
name_prefix = form_data.get("anrede")
|
||||
language = form_data.get("sprache", "de")[:2]
|
||||
user_comment = form_data.get("nachricht", "")
|
||||
plz = form_data.get("plz", "")
|
||||
city = form_data.get("stadt", "")
|
||||
country = form_data.get("land", "")
|
||||
|
||||
# Parse dates - handle DD.MM.YYYY format
|
||||
start_date_str = form_data.get("anreise")
|
||||
@@ -790,9 +814,9 @@ async def process_generic_webhook_submission(
|
||||
"phone": phone_number if phone_number else None,
|
||||
"email_newsletter": False,
|
||||
"address_line": None,
|
||||
"city_name": None,
|
||||
"postal_code": None,
|
||||
"country_code": None,
|
||||
"city_name": city if city else None,
|
||||
"postal_code": plz if plz else None,
|
||||
"country_code": country if country else None,
|
||||
"gender": None,
|
||||
"birth_date": None,
|
||||
"language": language,
|
||||
|
||||
@@ -7,6 +7,7 @@ including error alerts and daily reports.
|
||||
import asyncio
|
||||
import smtplib
|
||||
import ssl
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
@@ -74,7 +75,9 @@ class EmailService:
|
||||
|
||||
"""
|
||||
self.config = config
|
||||
self._executor = None # Lazy-initialized thread pool for blocking SMTP
|
||||
# Create dedicated thread pool for SMTP operations (max 2 threads is enough for email)
|
||||
# This prevents issues with default executor in multi-process environments
|
||||
self._executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="smtp-")
|
||||
|
||||
async def send_email(
|
||||
self,
|
||||
@@ -114,9 +117,9 @@ class EmailService:
|
||||
if html_body:
|
||||
msg.attach(MIMEText(html_body, "html"))
|
||||
|
||||
# Send email in thread pool (SMTP is blocking)
|
||||
# Send email in dedicated thread pool (SMTP is blocking)
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, self._send_smtp, msg, recipients)
|
||||
await loop.run_in_executor(self._executor, self._send_smtp, msg, recipients)
|
||||
|
||||
_LOGGER.info("Email sent successfully to %s: %s", recipients, subject)
|
||||
return True
|
||||
@@ -333,6 +336,17 @@ class EmailService:
|
||||
|
||||
return html
|
||||
|
||||
def shutdown(self) -> None:
|
||||
"""Shutdown the email service and clean up thread pool.
|
||||
|
||||
This should be called during application shutdown to ensure
|
||||
proper cleanup of the thread pool executor.
|
||||
"""
|
||||
if self._executor:
|
||||
_LOGGER.info("Shutting down email service thread pool")
|
||||
self._executor.shutdown(wait=True, cancel_futures=False)
|
||||
_LOGGER.info("Email service thread pool shut down complete")
|
||||
|
||||
|
||||
def create_email_service(config: dict[str, Any]) -> EmailService | None:
|
||||
"""Create an email service from configuration.
|
||||
|
||||
Reference in New Issue
Block a user