afterhours-shift-manager/src/ring-scheduler/app.py
Adam Moussa 6eb2e52a74
Some checks failed
Deploy / deploy (push) Has been cancelled
Deploy / release (push) Has been cancelled
feat(observability): add Sentry error reporting to Lambdas (#241)
Unhandled errors and timeout warnings go to Sentry when SENTRY_DSN is set; Slack and 3CX secrets are stripped before send.
2026-08-29 20:52:28 +00:00

76 lines
2.3 KiB
Python

"""Lambda handler — updates 3CX queue routing based on who's on shift.
Triggered by EventBridge at 8am ET daily and 5pm ET on weekends.
Also invoked directly by the Slack bot for same-day shift changes.
"""
import json
import logging
import os
from datetime import datetime
from zoneinfo import ZoneInfo
import shared.sentry_init # noqa: F401
from shared.ring_scheduler import update_queue_routing
from shared.schedule import (
FALLBACK_EXTENSION,
WEEKEND_DAYS,
ShiftSchedule,
determine_shift_type,
)
from shared.secrets import get_secret
logger = logging.getLogger()
logger.setLevel(logging.INFO)
EASTERN = ZoneInfo("America/New_York")
def handler(event, context):
now = datetime.now(EASTERN)
current_hour = now.hour
day_name = now.strftime("%A")
logger.info("Running queue scheduler at %s", now.isoformat())
force = event.get("force", False)
valid_hours = {8, 17} if day_name in WEEKEND_DAYS else {8}
if not force and current_hour not in valid_hours:
logger.info(
"ET hour is %d on %s — skipping (wrong DST rule fired)",
current_hour,
day_name,
)
return {"skipped": True}
shift_type = determine_shift_type(now)
if event.get("override_extension"):
extension = event["override_extension"]
else:
schedule = ShiftSchedule()
date_str = now.strftime("%Y-%m-%d")
ext, _name, source = schedule.resolve_shift(date_str, day_name, shift_type)
extension = ext if source != "available" else FALLBACK_EXTENSION
secret_prefix = os.environ["TCX_SECRET_PREFIX"]
try:
result = update_queue_routing(
extension=extension,
queue_number=os.environ["QUEUE_NUMBER"],
domain=get_secret(f"{secret_prefix}domain"),
client_id=get_secret(f"{secret_prefix}client-id"),
client_secret=get_secret(f"{secret_prefix}client-secret"),
)
except Exception:
logger.exception("Failed to update 3CX queue routing")
return {"error": True, "date": now.strftime("%Y-%m-%d"), "day": day_name}
result.update(
{
"date": now.strftime("%Y-%m-%d"),
"day": day_name,
"shift_type": shift_type,
}
)
logger.info("Result: %s", json.dumps(result))
return result