closed TG-1; git was inited;
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
"""UDP JSON event publisher on ``127.0.0.1:7001`` (configurable).
|
||||
|
||||
Contract: one serialized ``Event`` per UDP datagram. Events larger than
|
||||
``max_datagram_bytes`` are dropped and counted in
|
||||
``stats.udp_events_oversize`` (no fragmentation).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from ..config import UdpEventsCfg
|
||||
from ..core.bus import EventBus
|
||||
from ..core.models import Event
|
||||
from ..core.stats import Stats
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UdpEventsPublisher:
|
||||
def __init__(self, cfg: UdpEventsCfg, bus: EventBus, stats: Stats) -> None:
|
||||
self._cfg = cfg
|
||||
self._bus = bus
|
||||
self._stats = stats
|
||||
self._transport: asyncio.DatagramTransport | None = None
|
||||
self._sub: asyncio.Queue[Event] | None = None
|
||||
|
||||
async def run(self) -> None:
|
||||
loop = asyncio.get_running_loop()
|
||||
# Ephemeral sender socket; we only *send* to a fixed target.
|
||||
transport, _ = await loop.create_datagram_endpoint(
|
||||
lambda: asyncio.DatagramProtocol(),
|
||||
remote_addr=(self._cfg.host, self._cfg.port),
|
||||
)
|
||||
self._transport = transport
|
||||
self._sub = self._bus.subscribe(maxsize=1024)
|
||||
log.info("udp_events publisher -> %s:%d", self._cfg.host, self._cfg.port)
|
||||
try:
|
||||
while True:
|
||||
ev = await self._sub.get()
|
||||
self._send(ev)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
finally:
|
||||
if self._sub is not None:
|
||||
self._bus.unsubscribe(self._sub)
|
||||
self._sub = None
|
||||
if self._transport is not None:
|
||||
self._transport.close()
|
||||
self._transport = None
|
||||
|
||||
def _send(self, ev: Event) -> None:
|
||||
try:
|
||||
blob = json.dumps(ev.to_dict(), ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
||||
except Exception:
|
||||
self._stats.incr("udp_events_serialize_errors")
|
||||
return
|
||||
if len(blob) > self._cfg.max_datagram_bytes:
|
||||
self._stats.incr("udp_events_oversize")
|
||||
return
|
||||
try:
|
||||
assert self._transport is not None
|
||||
self._transport.sendto(blob)
|
||||
self._stats.incr("udp_events_sent")
|
||||
except Exception:
|
||||
self._stats.incr("udp_events_send_errors")
|
||||
log.debug("udp_events send failed", exc_info=True)
|
||||
|
||||
|
||||
__all__ = ["UdpEventsPublisher"]
|
||||
Reference in New Issue
Block a user