基于协程的任务会话 当主协程任务和会话内所有通过 `run_async` 注册的协程都退出后,会话关闭。 当用户浏览器主动关闭会话,CoroutineBasedSession.close 被调用, 协程任务和会话内所有通过 `run_async` 注册的协程都被关闭。
| 28 | |
| 29 | |
| 30 | class CoroutineBasedSession(Session): |
| 31 | """ |
| 32 | 基于协程的任务会话 |
| 33 | |
| 34 | 当主协程任务和会话内所有通过 `run_async` 注册的协程都退出后,会话关闭。 |
| 35 | 当用户浏览器主动关闭会话,CoroutineBasedSession.close 被调用, 协程任务和会话内所有通过 `run_async` 注册的协程都被关闭。 |
| 36 | |
| 37 | """ |
| 38 | |
| 39 | # 运行事件循环的线程id |
| 40 | # 用于在 CoroutineBasedSession.get_current_session() 判断调用方是否合法 |
| 41 | # Tornado backend时,在创建第一个CoroutineBasedSession时初始化 |
| 42 | # Flask backend时,在platform.flaskrun_event_loop()时初始化 |
| 43 | event_loop_thread_id = None |
| 44 | |
| 45 | @classmethod |
| 46 | def get_current_session(cls) -> "CoroutineBasedSession": |
| 47 | if _context.current_session is None or cls.event_loop_thread_id != threading.current_thread().ident: |
| 48 | raise SessionNotFoundException("No session found in current context!") |
| 49 | |
| 50 | if _context.current_session.closed(): |
| 51 | raise SessionClosedException |
| 52 | |
| 53 | return _context.current_session |
| 54 | |
| 55 | @staticmethod |
| 56 | def get_current_task_id(): |
| 57 | if _context.current_task_id is None: |
| 58 | raise RuntimeError("No current task found in context!") |
| 59 | return _context.current_task_id |
| 60 | |
| 61 | def __init__(self, target, session_info, on_task_command=None, on_session_close=None): |
| 62 | """ |
| 63 | :param target: 协程函数 |
| 64 | :param on_task_command: 由协程内发给session的消息的处理函数 |
| 65 | :param on_session_close: 会话结束的处理函数。后端Backend在相应on_session_close时关闭连接时,需要保证会话内的所有消息都传送到了客户端 |
| 66 | """ |
| 67 | assert iscoroutinefunction(target) or isgeneratorfunction(target), ValueError( |
| 68 | "CoroutineBasedSession accept coroutine function or generator function as task function") |
| 69 | |
| 70 | super().__init__(session_info) |
| 71 | |
| 72 | cls = type(self) |
| 73 | |
| 74 | self._on_task_command = on_task_command or (lambda _: None) |
| 75 | self._on_session_close = on_session_close or (lambda: None) |
| 76 | |
| 77 | # 当前会话未被Backend处理的消息 |
| 78 | self.unhandled_task_msgs = [] |
| 79 | |
| 80 | # 在创建第一个CoroutineBasedSession时 event_loop_thread_id 还未被初始化 |
| 81 | # 则当前线程即为运行 event loop 的线程 |
| 82 | if cls.event_loop_thread_id is None: |
| 83 | cls.event_loop_thread_id = threading.current_thread().ident |
| 84 | |
| 85 | # 会话内的协程任务 |
| 86 | self.coros = {} # coro_task_id -> Task() |
| 87 |
no outgoing calls
no test coverage detected
searching dependent graphs…