04/13/2026 Fixed email ingres function
This commit is contained in:
+32
-51
@@ -182,39 +182,47 @@ def create_app(config_name=None):
|
||||
_seed_settings()
|
||||
_seed_ticket_templates()
|
||||
|
||||
# ── Email ingestion background scheduler ────────────────────────────────────
|
||||
_start_email_ingestion_scheduler(app)
|
||||
|
||||
# ── SLA background scheduler ──────────────────────────────────────────────
|
||||
# APScheduler runs inside the gunicorn worker process (single-worker
|
||||
# eventlet setup), so no cross-process coordination is needed.
|
||||
# The scheduler is only started in the main process — not during Flask's
|
||||
# reloader child process — to prevent duplicate job execution.
|
||||
_start_sla_scheduler(app)
|
||||
# ── Background schedulers (SLA + Email Ingestion) ───────────────────────────
|
||||
# Both jobs share a single BackgroundScheduler instance to avoid duplicate
|
||||
# thread pools and simplify startup/shutdown. The scheduler is only started
|
||||
# in the main process — not during Flask's reloader child — to prevent
|
||||
# duplicate job execution.
|
||||
_start_background_schedulers(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def _start_sla_scheduler(app):
|
||||
"""Start the APScheduler background job that checks for SLA breaches.
|
||||
|
||||
Safe to call on every app startup: the scheduler is idempotent and
|
||||
jobstore deduplication prevents double-registration on hot-reloads.
|
||||
Under gunicorn with preload_app=False each worker calls create_app()
|
||||
once, so there is exactly one scheduler per worker.
|
||||
def _start_background_schedulers(app):
|
||||
"""Start a single shared APScheduler instance hosting both the SLA breach
|
||||
check and the inbound email ingestion job.
|
||||
|
||||
A single BackgroundScheduler is used rather than two separate instances to
|
||||
avoid creating duplicate thread pools under eventlet. Both jobs are
|
||||
registered here so they share one daemon thread pool.
|
||||
|
||||
The scheduler is skipped in Flask's reloader subprocess (identified by the
|
||||
WERKZEUG_RUN_MAIN env var) to prevent double-registration on hot-reloads.
|
||||
Under gunicorn with preload_app=False, each worker calls create_app() once,
|
||||
giving exactly one scheduler per worker.
|
||||
"""
|
||||
# Skip inside Flask's reloader subprocess (identified by the env var it sets).
|
||||
import os as _os
|
||||
if _os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
|
||||
# Reloader is active — the child process will start its own scheduler.
|
||||
return
|
||||
return # skip reloader child process
|
||||
|
||||
try:
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
from app.services.sla_service import check_sla_breaches
|
||||
from app.services.email_ingestion_service import check_inbound_email
|
||||
from app.models import SystemSetting
|
||||
|
||||
with app.app_context():
|
||||
email_interval = int(SystemSetting.get('email_ingestion_interval', '5') or '5')
|
||||
|
||||
scheduler = BackgroundScheduler(daemon=True)
|
||||
|
||||
# SLA breach check — every 30 minutes
|
||||
scheduler.add_job(
|
||||
func = check_sla_breaches,
|
||||
trigger = IntervalTrigger(minutes=30),
|
||||
@@ -223,49 +231,22 @@ def _start_sla_scheduler(app):
|
||||
replace_existing = True,
|
||||
args = [app],
|
||||
)
|
||||
scheduler.start()
|
||||
app.logger.info('[SLA] APScheduler started — SLA breach check every 30 minutes')
|
||||
except Exception as exc:
|
||||
app.logger.error(f'[SLA] Failed to start APScheduler: {exc}')
|
||||
|
||||
|
||||
def _start_email_ingestion_scheduler(app):
|
||||
"""Start the APScheduler job that polls the inbound mailbox for new emails.
|
||||
|
||||
The interval is read from SystemSetting at job creation time (default 5 min).
|
||||
The job is a no-op when email_ingestion_enabled = '0', so it is safe to
|
||||
always register it — no credentials are required until the admin enables it.
|
||||
"""
|
||||
import os as _os
|
||||
if _os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
|
||||
return # skip reloader child process
|
||||
|
||||
try:
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
from app.services.email_ingestion_service import check_inbound_email
|
||||
from app.models import SystemSetting
|
||||
|
||||
with app.app_context():
|
||||
interval = int(SystemSetting.get('email_ingestion_interval', '5') or '5')
|
||||
|
||||
scheduler = BackgroundScheduler(daemon=True)
|
||||
# Inbound email ingestion — interval from SystemSetting
|
||||
scheduler.add_job(
|
||||
func = check_inbound_email,
|
||||
trigger = IntervalTrigger(minutes=interval),
|
||||
trigger = IntervalTrigger(minutes=email_interval),
|
||||
id = 'email_ingest',
|
||||
name = 'Inbound Email Ingestion',
|
||||
replace_existing = True,
|
||||
args = [app],
|
||||
)
|
||||
|
||||
scheduler.start()
|
||||
app.logger.info(
|
||||
f'[EMAIL INGEST] APScheduler started — polling every {interval} minute(s)'
|
||||
)
|
||||
app.logger.info('[SCHEDULER] APScheduler started — SLA check every 30 min, '
|
||||
f'email ingestion every {email_interval} min')
|
||||
except Exception as exc:
|
||||
app.logger.error(f'[EMAIL INGEST] Failed to start scheduler: {exc}')
|
||||
|
||||
|
||||
app.logger.error(f'[SCHEDULER] Failed to start APScheduler: {exc}')
|
||||
|
||||
|
||||
def _seed_ticket_templates():
|
||||
|
||||
Reference in New Issue
Block a user