stats 로깅 시스템 & 대시보드 api 추가#93
Conversation
…board # Conflicts: # core/lifecycle/internal/hlife.py # handler/cursor/internal/cursor_handler.py # server.py
|
#91 (comment) |
|
반영했습니다.
|
| continue | ||
|
|
||
| position = cursor.position | ||
| cursors.append( |
| actor_id: str | None | ||
| tile_id: str | None | ||
| x: int | None | ||
| y: int | None |
|
|
||
| async def insert_app_log( | ||
| db: DB, | ||
| *, |
| from __future__ import annotations | ||
|
|
||
| import json | ||
| import sqlite3 |
| if "locked" not in str(e).lower(): | ||
| break | ||
| time.sleep(0.1 * (attempt + 1)) |
There was a problem hiding this comment.
빼셈, 만약 이거가 있어야 문제가 안 생긴다 해도 문제임
그냥 time sleep 자체가 안티패턴, 특히 그냥 안되서 기다리는거
| @dataclass(frozen=True) | ||
| class StatEventRecord: | ||
| event_type: str | ||
| actor_id: str | None | ||
| tile_id: str | None | ||
| x: int | None | ||
| y: int | None | ||
| value: int | None | ||
| payload: JsonObject | None |
There was a problem hiding this comment.
이거 높은 확율로 나중에 바꿔야 할탠데 일단 이렇게 만들어 놨으니까 지금은 통과
| { | ||
| "connection_id": cursor_id, | ||
| "cursor_id": cursor_id, | ||
| "color": int(cursor.color), | ||
| "tile_id": f"tile:{position.x}:{position.y}", | ||
| "x": position.x, | ||
| "y": position.y, | ||
| "score": cursor.score, | ||
| "is_alive": cursor.is_alive, | ||
| "active_at": cursor.active_at.isoformat(), | ||
| "window": { | ||
| "width": cursor.width, | ||
| "height": cursor.height, | ||
| }, | ||
| } |
| DBContextFactory = Callable[[], AbstractAsyncContextManager[DB]] | ||
|
|
||
|
|
||
| @dataclass(frozen=True) |
There was a problem hiding this comment.
frozen쓰는건 좋음, 근데 이거 알고쓰고
쓸거면 slot도 같이 쓰셈
|
|
||
| DB = aiosqlite.Connection | ||
| Row = aiosqlite.Row | ||
| JsonValue: TypeAlias = None | bool | int | float | str | list["JsonValue"] | dict[str, "JsonValue"] |
There was a problem hiding this comment.
왜 힌팅을 이렇게 하는가? recursive한 구조가 굳이 필요했나?
json을 힌팅하기 위해 사용한 것 치고는 너무 많은 복잡성
| LogRecord: TypeAlias = Mapping[str, object] | ||
|
|
||
|
|
||
| @runtime_checkable |
| LifecycleSink = Callable[[LifeCycle], None] | ||
|
|
||
|
|
||
| class LifecycleSinkRegistry: |
| @staticmethod | ||
| async def wait_until_idle(timeout: float | None = None): | ||
| event = EventBroker._get_idle_event() | ||
| await asyncio.wait_for(event.wait(), timeout=timeout) | ||
|
|
||
| @staticmethod | ||
| def _get_idle_event(): | ||
| loop = asyncio.get_running_loop() | ||
| if EventBroker._idle_event is None or EventBroker._idle_loop is not loop: | ||
| EventBroker._idle_event = asyncio.Event() | ||
| EventBroker._idle_loop = loop | ||
| if EventBroker.is_end(): | ||
| EventBroker._idle_event.set() | ||
| return EventBroker._idle_event | ||
|
|
||
| @staticmethod | ||
| def _mark_running(): | ||
| event = EventBroker._get_idle_event() | ||
| event.clear() | ||
|
|
||
| @staticmethod | ||
| def _mark_done(): | ||
| if EventBroker.is_end(): | ||
| event = EventBroker._get_idle_event() | ||
| event.set() |
요약
주요 변경
검증
참고