mirror of
https://github.com/sassanix/Warracker.git
synced 2026-01-05 04:59:31 -06:00
Fixes & Enhancements * Resolved five critical Apprise notification issues: • Ensured configuration reload during scheduled jobs • Fixed warranty data fetching for Apprise-only users • Refactored notification dispatch logic with dedicated helpers • Corrected handler scoping via Flask app context • Wrapped scheduler jobs with Flask app context to prevent context errors → Verified: Scheduled Apprise notifications now work reliably for "Apprise only" and "Both" channels. * Added support for SMTP\_FROM\_ADDRESS environment variable, allowing sender address customization independent of SMTP username. (PR #115) * Fixed duplicate scheduled notifications in multi-worker environments: • Strengthened should\_run\_scheduler() logic • Now guarantees exactly one scheduler instance across all Gunicorn modes. * Fixed stale database connection handling in scheduled jobs: • Fresh connection acquired each run, properly released via try/finally • Eliminates "server closed the connection" errors. * Definitive scheduler logic fix for all memory modes (ultra-light, optimized, performance): • Single-worker runs scheduler if GUNICORN\_WORKER\_ID is unset • Multi-worker: only worker 0 runs scheduler. Impact * Apprise and Email notifications are now stable, reliable, and production-ready * No more duplicate or missed notifications across all memory modes * Improved system efficiency and robustness
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
# backend/extensions.py
|
|
import logging
|
|
from authlib.integrations.flask_client import OAuth
|
|
from flask_cors import CORS
|
|
from flask_bcrypt import Bcrypt
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Initialize extensions without app instance
|
|
oauth = OAuth()
|
|
cors = CORS()
|
|
bcrypt = Bcrypt()
|
|
babel = None # Will be initialized in initialize_extensions
|
|
db_pool = None # Database connection pool
|
|
|
|
def initialize_extensions(app):
|
|
"""Initialize all extensions with the Flask app object."""
|
|
global babel, db_pool
|
|
|
|
logger.info("Initializing Flask extensions...")
|
|
|
|
# Initialize OAuth
|
|
oauth.init_app(app)
|
|
logger.info("OAuth initialized")
|
|
|
|
# Initialize CORS with credentials support
|
|
cors.init_app(app, supports_credentials=True)
|
|
logger.info("CORS initialized")
|
|
|
|
# Initialize Bcrypt
|
|
bcrypt.init_app(app)
|
|
logger.info("Bcrypt initialized")
|
|
|
|
# Initialize Babel for localization
|
|
try:
|
|
from .localization import init_babel, get_current_language
|
|
babel = init_babel(app)
|
|
logger.info("Babel localization initialized successfully")
|
|
except ImportError:
|
|
try:
|
|
from localization import init_babel, get_current_language
|
|
babel = init_babel(app)
|
|
logger.info("Babel localization initialized successfully")
|
|
except ImportError as e:
|
|
logger.error(f"Failed to initialize localization: {e}")
|
|
babel = None
|
|
|
|
# Initialize the database connection pool
|
|
try:
|
|
from .db_handler import init_db_pool
|
|
db_pool = init_db_pool()
|
|
logger.info("Database connection pool initialized successfully")
|
|
except ImportError:
|
|
try:
|
|
from db_handler import init_db_pool
|
|
db_pool = init_db_pool()
|
|
logger.info("Database connection pool initialized successfully")
|
|
except ImportError as e:
|
|
logger.critical(f"CRITICAL: Failed to initialize database pool: {e}")
|
|
raise
|
|
|
|
# Initialize Apprise notification handler
|
|
try:
|
|
try:
|
|
from .apprise_handler import AppriseNotificationHandler
|
|
except ImportError:
|
|
from apprise_handler import AppriseNotificationHandler
|
|
|
|
apprise_handler = AppriseNotificationHandler()
|
|
app.config['APPRISE_HANDLER'] = apprise_handler
|
|
app.config['APPRISE_AVAILABLE'] = True
|
|
logger.info("Apprise notification handler initialized successfully")
|
|
except ImportError as e:
|
|
app.config['APPRISE_HANDLER'] = None
|
|
app.config['APPRISE_AVAILABLE'] = False
|
|
logger.warning(f"Apprise not available: {e}. Notification features will be disabled.")
|
|
|
|
logger.info("All extensions initialized successfully") |