build 039: complete Quotes Feed migration foundation
This commit is contained in:
118
app/tools/dzengi_probe/connection_probe.py
Normal file
118
app/tools/dzengi_probe/connection_probe.py
Normal file
@@ -0,0 +1,118 @@
|
||||
# app/tools/dzengi_probe/connection_probe.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
import websockets
|
||||
from websockets.typing import Subprotocol
|
||||
|
||||
from app.tools.dzengi_probe.config import DzengiProbeConfig
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ConnectionProbeResult:
|
||||
name: str
|
||||
ok: bool
|
||||
error: str | None = None
|
||||
|
||||
|
||||
class DzengiConnectionProbe:
|
||||
def __init__(self, config: DzengiProbeConfig) -> None:
|
||||
self.config = config
|
||||
|
||||
async def run_all(self) -> list[ConnectionProbeResult]:
|
||||
return [
|
||||
await self._check(
|
||||
name="baseline",
|
||||
headers={
|
||||
"Origin": self.config.base_url,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
subprotocols=[Subprotocol("json")],
|
||||
),
|
||||
await self._check(
|
||||
name="without_origin",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
subprotocols=[Subprotocol("json")],
|
||||
),
|
||||
await self._check(
|
||||
name="without_content_type",
|
||||
headers={
|
||||
"Origin": self.config.base_url,
|
||||
},
|
||||
subprotocols=[Subprotocol("json")],
|
||||
),
|
||||
await self._check(
|
||||
name="without_headers",
|
||||
headers=None,
|
||||
subprotocols=[Subprotocol("json")],
|
||||
),
|
||||
await self._check(
|
||||
name="without_subprotocol",
|
||||
headers={
|
||||
"Origin": self.config.base_url,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
subprotocols=None,
|
||||
),
|
||||
await self._check(
|
||||
name="minimal_connection",
|
||||
headers=None,
|
||||
subprotocols=None,
|
||||
),
|
||||
]
|
||||
|
||||
async def _check(
|
||||
self,
|
||||
*,
|
||||
name: str,
|
||||
headers: dict[str, str] | None,
|
||||
subprotocols: list[Subprotocol] | None,
|
||||
) -> ConnectionProbeResult:
|
||||
subscribe_message: dict[str, Any] = {
|
||||
"correlationId": f"connection-probe-{name}",
|
||||
"destination": "marketData.subscribe",
|
||||
"payload": {
|
||||
"symbols": [self.config.symbol],
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
async with websockets.connect(
|
||||
self.config.ws_url,
|
||||
extra_headers=headers,
|
||||
subprotocols=subprotocols,
|
||||
ping_interval=20,
|
||||
ping_timeout=20,
|
||||
close_timeout=5,
|
||||
) as websocket:
|
||||
await websocket.send(json.dumps(subscribe_message))
|
||||
|
||||
raw_message = await asyncio.wait_for(
|
||||
websocket.recv(),
|
||||
timeout=self.config.timeout_seconds,
|
||||
)
|
||||
|
||||
payload = json.loads(raw_message)
|
||||
|
||||
if payload.get("status") != "OK":
|
||||
return ConnectionProbeResult(
|
||||
name=name,
|
||||
ok=False,
|
||||
error=json.dumps(payload, ensure_ascii=False),
|
||||
)
|
||||
|
||||
return ConnectionProbeResult(name=name, ok=True)
|
||||
|
||||
except Exception as exc:
|
||||
return ConnectionProbeResult(
|
||||
name=name,
|
||||
ok=False,
|
||||
error=str(exc),
|
||||
)
|
||||
Reference in New Issue
Block a user