feat(mp): add !mp command handling support#149
Open
CloneWith wants to merge 26 commits into
Open
Conversation
15 tasks
- Use blocking Redis - Auto re-spawn
Comment on lines
+24
to
+100
| class MultiplayerTaskAwaiter: | ||
| """Manages the communication process with the spectator server using tasks.""" | ||
|
|
||
| def __init__(self, default_timeout: float = 10.0): | ||
| self._futures: dict[str, asyncio.Future[MultiplayerCallbackMessage]] = {} | ||
| self._default_timeout = default_timeout | ||
| self._lock = asyncio.Lock() | ||
|
|
||
| async def create_task(self, task_id: str | None = None) -> str: | ||
| """Creates a new async task. | ||
|
|
||
| Args: | ||
| task_id (str | None): Optional task ID to use. Defaults to UUID4 if not given. | ||
|
|
||
| Returns: | ||
| str: The ID of the new task. | ||
| """ | ||
| tid = task_id or str(uuid.uuid4()) | ||
| async with self._lock: | ||
| # 清理已存在的同名任务(防御性) | ||
| if tid in self._futures and not self._futures[tid].done(): | ||
| self._futures[tid].cancel() | ||
|
|
||
| self._futures[tid] = asyncio.get_running_loop().create_future() | ||
| return tid | ||
|
|
||
| async def wait_for_result( | ||
| self, | ||
| task_id: str, | ||
| timeout: float | None = None, # noqa: ASYNC109 | ||
| ) -> MultiplayerCallbackMessage: | ||
| """Wait for the result of a specific task. | ||
|
|
||
| Returns: | ||
| MultiplayerCallbackMessage: The callback event message from the spectator server. | ||
| If the task runs out of time, return a placeholder message with the timeout prompt. | ||
| """ | ||
| future = self._futures.get(task_id) | ||
| if not future: | ||
| raise ValueError(f"Task {task_id} not found") | ||
|
|
||
| logger.info(f"Waiting for result of task #{task_id}") | ||
|
|
||
| try: | ||
| result = await asyncio.wait_for(future, timeout=timeout or self._default_timeout) | ||
| logger.info(f"Got result for #{task_id}: {result}") | ||
| return result | ||
| except TimeoutError: | ||
| logger.warning(f"Task {task_id} timed out") | ||
| return MultiplayerCallbackMessage( | ||
| id="0", | ||
| type="TaskResult", | ||
| success=False, | ||
| message="Server-side request timeout. Please try again later.", | ||
| details=MultiplayerCallbackDetails(), | ||
| ) | ||
| finally: | ||
| # 清理 | ||
| async with self._lock: | ||
| self._futures.pop(task_id, None) | ||
|
|
||
| def resolve_task(self, task_id: str, result: MultiplayerCallbackMessage) -> bool: | ||
| """Sets a specified task as resolved with given callback message. | ||
|
|
||
| Args: | ||
| task_id (str): The task ID. | ||
| result (MultiplayerCallbackMessage): The callback message as a result. | ||
|
|
||
| Returns: | ||
| bool: `True` if the task was resolved, `False` otherwise. | ||
| """ | ||
| future = self._futures.get(task_id) | ||
| if not future or future.done(): | ||
| return False | ||
|
|
||
| future.set_result(result) | ||
| return True |
Contributor
There was a problem hiding this comment.
v2_ipc provides a similar waiter. Consider merging them into a general waiter?
| task_awaiter = MultiplayerTaskAwaiter(default_timeout=10.0) | ||
|
|
||
|
|
||
| class MultiplayerEventDispatcher: |
Contributor
There was a problem hiding this comment.
Consider RedisSubscriber?
Contributor
Author
There was a problem hiding this comment.
These classes (including the one above, the MultiplayerTaskAwaiter) are still too specific for a general name like this. Renaming could be considered when the generic messager part is extracted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #147.
TODO: The mechanics behind all of this would get explained later on.
Tasks
banchobot.py