Files
tracer-cloud--opensre/core/domain/alerts/inbox.py
T
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

103 lines
2.7 KiB
Python

"""In-process alert inbox — the pure domain queue for external alert pushes.
HTTP intake lives in :mod:`gateway.webapp` (``POST /alerts``); this module only
owns the queue and the process-wide current-inbox handle.
"""
from __future__ import annotations
import threading
from collections import deque
from datetime import datetime
from config.strict_config import StrictConfigModel
_DEFAULT_MAX_INBOX = 256
class IncomingAlert(StrictConfigModel):
text: str
alert_name: str | None = None
severity: str | None = None
source: str | None = None
received_at: datetime | None = None
class AlertInbox:
def __init__(self, maxsize: int = _DEFAULT_MAX_INBOX) -> None:
self._queue: deque[IncomingAlert] = deque()
self._maxsize = maxsize
self._dropped: int = 0
self._lock = threading.Lock()
self._pending_event = threading.Event() # Set when alerts are available
def put(self, alert: IncomingAlert) -> bool:
"""Return True if queued without eviction, False if an old alert was dropped."""
with self._lock:
if len(self._queue) >= self._maxsize:
self._queue.popleft()
self._dropped += 1
self._queue.append(alert)
self._pending_event.set()
return False
self._queue.append(alert)
self._pending_event.set()
return True
def pop_nowait(self) -> IncomingAlert | None:
with self._lock:
try:
return self._queue.popleft()
except IndexError:
return None
def iter_pending(self) -> list[IncomingAlert]:
with self._lock:
items: list[IncomingAlert] = []
while True:
try:
items.append(self._queue.popleft())
except IndexError:
break
if not self._queue:
self._pending_event.clear()
return items
def peek_last(self, n: int) -> list[IncomingAlert]:
with self._lock:
items = list(self._queue)
return items[-n:]
@property
def qsize(self) -> int:
return len(self._queue)
@property
def dropped(self) -> int:
return self._dropped
@property
def pending_event(self) -> threading.Event:
"""Event set when alerts are available, for background wakers."""
return self._pending_event
_current_inbox: AlertInbox | None = None
def set_current_inbox(inbox: AlertInbox | None) -> None:
global _current_inbox
_current_inbox = inbox
def get_current_inbox() -> AlertInbox | None:
return _current_inbox
__all__ = [
"AlertInbox",
"IncomingAlert",
"get_current_inbox",
"set_current_inbox",
]