feat: переработка NetwrokMessage и EventMapper
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import json
|
||||
import logging
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from enum import StrEnum, auto
|
||||
from typing import Any
|
||||
from typing import Any, Optional
|
||||
|
||||
from uuid_extensions import uuid7str
|
||||
|
||||
@@ -16,6 +17,8 @@ from ..state_machines.session.events import (
|
||||
SetterMoveEvent,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SessionMessageKind(StrEnum):
|
||||
PLAYER_HELLO = auto()
|
||||
@@ -42,6 +45,14 @@ KIND_TO_EVENT_MAP = {
|
||||
}
|
||||
|
||||
|
||||
def serializer(obj: Any) -> Any:
|
||||
if isinstance(obj, StrEnum):
|
||||
return obj.value
|
||||
raise TypeError(
|
||||
f"Object of type {type(obj).__name__} is not JSON serializable"
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class NetworkMessage:
|
||||
kind: NetworkMessageKind
|
||||
@@ -50,17 +61,22 @@ class NetworkMessage:
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json_str: str) -> "NetworkMessage":
|
||||
data = json.loads(json_str)
|
||||
return cls(
|
||||
kind=NetworkMessageKind(data["kind"]),
|
||||
payload=data.get("payload", {}),
|
||||
id=data["id"],
|
||||
)
|
||||
try:
|
||||
data = json.loads(json_str)
|
||||
return cls(
|
||||
kind=NetworkMessageKind(data["kind"]),
|
||||
payload=data.get("payload", {}),
|
||||
id=data["id"],
|
||||
)
|
||||
except (KeyError, ValueError, json.JSONDecodeError) as err:
|
||||
logger.error(
|
||||
"Failed to deserialize NetworkMessage from JSON: %s", err
|
||||
)
|
||||
raise
|
||||
|
||||
def to_json(self) -> str:
|
||||
data = asdict(self)
|
||||
data["kind"] = self.kind.value
|
||||
return json.dumps(data, ensure_ascii=False)
|
||||
data = {"kind": self.kind.value, "payload": self.payload, "id": self.id}
|
||||
return json.dumps(data, ensure_ascii=False, default=serializer)
|
||||
|
||||
|
||||
class EventMapper:
|
||||
@@ -70,9 +86,14 @@ class EventMapper:
|
||||
kind = EVENT_TO_KIND_MAP.get(event_type)
|
||||
|
||||
if not kind:
|
||||
raise ValueError(f"Event {event_type} not registered")
|
||||
logger.error(
|
||||
"Attempted to serialize unregistered event: %s", event_type
|
||||
)
|
||||
raise ValueError(
|
||||
f"Event {event_type} is not registered in EVENT_TO_KIND_MAP"
|
||||
)
|
||||
|
||||
return NetworkMessage(kind=kind, payload=asdict(event))
|
||||
return NetworkMessage(kind=kind, payload=event.to_payload())
|
||||
|
||||
@staticmethod
|
||||
def from_message(message: NetworkMessage) -> Event | None:
|
||||
@@ -82,33 +103,6 @@ class EventMapper:
|
||||
return None
|
||||
|
||||
try:
|
||||
payload = message.payload
|
||||
|
||||
player = Player(
|
||||
name=payload["player"]["name"],
|
||||
role=PlayerRole(payload["player"]["role"]),
|
||||
)
|
||||
|
||||
match message.kind:
|
||||
case NetworkMessageKind.PLAYER_HELLO:
|
||||
return PlayerHelloEvent(player=player)
|
||||
case NetworkMessageKind.SETTER_MOVED:
|
||||
return SetterMoveEvent(
|
||||
player=player,
|
||||
direction=ArrowDirection(payload["direction"]),
|
||||
)
|
||||
case NetworkMessageKind.GUESSER_MOVED:
|
||||
return GuesserMoveEvent(
|
||||
player=player,
|
||||
direction=ArrowDirection(payload["direction"]),
|
||||
)
|
||||
case NetworkMessageKind.SECRET_REVEALED:
|
||||
return RevealSecretEvent(
|
||||
player=player,
|
||||
direction=ArrowDirection(payload["direction"]),
|
||||
)
|
||||
case NetworkMessageKind.NEXT_STEP_REQUESTED:
|
||||
return NextStepRequestedEvent(player=player)
|
||||
|
||||
return event_cls.from_payload(message.payload)
|
||||
except (KeyError, ValueError, TypeError):
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user