mirror of
https://github.com/smittix/intercept.git
synced 2026-06-09 22:43:32 -07:00
a3f2fa7b88
Fix app becoming unresponsive when two browser windows are open: the root cause was HTTP/1.1 connection pool exhaustion (6-connection limit per origin). VoiceAlerts was opening 3 SSE streams per window by default, so two windows produced 8 connections and permanently starved all regular HTTP requests. - voice-alerts.js: default all streams to false (opt-in) to stay within the browser connection limit; existing user preferences in localStorage are preserved - routes/alerts.py: replace direct AlertManager.stream_events() with sse_stream_fanout so both windows receive every alert instead of competing for the same queue - routes/bluetooth_v2.py: same fanout fix via subscribe_fanout_queue, preserving named SSE events (device_update, scan_started, etc.) Also includes accumulated UI/theming changes: accent-cyan CSS variable sweep across mode CSS/JS files, standalone dashboard pages, template updates, satellite TLE data refresh, and tile provider default rename. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.3 KiB
Python
77 lines
2.3 KiB
Python
"""Alerting API endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from flask import Blueprint, Response, request
|
|
|
|
from utils.alerts import get_alert_manager
|
|
from utils.responses import api_error, api_success
|
|
from utils.sse import sse_stream_fanout
|
|
|
|
alerts_bp = Blueprint("alerts", __name__, url_prefix="/alerts")
|
|
|
|
|
|
@alerts_bp.route("/rules", methods=["GET"])
|
|
def list_rules():
|
|
manager = get_alert_manager()
|
|
include_disabled = request.args.get("all") in ("1", "true", "yes")
|
|
return api_success(data={"rules": manager.list_rules(include_disabled=include_disabled)})
|
|
|
|
|
|
@alerts_bp.route("/rules", methods=["POST"])
|
|
def create_rule():
|
|
data = request.get_json() or {}
|
|
if not isinstance(data.get("match", {}), dict):
|
|
return api_error("match must be a JSON object", 400)
|
|
|
|
manager = get_alert_manager()
|
|
rule_id = manager.add_rule(data)
|
|
return api_success(data={"rule_id": rule_id})
|
|
|
|
|
|
@alerts_bp.route("/rules/<int:rule_id>", methods=["PUT", "PATCH"])
|
|
def update_rule(rule_id: int):
|
|
data = request.get_json() or {}
|
|
manager = get_alert_manager()
|
|
ok = manager.update_rule(rule_id, data)
|
|
if not ok:
|
|
return api_error("Rule not found or no changes", 404)
|
|
return api_success()
|
|
|
|
|
|
@alerts_bp.route("/rules/<int:rule_id>", methods=["DELETE"])
|
|
def delete_rule(rule_id: int):
|
|
manager = get_alert_manager()
|
|
ok = manager.delete_rule(rule_id)
|
|
if not ok:
|
|
return api_error("Rule not found", 404)
|
|
return api_success()
|
|
|
|
|
|
@alerts_bp.route("/events", methods=["GET"])
|
|
def list_events():
|
|
manager = get_alert_manager()
|
|
limit = request.args.get("limit", default=100, type=int)
|
|
mode = request.args.get("mode")
|
|
severity = request.args.get("severity")
|
|
events = manager.list_events(limit=limit, mode=mode, severity=severity)
|
|
return api_success(data={"events": events})
|
|
|
|
|
|
@alerts_bp.route("/stream", methods=["GET"])
|
|
def stream_alerts() -> Response:
|
|
manager = get_alert_manager()
|
|
response = Response(
|
|
sse_stream_fanout(
|
|
source_queue=manager._queue,
|
|
channel_key="alerts",
|
|
timeout=1.0,
|
|
keepalive_interval=30.0,
|
|
),
|
|
mimetype="text/event-stream",
|
|
)
|
|
response.headers["Cache-Control"] = "no-cache"
|
|
response.headers["X-Accel-Buffering"] = "no"
|
|
response.headers["Connection"] = "keep-alive"
|
|
return response
|