2021-12-13 18:08:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# tractor: structured concurrent "actors".
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# Copyright 2018-eternity Tyler Goodlet.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# This program is free software: you can redistribute it and/or modify
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# it under the terms of the GNU Affero General Public License as published by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# the Free Software Foundation, either version 3 of the License, or
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# (at your option) any later version.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# This program is distributed in the hope that it will be useful,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# GNU Affero General Public License for more details.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# You should have received a copy of the GNU Affero General Public License
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								# along with this program.  If not, see <https://www.gnu.org/licenses/>.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								"""
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								Actor primitives and helpers
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								"""
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from __future__ import annotations
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from collections import defaultdict
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from functools import partial
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from itertools import chain
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import importlib
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-12 02:37:30 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import importlib.util
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import inspect
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import signal
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import sys
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from typing import (
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Any,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Callable,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Optional,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Union,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TYPE_CHECKING,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								import uuid
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-31 17:04:46 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from types import ModuleType
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-12 02:37:30 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import os
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-24 13:59:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from contextlib import ExitStack
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import warnings
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-09 17:12:50 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from async_generator import aclosing
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from exceptiongroup import BaseExceptionGroup
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-26 17:12:29 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import trio  # type: ignore
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from trio_typing import TaskStatus
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-26 01:36:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from ._ipc import Channel
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 20:23:47 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from ._context import (
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    mk_context,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Context,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								)
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-20 20:06:50 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from .log import get_logger
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-12 20:27:38 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from ._exceptions import (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    pack_error,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    unpack_error,
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-25 20:20:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ModuleNotExposed,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    is_multi_cancelled,
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-13 22:03:50 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ContextCancelled,
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 11:44:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    TransportClosed,
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-12 20:27:38 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								)
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-28 17:02:33 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from . import _debug
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-24 15:37:11 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from ._discovery import get_arbiter
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from ._portal import Portal
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from . import _state
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from . import _mp_fixup_main
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								if TYPE_CHECKING:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    from ._supervise import ActorNursery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								log = get_logger('tractor')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								async def _invoke(
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    actor: 'Actor',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    cid: str,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    chan: Channel,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    func: Callable,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    kwargs: dict[str, Any],
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-08 22:20:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    is_rpc: bool = True,
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 23:18:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    task_status: TaskStatus[
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        Union[Context, BaseException]
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 23:18:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ] = trio.TASK_STATUS_IGNORED,
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								):
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Invoke local func and deliver result(s) over provided channel.
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-31 17:56:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    This is the core "RPC task" starting machinery.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-31 17:56:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    __tracebackhide__ = True
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    treat_as_gen: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    failed_resp: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # possibly a traceback (not sure what typing is for this..)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    tb = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    cancel_scope = trio.CancelScope()
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # activated cancel scope ref
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-08 16:48:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    cs: Optional[trio.CancelScope] = None
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    ctx = actor.get_context(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # We shouldn't ever need to pass this through right?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # it's up to the soon-to-be called rpc task to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # open the stream with this option.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # allow_overruns=True,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    )
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    context: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-26 01:36:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    if getattr(func, '_tractor_stream_function', False):
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-29 23:10:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # handle decorated ``@tractor.stream`` async functions
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        sig = inspect.signature(func)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        params = sig.parameters
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # compat with old api
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-12 20:27:38 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        kwargs['ctx'] = ctx
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if 'ctx' in params:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            warnings.warn(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "`@tractor.stream decorated funcs should now declare "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "a `stream`  arg, `ctx` is now designated for use with "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "@tractor.context",
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                DeprecationWarning,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                stacklevel=2,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif 'stream' in params:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert 'stream' in params
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            kwargs['stream'] = ctx
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-21 04:10:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        treat_as_gen = True
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    elif getattr(func, '_tractor_context_function', False):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # handle decorated ``@tractor.context`` async function
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        kwargs['ctx'] = ctx
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        context = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-27 12:46:54 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # errors raised inside this block are propgated back to caller
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    try:
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-27 12:46:54 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            inspect.isasyncgenfunction(func) or
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            inspect.iscoroutinefunction(func)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise TypeError(f'{func} must be an async function!')
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            coro = func(**kwargs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except TypeError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if inspect.isasyncgen(coro):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.send({'functype': 'asyncgen', 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # XXX: massive gotcha! If the containing scope
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # is cancelled and we execute the below line,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # any ``ActorNursery.__aexit__()`` WON'T be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # triggered in the underlying async gen! So we
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # have to properly handle the closing (aclosing)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # of the async gen in order to be sure the cancel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # is propagated!
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            with cancel_scope as cs:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                ctx._scope = cs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task_status.started(ctx)
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                async with aclosing(coro) as agen:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    async for item in agen:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # TODO: can we send values back in here?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # it's gonna require a `while True:` and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # some non-blocking way to retrieve new `asend()`
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # values from the channel:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # to_send = await chan.recv_nowait()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # if to_send is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        #     to_yield = await coro.asend(to_send)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        await chan.send({'yield': item, 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime(f"Finished iterating {coro}")
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # TODO: we should really support a proper
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # `StopAsyncIteration` system here for returning a final
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # value if desired
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.send({'stop': True, 'cid': cid})
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # one way @stream func that gets treated like an async gen
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif treat_as_gen:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.send({'functype': 'asyncgen', 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # XXX: the async-func may spawn further tasks which push
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # back values like an async-generator would but must
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # manualy construct the response dict-packet-responses as
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # above
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            with cancel_scope as cs:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                ctx._scope = cs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task_status.started(ctx)
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await coro
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not cs.cancelled_caught:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # task was not cancelled so we can instruct the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # far end async gen to tear down
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await chan.send({'stop': True, 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        elif context:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # context func with support for bi-dir streaming
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.send({'functype': 'context', 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            try:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 03:10:39 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                async with trio.open_nursery() as nurse:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    ctx._scope_nursery = nurse
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    ctx._scope = nurse.cancel_scope
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    task_status.started(ctx)
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    res = await coro
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await chan.send({'return': res, 'cid': cid})
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            # XXX: do we ever trigger this block any more?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                BaseExceptionGroup,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                trio.Cancelled,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ):
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 16:38:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # if a context error was set then likely
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # thei multierror was raised due to that
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if ctx._remote_error is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise ctx._remote_error
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 16:38:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # maybe TODO: pack in ``trio.Cancelled.__traceback__`` here
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # so they can be unwrapped and displayed on the caller
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # side?
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 16:38:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                raise
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 18:47:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # XXX: only pop the context tracking if
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # a ``@tractor.context`` entrypoint was called
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                assert chan.uid
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # don't pop the local context until we know the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # associated child isn't in debug any more
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await _debug.maybe_wait_for_debugger()
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 18:47:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                ctx = actor._contexts.pop((chan.uid, cid))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if ctx:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f'Context entrypoint {func} was terminated:\n{ctx}'
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 18:47:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 03:10:39 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if ctx.cancelled_caught:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # first check for and raise any remote error
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # before raising any context cancelled case
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # so that real remote errors don't get masked as
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # ``ContextCancelled``s.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                re = ctx._remote_error
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if re:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    ctx._maybe_raise_remote_err(re)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                fname = func.__name__
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 03:10:39 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                cs: trio.CancelScope = ctx._scope
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if cs.cancel_called:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    canceller = ctx._cancel_called_remote
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # await _debug.breakpoint()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # NOTE / TODO: if we end up having
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # ``Actor._cancel_task()`` call
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # ``Context.cancel()`` directly, we're going to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # need to change this logic branch since it will
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # always enter..
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if ctx._cancel_called:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg = f'`{fname}()`@{actor.uid} cancelled itself'
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg = (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'`{fname}()`@{actor.uid} '
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            'was remotely cancelled by '
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    # if the channel which spawned the ctx is the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # one that cancelled it then we report that, vs.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # it being some other random actor that for ex.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # some actor who calls `Portal.cancel_actor()`
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # and by side-effect cancels this ctx.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if canceller == ctx.chan.uid:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg += f'its caller {canceller}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg += f'remote actor {canceller}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # TODO: does this ever get set any more or can
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # we remove it?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if ctx._cancel_msg:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg += f' with msg:\n{ctx._cancel_msg}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # task-contex was either cancelled by request using
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # ``Portal.cancel_actor()`` or ``Context.cancel()``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # on the far end, or it was cancelled by the local
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # (callee) task, so relay this cancel signal to the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # other side.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise ContextCancelled(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        msg,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        suberror_type=trio.Cancelled,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        canceller=canceller,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # regular async function
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await chan.send({'functype': 'asyncfunc', 'cid': cid})
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            except trio.BrokenResourceError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                failed_resp = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if is_rpc:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f'Failed to respond to non-rpc request: {func}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-05-01 19:10:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            with cancel_scope as cs:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                ctx._scope = cs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task_status.started(ctx)
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                result = await coro
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                fname = func.__name__
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f'{fname}() result: {result}')
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if not failed_resp:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # only send result if we know IPC isn't down
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    await chan.send(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        {'return': result,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                         'cid': cid}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-21 14:09:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-18 17:19:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Exception,
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-09 17:12:50 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        BaseExceptionGroup,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-18 17:19:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) as err:
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-21 14:09:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-29 19:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not is_multi_cancelled(err):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # TODO: maybe we'll want different "levels" of debugging
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # eventualy such as ('app', 'supervisory', 'runtime') ?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # if not isinstance(err, trio.ClosedResourceError) and (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # if not is_multi_cancelled(err) and (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            entered_debug: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                not isinstance(err, ContextCancelled)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                or (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    isinstance(err, ContextCancelled)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    and ctx._cancel_called
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # if the root blocks the debugger lock request from a child
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # we will get a remote-cancelled condition.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    and ctx._enter_debugger_on_cancel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-29 19:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # XXX: is there any case where we'll want to debug IPC
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # disconnects as a default?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                #
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # I can't think of a reason that inspecting
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # this type of failure will be useful for respawns or
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # recovery logic - the only case is some kind of strange bug
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # in our transport layer itself? Going to keep this
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # open ended for now.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                entered_debug = await _debug._maybe_enter_pm(err)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:03:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if not entered_debug:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.exception("Actor crashed:")
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-23 17:23:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # always ship errors back to caller
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        err_msg = pack_error(err, tb=tb)
							 | 
						
					
						
							
								
									
										
										
										
											2018-11-19 09:05:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        err_msg['cid'] = cid
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-11-19 21:52:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.send(err_msg)
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-18 17:19:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # TODO: tests for this scenario:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # - RPC caller closes connection before getting a response
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # should **not** crash this actor..
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            trio.ClosedResourceError,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            trio.BrokenResourceError,
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            BrokenPipeError,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-18 17:19:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # if we can't propagate the error that's a big boo boo
							 | 
						
					
						
							
								
									
										
										
										
											2023-01-26 22:49:14 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            log.exception(
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"Failed to ship error to caller @ {chan.uid} !?"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # error is probably from above coro running code *not from the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # underlyingn rpc invocation* since a scope was never allocated
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # around actual coroutine await.
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-14 03:10:39 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if ctx._scope is None:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            # we don't ever raise directly here to allow the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # msg-loop-scheduler to continue running for this
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # channel.
							 | 
						
					
						
							
								
									
										
										
										
											2018-11-19 09:05:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            task_status.started(err)
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-14 23:18:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-01 19:15:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # RPC task bookeeping
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ctx, func, is_complete = actor._rpc_tasks.pop(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                (chan, cid)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            is_complete.set()
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 18:47:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyError:
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-08 22:20:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if is_rpc:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # If we're cancelled before the task returns then the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # cancel scope will not have been inserted yet
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.warning(
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Task {func} likely errored or cancelled before start")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.cancel(f'{func.__name__}({kwargs}) failed?')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not actor._rpc_tasks:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime("All RPC tasks have completed")
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                actor._ongoing_rpc_tasks.set()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-29 05:51:25 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								def _get_mod_abspath(module):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return os.path.abspath(module.__file__)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								async def try_ship_error_to_parent(
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    channel: Channel,
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-09 17:12:50 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    err: Union[Exception, BaseExceptionGroup],
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    with trio.CancelScope(shield=True):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # internal error so ship to parent without cid
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await channel.send(pack_error(err))
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            trio.ClosedResourceError,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            trio.BrokenResourceError,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # in SC terms this is one of the worst things that can
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # happen and creates the 2-general's dilemma.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.critical(
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"Failed to ship error to parent "
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"{channel.uid}, channel was closed"
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class Actor:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    The fundamental "runtime" concurrency primitive.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    An *actor* is the combination of a regular Python process executing
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a ``trio`` task tree, communicating with other actors through
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    "memory boundary portals" - which provide a native async API around
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    IPC transport "channels" which themselves encapsulate various
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    (swappable) network protocols.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Each "actor" is ``trio.run()`` scheduled "runtime" composed of many
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    concurrent tasks in a single thread. The "runtime" tasks conduct
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a slew of low(er) level functions to make it possible for message
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    passing between actors as well as the ability to create new actors
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    (aka new "runtimes" in new processes which are supervised via
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a nursery construct). Each task which sends messages to a task in
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    a "peer" (not necessarily a parent-child, depth hierarchy)) is able
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    to do so via an "address", which maps IPC connections across memory
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    boundaries, and task request id which allows for per-actor
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    tasks to send and receive messages to specific peer-actor tasks with
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    which there is an ongoing RPC/IPC dialog.
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # ugh, we need to get rid of this and replace with a "registry" sys
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # https://github.com/goodboy/tractor/issues/216
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    is_arbiter: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    msg_buffer_size: int = 2**6
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # nursery placeholders filled in by `async_main()` after fork
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _root_n: Optional[trio.Nursery] = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _service_n: Optional[trio.Nursery] = None
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _server_n: Optional[trio.Nursery] = None
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # Information about `__main__` from parent
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _parent_main_data: dict[str, str]
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-26 21:46:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _parent_chan_cs: Optional[trio.CancelScope] = None
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # syncs for setup/teardown sequences
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _server_down: Optional[trio.Event] = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-29 02:44:16 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # if started on ``asycio`` running ``trio`` in guest mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _infected_aio: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-29 19:08:04 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # Process-global stack closed at end on actor runtime teardown.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # NOTE: this is currently an undocumented public api.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    lifetime_stack: ExitStack = ExitStack()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def __init__(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        name: str,
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-23 17:23:55 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        *,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        enable_modules: list[str] = [],
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        uid: str | None = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        loglevel: str | None = None,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        arbiter_addr: Optional[tuple[str, int]] = None,
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-28 00:05:00 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        spawn_method: Optional[str] = None
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This constructor is called in the parent actor **before** the spawning
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        phase (aka before a new process is executed).
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.name = name
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.uid = (name, uid or str(uuid.uuid4()))
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._cancel_complete = trio.Event()
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self._cancel_called_remote: tuple[str, tuple] | None = None
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._cancel_called: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-20 16:04:36 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # retreive and store parent `__main__` data which
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # will be passed to children
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._parent_main_data = _mp_fixup_main._mp_figure_out_main()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-30 14:41:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # always include debugging tools module
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-05 13:28:06 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        enable_modules.append('tractor._debug')
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-30 14:41:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-20 16:04:36 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        mods = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-05 13:28:06 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for name in enable_modules:
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-29 05:51:25 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mod = importlib.import_module(name)
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mods[name] = _get_mod_abspath(mod)
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-20 16:04:36 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-05 13:28:06 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.enable_modules = mods
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._mods: dict[str, ModuleType] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self.loglevel = loglevel
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 18:52:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-13 05:23:27 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self._arb_addr: tuple[str, int] | None = (
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 23:25:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            str(arbiter_addr[0]),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            int(arbiter_addr[1])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ) if arbiter_addr else None
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-28 00:05:00 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # marked by the process spawning backend at startup
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # will be None for the parent most process started manually
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # by the user (currently called the "arbiter")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._spawn_method = spawn_method
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._peers: defaultdict = defaultdict(list)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._peer_connected: dict = {}
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._no_more_peers = trio.Event()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._no_more_peers.set()
							 | 
						
					
						
							
								
									
										
										
										
											2019-11-23 06:29:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._ongoing_rpc_tasks = trio.Event()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._ongoing_rpc_tasks.set()
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # (chan, cid) -> (cancel_scope, func)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._rpc_tasks: dict[
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[Channel, str],
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            tuple[Context, Callable, trio.Event]
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # map {actor uids -> Context}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._contexts: dict[
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[tuple[str, str], str],
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            Context
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._listeners: list[trio.abc.Listener] = []
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._parent_chan: Optional[Channel] = None
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._forkserver_info: Optional[
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[Any, Any, Any, Any, Any]] = None
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-17 19:54:05 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self._actoruid2nursery: dict[
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[str, str],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ActorNursery | None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] = {}  # type: ignore  # noqa
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-26 17:12:29 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def wait_for_peer(
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self, uid: tuple[str, str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> tuple[trio.Event, Channel]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Wait for a connection back from a spawned actor with a given
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ``uid``.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"Waiting for peer {uid} to connect")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        event = self._peer_connected.setdefault(uid, trio.Event())
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        await event.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"{uid} successfully connected back to us")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return event, self._peers[uid][-1]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-21 04:10:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def load_modules(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Load allowed RPC modules locally (after fork).
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-21 04:10:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Since this actor may be spawned on a different machine from
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        the original nursery we need to try and load the local module
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        code (if it exists).
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-11-26 14:23:37 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-20 23:50:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self._spawn_method == 'trio':
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                parent_data = self._parent_main_data
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if 'init_main_from_name' in parent_data:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    _mp_fixup_main._fixup_main_from_name(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        parent_data['init_main_from_name'])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                elif 'init_main_from_path' in parent_data:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    _mp_fixup_main._fixup_main_from_path(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        parent_data['init_main_from_path'])
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-01-05 13:28:06 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for modpath, filepath in self.enable_modules.items():
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # XXX append the allowed module to the python path which
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # should allow for relative (at least downward) imports.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                sys.path.append(os.path.dirname(filepath))
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"Attempting to import {modpath}@{filepath}")
							 | 
						
					
						
							
								
									
										
										
										
											2020-02-09 06:05:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                mod = importlib.import_module(modpath)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self._mods[modpath] = mod
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if modpath == '__main__':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    self._mods['__mp_main__'] = mod
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-07 22:05:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-11-26 14:23:37 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except ModuleNotFoundError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # it is expected the corresponding `ModuleNotExposed` error
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # will be raised later
							 | 
						
					
						
							
								
									
										
										
										
											2020-01-30 02:06:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.error(f"Failed to import {modpath} in {self.name}")
							 | 
						
					
						
							
								
									
										
										
										
											2019-11-26 14:23:37 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-01 20:58:38 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def _get_rpc_func(self, ns, funcname):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return getattr(self._mods[ns], funcname)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyError as err:
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-16 02:49:12 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mne = ModuleNotExposed(*err.args)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if ns == '__main__':
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-01 18:36:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                modpath = '__name__'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                modpath = f"'{ns}'"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            msg = (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "\n\nMake sure you exposed the target module, `{ns}`, "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "using:\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "ActorNursery.start_actor(<name>, enable_modules=[{mod}])"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ).format(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                ns=ns,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                mod=modpath,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-16 02:49:12 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-01 18:36:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            mne.msg += msg
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-16 02:49:12 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise mne
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-01 20:58:38 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def _stream_handler(
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        stream: trio.SocketStream,
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-04 21:59:10 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """Entry point for new inbound connections to the channel server.
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        """
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._no_more_peers = trio.Event()  # unset
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-06 19:17:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan = Channel.from_stream(stream)
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid: Optional[tuple[str, str]] = chan.uid
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"New connection to us {chan}")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # send/receive initial handshake response
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            uid = await self._do_handshake(chan)
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 11:44:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except (
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-05 22:48:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # we need this for ``msgspec`` for some reason?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # for now, it's been put in the stream backend.
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-03 22:57:54 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # trio.BrokenResourceError,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # trio.ClosedResourceError,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 11:44:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            TransportClosed,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # XXX: This may propagate up from ``Channel._aiter_recv()``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # and ``MsgpackStream._inter_packets()`` on a read from the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # stream particularly when the runtime is first starting up
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # inside ``open_root_actor()`` where there is a check for
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # a bound listener on the "arbiter" addr.  the reset will be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # because the handshake was never meant took place.
							 | 
						
					
						
							
								
									
										
										
										
											2018-09-10 19:19:49 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.warning(f"Channel {chan} failed to handshake")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # channel tracking
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        event = self._peer_connected.pop(uid, None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if event:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Instructing connection: this is likely a new channel to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # a recently spawned actor which we'd like to control via
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # async-rpc calls.
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime(f"Waking channel waiters {event.statistics()}")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Alert any task waiting on this connection to come up
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            event.set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chans = self._peers[uid]
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-05 18:03:14 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # TODO: re-use channels for new connections instead
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # of always new ones; will require changing all the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # discovery funcs
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if chans:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"already have channel(s) for {uid}:{chans}?"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-30 17:47:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"Registered {chan} for {uid}")  # type: ignore
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # append new channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._peers[uid].append(chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 15:37:31 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        local_nursery: Optional[ActorNursery] = None  # noqa
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-16 18:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        disconnected: bool = False
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Begin channel management - respond to remote requests and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # process received reponses.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            disconnected = await process_messages(self, chan)
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-16 18:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            trio.Cancelled,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.cancel(f"Msg loop was cancelled for {chan}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        finally:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            local_nursery = self._actoruid2nursery.get(uid, local_nursery)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # This is set in ``Portal.cancel_actor()``. So if
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # the peer was cancelled we try to wait for them
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # to tear down their side of the connection before
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # moving on with closing our own side.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                local_nursery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ):
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if chan._cancel_called:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.cancel(f"Waiting on cancel request to peer {chan.uid}")
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # XXX: this is a soft wait on the channel (and its
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # underlying transport protocol) to close from the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # remote peer side since we presume that any channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # which is mapped to a sub-actor (i.e. it's managed by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # one of our local nurseries) has a message is sent to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # the peer likely by this actor (which is now in
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # a cancelled condition) when the local runtime here is
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # now cancelled while (presumably) in the middle of msg
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # loop processing.
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                with trio.move_on_after(0.5) as cs:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    cs.shield = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # Attempt to wait for the far end to close the channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # and bail after timeout (2-generals on closure).
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    assert chan.msgstream
							 | 
						
					
						
							
								
									
										
										
										
											2022-06-26 17:47:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f'Draining lingering msgs from stream {chan.msgstream}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    async for msg in chan.msgstream.drain():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # try to deliver any lingering msgs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # before we destroy the channel.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # This accomplishes deterministic
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # ``Portal.cancel_actor()`` cancellation by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # making sure any RPC response to that call is
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # delivered the local calling task.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # TODO: factor this into a helper?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        log.runtime(f'drained {msg} for {chan.uid}')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        cid = msg.get('cid')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if cid:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            # deliver response to local caller/waiter
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            await self._push_result(chan, cid, msg)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await local_nursery.exited.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-10 22:05:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if disconnected:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # if the transport died and this actor is still
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # registered within a local nursery, we report that the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # IPC layer may have failed unexpectedly since it may be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # the cause of other downstream errors.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    entry = local_nursery._children.get(uid)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if entry:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        _, proc, _ = entry
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 13:42:00 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        poll = getattr(proc, 'poll', None)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if poll and poll() is None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-10 22:05:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            log.cancel(
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-11 13:42:00 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                f'Actor {uid} IPC broke but proc is alive?'
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-10 22:05:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            )
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # ``Channel`` teardown and closure sequence
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Drop ref to channel so it can be gc-ed and disconnected
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime(f"Releasing channel {chan} from {chan.uid}")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            chans = self._peers.get(chan.uid)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            chans.remove(chan)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not chans:
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"No more channels for {chan.uid}")
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self._peers.pop(uid, None)
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            log.runtime(f"Peers is {self._peers}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # No more channels to other actors (at all) registered
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # as connected.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if not self._peers:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime("Signalling no more peer channel connections")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self._no_more_peers.set()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # NOTE: block this actor from acquiring the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # debugger-TTY-lock since we have no way to know if we
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # cancelled it and further there is no way to ensure the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # lock will be released if acquired due to having no
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # more active IPC channels.
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-12 16:35:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if _state.is_root_process():
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    pdb_lock = _debug.Lock
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    pdb_lock._blocked.add(uid)
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-12 16:35:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(f"{uid} blocked from pdb locking")
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # if a now stale local task has the TTY lock still
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # we cancel it to allow servicing other requests for
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # the lock.
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    db_cs = pdb_lock._root_local_task_cs_in_debug
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    if (
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        db_cs
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        and not db_cs.cancel_called
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-11 19:22:19 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'STALE DEBUG LOCK DETECTED FOR {uid}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # TODO: figure out why this breaks tests..
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        db_cs.cancel()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # XXX: is this necessary (GC should do it)?
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if chan.connected():
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # if the channel is still connected it may mean the far
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # end has not closed and we may have gotten here due to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # an error and so we should at least try to terminate
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # the channel from this end gracefully.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"Disconnecting channel {chan}")
							 | 
						
					
						
							
								
									
										
										
										
											2018-12-15 07:19:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                try:
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # send a msg loop terminate sentinel
							 | 
						
					
						
							
								
									
										
										
										
											2018-12-15 07:19:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await chan.send(None)
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # XXX: do we want this?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # causes "[104] connection reset by peer" on other end
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # await chan.aclose()
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-12-15 07:19:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                except trio.BrokenResourceError:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-10 22:05:44 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(f"Channel {chan.uid} was already closed")
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def _push_result(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-16 19:05:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan: Channel,
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cid: str,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msg: dict[str, Any],
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Push an RPC result to the local consumer's queue.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 16:38:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid = chan.uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        assert uid, f"`chan.uid` can't be {uid}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ctx = self._contexts[(uid, cid)]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.warning(
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-14 14:25:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f'Ignoring msg from [no-longer/un]known context {uid}:'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f'\n{msg}')
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 16:38:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return await ctx._deliver_msg(msg)
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def get_context(
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan: Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cid: str,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        msg_buffer_size: int | None = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        allow_overruns: bool = False,
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> Context:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Look up or create a new inter-actor-task-IPC-linked task
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        "context" which encapsulates the local task's scheduling
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        enviroment including a ``trio`` cancel scope, a pair of IPC
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        messaging "feeder" channels, and an RPC id unique to the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        task-as-function invocation.
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-24 23:56:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"Getting result queue for {chan.uid} cid {cid}")
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        actor_uid = chan.uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        assert actor_uid
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ctx = self._contexts[(actor_uid, cid)]
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ctx._allow_overruns = allow_overruns
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # adjust buffer size if specified
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 01:00:40 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            state = ctx._send_chan._state  # type: ignore
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if msg_buffer_size and state.max_buffer_size != msg_buffer_size:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                state.max_buffer_size = msg_buffer_size
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyError:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ctx = mk_context(
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                cid,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                msg_buffer_size=msg_buffer_size or self.msg_buffer_size,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _allow_overruns=allow_overruns,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self._contexts[(actor_uid, cid)] = ctx
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return ctx
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def start_remote_task(
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-15 21:23:58 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan: Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ns: str,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        func: str,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-06 00:31:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        kwargs: dict,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        msg_buffer_size: int | None = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        allow_overruns: bool = False,
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 19:27:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> Context:
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Send a ``'cmd'`` message to a remote actor, which starts
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        a remote task-as-function entrypoint.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Synchronously validates the endpoint type  and return a caller
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        side task ``Context`` that can be used to wait for responses
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        delivered by the local runtime's message processing loop.
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 03:17:09 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cid = str(uuid.uuid4())
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        assert chan.uid
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        ctx = self.get_context(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            msg_buffer_size=msg_buffer_size,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            allow_overruns=allow_overruns,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"Sending cmd to {chan.uid}: {ns}.{func}({kwargs})")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        await chan.send(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            {'cmd': (ns, func, kwargs, self.uid, cid)}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Wait on first response msg and validate; this should be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # immediate.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        first_msg = await ctx._recv_chan.receive()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        functype = first_msg.get('functype')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if 'error' in first_msg:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise unpack_error(first_msg, chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        elif functype not in (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'asyncfunc',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'asyncgen',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            'context',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-03 21:51:15 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise ValueError(f"{first_msg} is an invalid response packet?")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ctx._remote_func_type = functype
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return ctx
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-12 15:48:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def _from_parent(
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        parent_addr: Optional[tuple[str, int]],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> tuple[Channel, Optional[tuple[str, int]]]:
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Connect back to the parent actor and conduct initial
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # handshake. From this point on if we error, we
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # attempt to ship the exception back to the parent.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            chan = Channel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                destaddr=parent_addr,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await chan.connect()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # Initial handshake: swap names.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await self._do_handshake(chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            accept_addr: Optional[tuple[str, int]] = None
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self._spawn_method == "trio":
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # Receive runtime state from our parent
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                parent_data: dict[str, Any]
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                parent_data = await chan.recv()
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-16 02:49:12 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Received state from parent:\n"
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"{parent_data}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                accept_addr = (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    parent_data.pop('bind_host'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    parent_data.pop('bind_port'),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-12 15:48:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                rvs = parent_data.pop('_runtime_vars')
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"Runtime vars are: {rvs}")
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-12 15:48:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                rvs['_is_root'] = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                _state._runtime_vars.update(rvs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                for attr, value in parent_data.items():
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 20:21:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if attr == '_arb_addr':
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # XXX: ``msgspec`` doesn't support serializing tuples
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 20:21:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # so just cash manually here since it's what our
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # internals expect.
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        value = tuple(value) if value else None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        self._arb_addr = value
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-11 20:21:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        setattr(self, attr, value)
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return chan, accept_addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except OSError:  # failed to connect
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"Failed to connect to parent @ {parent_addr},"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                " closing server")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await self.cancel()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def _serve_forever(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        handler_nursery: trio.Nursery,
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        *,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # (host, port) to bind for channel server
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        accept_host: tuple[str, int] | None = None,
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        accept_port: int = 0,
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        task_status: TaskStatus[trio.Nursery] = trio.TASK_STATUS_IGNORED,
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Start the channel server, begin listening for new connections.
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This will cause an actor to continue living (blocking) until
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ``cancel_server()`` is called.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._server_down = trio.Event()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            async with trio.open_nursery() as server_n:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                l: list[trio.abc.Listener] = await server_n.start(
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    partial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        trio.serve_tcp,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        self._stream_handler,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # new connections will stay alive even if this server
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # is cancelled
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        handler_nursery=handler_nursery,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        port=accept_port,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        host=accept_host,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2020-12-10 19:07:36 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    "Started tcp server(s) on"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f" {[getattr(l, 'socket', 'unknown socket') for l in l]}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self._listeners.extend(l)
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task_status.started(server_n)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # signal the server is down since nursery above terminated
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self._server_down.set()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-16 04:54:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def cancel_soon(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Cancel this actor asap; can be called from a sync context.
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-16 04:54:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Schedules `.cancel()` to be run immediately just like when
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cancelled by the parent.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-27 16:07:16 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        assert self._service_n
							 | 
						
					
						
							
								
									
										
										
										
											2020-11-16 04:54:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._service_n.start_soon(self.cancel)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    async def cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        requesting_uid: tuple[str, str],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> bool:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Cancel this actor's runtime.
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-01 19:15:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        The "deterministic" teardown sequence in order is:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            - cancel all ongoing rpc tasks by cancel scope
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            - cancel the channel server to prevent new inbound
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              connections
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            - cancel the "service" nursery reponsible for
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								              spawning new rpc tasks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            - return control the parent channel message loop
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 23:25:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.cancel(f"{self.uid} is trying to cancel")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self._cancel_called_remote: tuple = requesting_uid
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._cancel_called = True
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-12 15:48:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-01 19:15:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # cancel all ongoing rpc tasks
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        with trio.CancelScope(shield=True):
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-28 17:02:33 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # kill any debugger request task to avoid deadlock
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # with the root actor in this tree
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-29 20:03:26 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            dbcs = _debug.Lock._debugger_request_cs
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-28 17:02:33 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if dbcs is not None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 23:25:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.cancel("Cancelling active debugger request")
							 | 
						
					
						
							
								
									
										
										
										
											2020-09-28 17:02:33 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                dbcs.cancel()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # kill all ongoing tasks
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            await self.cancel_rpc_tasks(requesting_uid=requesting_uid)
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # stop channel server
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self.cancel_server()
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self._server_down is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await self._server_down.wait()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f'{self.uid} was likely cancelled before it started')
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-09 00:57:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-14 17:46:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # cancel all rpc tasks permanently
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if self._service_n:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                self._service_n.cancel_scope.cancel()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-08 03:13:47 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.cancel(f"{self.uid} called `Actor.cancel()`")
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-13 15:48:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._cancel_complete.set()
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # XXX: hard kill logic if needed?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # def _hard_mofo_kill(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #     # If we're the root actor or zombied kill everything
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #     if self._parent_chan is None:  # TODO: more robust check
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #         root = trio.lowlevel.current_root_task()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #         for n in root.child_nurseries:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    #             n.cancel_scope.cancel()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    async def _cancel_task(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        cid: str,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan: Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        requesting_uid: tuple[str, str] | None = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> bool:
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Cancel a local task by call-id / channel.
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Note this method will be treated as a streaming function
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        by remote actor-callers due to the declaration of ``ctx``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        in the signature (for now).
							 | 
						
					
						
							
								
									
										
										
										
											2022-07-23 00:45:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # right now this is only implicitly called by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # streaming IPC but it should be called
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # to cancel any remotely spawned task
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-16 02:59:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # this ctx based lookup ensures the requested task to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # be cancelled was indeed spawned by a request from this channel
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            ctx, func, is_complete = self._rpc_tasks[(chan, cid)]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            scope = ctx._scope
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-16 02:59:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        except KeyError:
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 23:25:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.cancel(f"{cid} has already completed/terminated?")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return True
							 | 
						
					
						
							
								
									
										
										
										
											2019-02-16 02:59:42 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 23:25:28 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.cancel(
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f"Cancelling task:\ncid: {cid}\nfunc: {func}\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f"peer: {chan.uid}\n")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ctx._cancel_called_remote is None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            and requesting_uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ctx._cancel_called_remote: tuple = requesting_uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-24 01:01:29 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # don't allow cancelling this function mid-execution
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # (is this necessary?)
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if func is self._cancel_task:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return True
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        # TODO: shouldn't we eventually be calling ``Context.cancel()``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # directly here instead (since that method can handle both
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # side's calls into it?
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        scope.cancel()
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # wait for _invoke to mark the task complete
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            'Waiting on task to cancel:\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f'cid: {cid}\nfunc: {func}\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f'peer: {chan.uid}\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        await is_complete.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-26 20:14:45 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(
							 | 
						
					
						
							
								
									
										
										
										
											2019-01-21 05:16:20 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f"Sucessfully cancelled task:\ncid: {cid}\nfunc: {func}\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f"peer: {chan.uid}\n")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        return True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-04 21:58:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def cancel_rpc_tasks(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        only_chan: Channel | None = None,
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        requesting_uid: tuple[str, str] | None = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-04 21:58:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Cancel all existing RPC responder tasks using the cancel scope
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-01 19:15:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        registered for each.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        tasks = self._rpc_tasks
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-10 15:42:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if tasks:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.cancel(f"Cancelling all {len(tasks)} rpc tasks:\n{tasks} ")
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                (chan, cid),
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                (ctx, func, is_complete),
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ) in tasks.copy().items():
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-10 15:42:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if only_chan is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if only_chan != chan:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        continue
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-04 21:58:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-10 15:42:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # TODO: this should really done in a nursery batch
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if func != self._cancel_task:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    await self._cancel_task(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        requesting_uid=requesting_uid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2020-10-04 21:58:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-10 15:42:32 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"Waiting for remaining rpc tasks to complete {tasks}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await self._ongoing_rpc_tasks.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-01 19:15:18 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def cancel_server(self) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Cancel the internal channel server nursery thereby
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        preventing any new inbound connections from being established.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if self._server_n:
							 | 
						
					
						
							
								
									
										
										
										
											2021-10-05 21:07:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime("Shutting down channel server")
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-08 18:55:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self._server_n.cancel_scope.cancel()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    @property
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def accept_addr(self) -> Optional[tuple[str, int]]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Primary address to which the channel server is bound.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-12-10 05:55:03 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # throws OSError on failure
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return self._listeners[0].socket.getsockname()  # type: ignore
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def get_parent(self) -> Portal:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Return a portal to our parent actor.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        assert self._parent_chan, "No parent channel for this actor?"
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return Portal(self._parent_chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def get_chans(self, uid: tuple[str, str]) -> list[Channel]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Return all channels to the actor with provided uid.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-20 02:13:13 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return self._peers[uid]
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def _do_handshake(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan: Channel
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 18:52:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> tuple[str, str]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Exchange (name, UUIDs) identifiers as the first communication step.
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        These are essentially the "mailbox addresses" found in actor model
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        parlance.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 20:09:16 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        await chan.send(self.uid)
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        value = await chan.recv()
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid: tuple[str, str] = (str(value[0]), str(value[1]))
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 18:52:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not isinstance(uid, tuple):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            raise ValueError(f"{uid} is not a valid uid?!")
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        chan.uid = str(uid[0]), str(uid[1])
							 | 
						
					
						
							
								
									
										
										
										
											2021-06-27 15:37:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(f"Handshake with actor {uid}@{chan.raddr} complete")
							 | 
						
					
						
							
								
									
										
										
										
											2019-03-23 17:50:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-06-29 02:44:16 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def is_infected_aio(self) -> bool:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return self._infected_aio
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-07-20 20:06:50 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								async def async_main(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    actor: Actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    accept_addr: Optional[tuple[str, int]] = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # XXX: currently ``parent_addr`` is only needed for the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # ``multiprocessing`` backend (which pickles state sent to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # the child instead of relaying it over the connect-back
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # channel). Once that backend is removed we can likely just
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # change this to a simple ``is_subactor: bool`` which will
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # be False when running as root actor and True when as
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # a subactor.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    parent_addr: Optional[tuple[str, int]] = None,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    task_status: TaskStatus[None] = trio.TASK_STATUS_IGNORED,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								) -> None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    Actor runtime entrypoint; start the IPC channel server, maybe connect
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    back to the parent, and startup all core machinery tasks.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    A "root" (or "top-level") nursery for this actor is opened here and
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    when cancelled/terminated effectively closes the actor's "runtime".
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-13 17:12:17 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    # attempt to retreive ``trio``'s sigint handler and stash it
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # on our debugger lock state.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    _debug.Lock._trio_handler = signal.getsignal(signal.SIGINT)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    registered_with_arbiter = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # establish primary connection with immediate parent
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        actor._parent_chan = None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if parent_addr is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            actor._parent_chan, accept_addr_rent = await actor._from_parent(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                parent_addr)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # either it's passed in because we're not a child
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # or because we're running in mp mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if accept_addr_rent is not None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                accept_addr = accept_addr_rent
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # load exposed/allowed RPC modules
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # XXX: do this **after** establishing a channel to the parent
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # but **before** starting the message loop for that channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # such that import errors are properly propagated upwards
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        actor.load_modules()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # The "root" nursery ensures the channel with the immediate
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # parent is kept alive as a resilient service until
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # cancellation steps have (mostly) occurred in
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # a deterministic way.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        async with trio.open_nursery() as root_nursery:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            actor._root_n = root_nursery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert actor._root_n
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            async with trio.open_nursery() as service_nursery:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # This nursery is used to handle all inbound
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # connections to us such that if the TCP server
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # is killed, connections can continue to process
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # in the background until this nursery is cancelled.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                actor._service_n = service_nursery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                assert actor._service_n
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # Startup up the channel server with,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # - subactor: the bind address is sent by our parent
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                #   over our established channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # - root actor: the ``accept_addr`` passed to this method
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                assert accept_addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                host, port = accept_addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                actor._server_n = await service_nursery.start(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    partial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        actor._serve_forever,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        service_nursery,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        accept_host=host,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        accept_port=port
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                accept_addr = actor.accept_addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if _state._runtime_vars['_is_root']:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    _state._runtime_vars['_root_mailbox'] = accept_addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # Register with the arbiter if we're told its addr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"Registering {actor} for role `{actor.name}`")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                assert isinstance(actor._arb_addr, tuple)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                async with get_arbiter(*actor._arb_addr) as arb_portal:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await arb_portal.run_from_ns(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        'self',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        'register_actor',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        uid=actor.uid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        sockaddr=accept_addr,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                registered_with_arbiter = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # init steps complete
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                task_status.started()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # Begin handling our new connection back to our
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # parent. This is done last since we don't want to
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # start processing parent requests until our channel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # server is 100% up and running.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if actor._parent_chan:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await root_nursery.start(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        partial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            process_messages,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            actor._parent_chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            shield=True,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime("Waiting on service nursery to complete")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "Service nursery complete\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "Waiting on root nursery to complete"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Blocks here as expected until the root nursery is
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # killed (i.e. this actor is cancelled or signalled by the parent)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    except Exception as err:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        log.runtime("Closing all actor lifetime contexts")
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-29 19:08:04 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        actor.lifetime_stack.close()
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not registered_with_arbiter:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # TODO: I guess we could try to connect back
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # to the parent through a channel and engage a debugger
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # once we have that all working with std streams locking?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.exception(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"Actor errored and failed to register with arbiter "
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"@ {actor._arb_addr}?")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.error(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "\n\n\t^^^ THIS IS PROBABLY A TRACTOR BUGGGGG!!! ^^^\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "\tCALMLY CALL THE AUTHORITIES AND HIDE YOUR CHILDREN.\n\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "\tYOUR PARENT CODE IS GOING TO KEEP WORKING FINE!!!\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                "\tTHIS IS HOW RELIABlE SYSTEMS ARE SUPPOSED TO WORK!?!?\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if actor._parent_chan:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await try_ship_error_to_parent(actor._parent_chan, err)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # always!
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        match err:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            case ContextCancelled():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f'Actor: {actor.uid} was task-context-cancelled with,\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f'str(err)'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            case _:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.exception("Actor errored:")
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.info("Runtime nursery complete")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # tear down all lifetime contexts if not in guest mode
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # XXX: should this just be in the entrypoint?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.info("Closing all actor lifetime contexts")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # TODO: we can't actually do this bc the debugger
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # uses the _service_n to spawn the lock task, BUT,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # in theory if we had the root nursery surround this finally
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # block it might be actually possible to debug THIS
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # machinery in the same way as user task code?
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # if actor.name == 'brokerd.ib':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        #     with trio.CancelScope(shield=True):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        #         await _debug.breakpoint()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-29 19:08:04 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        actor.lifetime_stack.close()
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Unregister actor from the arbiter
							 | 
						
					
						
							
								
									
										
										
										
											2022-11-10 00:22:33 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            registered_with_arbiter
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            and not actor.is_arbiter
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            failed = False
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-13 05:23:27 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            assert isinstance(actor._arb_addr, tuple)
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            with trio.move_on_after(0.5) as cs:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                cs.shield = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    async with get_arbiter(*actor._arb_addr) as arb_portal:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        await arb_portal.run_from_ns(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            'self',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            'unregister_actor',
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            uid=actor.uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                except OSError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    failed = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if cs.cancelled_caught:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                failed = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if failed:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Failed to unregister {actor.name} from arbiter")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # Ensure all peers (actors connected to us as clients) are finished
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not actor._no_more_peers.is_set():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if any(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                chan.connected() for chan in chain(*actor._peers.values())
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Waiting for remaining peers {actor._peers} to clear")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                with trio.CancelScope(shield=True):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    await actor._no_more_peers.wait()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime("All peer channels are complete")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    log.runtime("Runtime completed")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								async def process_messages(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    actor: Actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    chan: Channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    shield: bool = False,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    task_status: TaskStatus[trio.CancelScope] = trio.TASK_STATUS_IGNORED,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								) -> bool:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    This is the per-channel, low level RPC task scheduler loop.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    Receive multiplexed RPC request messages from some remote process,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    spawn handler tasks depending on request type and deliver responses
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    or boxed errors back to the remote caller (task).
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # TODO: once https://github.com/python-trio/trio/issues/467 gets
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # worked out we'll likely want to use that!
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    msg: dict | None = None
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    nursery_cancelled_before_task: bool = False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    log.runtime(f"Entering msg loop for {chan} from {chan.uid}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        with trio.CancelScope(shield=shield) as loop_cs:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # this internal scope allows for keeping this message
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # loop running despite the current task having been
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # cancelled (eg. `open_portal()` may call this method from
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # a locally spawned task) and recieve this scope using
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # ``scope = Nursery.start()``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            task_status.started(loop_cs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            async for msg in chan:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if msg is None:  # loop terminate sentinel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"Channel to {chan.uid} terminated?\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        "Cancelling all associated tasks..")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    for (channel, cid) in actor._rpc_tasks.copy():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if channel is chan:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            await actor._cancel_task(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                channel,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f"Msg loop signalled to terminate for"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f" {chan} from {chan.uid}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.transport(   # type: ignore
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Received msg {msg} from {chan.uid}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                cid = msg.get('cid')
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if cid:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # deliver response to local caller/waiter
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    # via its per-remote-context memory channel.
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    await actor._push_result(chan, cid, msg)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"Waiting on next msg for {chan} from {chan.uid}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # TODO: implement with ``match:`` syntax?
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # process command request
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    ns, funcname, kwargs, actorid, cid = msg['cmd']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                except KeyError:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # This is the non-rpc error case, that is, an
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # error **not** raised inside a call to ``_invoke()``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # (i.e. no cid was provided in the msg - see above).
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # Push this error to all local channel consumers
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # (normally portals) by marking the channel as errored
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    assert chan.uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    exc = unpack_error(msg, chan=chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    chan._exc = exc
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    raise exc
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Processing request from {actorid}\n"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"{ns}.{funcname}({kwargs})")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if ns == 'self':
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if funcname == 'cancel':
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        func = actor.cancel
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        kwargs['requesting_uid'] = chan.uid
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        # don't start entire actor runtime cancellation
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # if this actor is currently in debug mode!
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        pdb_complete = _debug.Lock.local_pdb_complete
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        if pdb_complete:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            await pdb_complete.wait()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # we immediately start the runtime machinery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # shutdown
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        with trio.CancelScope(shield=True):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            # actor.cancel() was called so kill this
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            # msg loop and break out into
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:29:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            # ``async_main()``
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            log.cancel(
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                "Actor runtime for was remotely cancelled "
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                f"by {chan.uid}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            await _invoke(
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                                actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                func,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                kwargs,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                is_rpc=False,
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'Cancelling msg loop for {chan.uid}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        loop_cs.cancel()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    if funcname == '_cancel_task':
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        func = actor._cancel_task
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # we immediately start the runtime machinery
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # shutdown
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        # with trio.CancelScope(shield=True):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        kwargs['chan'] = chan
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        target_cid = kwargs['cid']
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        kwargs['requesting_uid'] = chan.uid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'Remote request to cancel task\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'remote actor: {chan.uid}\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            f'task: {target_cid}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            await _invoke(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                func,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                kwargs,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                                is_rpc=False,
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                            )
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        except BaseException:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            log.exception("failed to cancel task?")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # normally registry methods, eg.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        # ``.register_actor()`` etc.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        func = getattr(actor, funcname)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # complain to client about restricted modules
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    try:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        func = actor._get_rpc_func(ns, funcname)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    except (ModuleNotExposed, AttributeError) as err:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        err_msg = pack_error(err)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        err_msg['cid'] = cid
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        await chan.send(err_msg)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # spin up a task for the requested function
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(f"Spawning task for {func}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                assert actor._service_n
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                try:
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    ctx: Context = await actor._service_n.start(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        partial(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            _invoke,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            actor,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            cid,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            chan,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            func,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                            kwargs,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        ),
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        name=funcname,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-09 17:12:50 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    RuntimeError,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    BaseExceptionGroup,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                ):
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    # avoid reporting a benign race condition
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # during actor runtime teardown.
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    nursery_cancelled_before_task: bool = True
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    break
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                # in the lone case where a ``Context`` is not
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # delivered, it's likely going to be a locally
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                # scoped exception from ``_invoke()`` itself.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                if isinstance(ctx, Exception):
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    log.warning(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        f"Task for RPC func {func} failed with"
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        f"{ctx}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    continue
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # mark that we have ongoing rpc tasks
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    actor._ongoing_rpc_tasks = trio.Event()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.runtime(f"RPC func is {func}")
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                    # store cancel scope such that the rpc task can be
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    # cancelled gracefully if requested
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    actor._rpc_tasks[(chan, cid)] = (
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        ctx,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        func,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                        trio.Event(),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    f"Waiting on next msg for {chan} from {chan.uid}")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # end of async for, channel disconnect vis
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # ``trio.EndOfChannel``
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f"{chan} for {chan.uid} disconnected, cancelling tasks"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await actor.cancel_rpc_tasks(chan)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        TransportClosed,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # channels "breaking" (for TCP streams by EOF or 104
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # connection-reset) is ok since we don't have a teardown
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # handshake for them (yet) and instead we simply bail out of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # the message loop and expect the teardown sequence to clean
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # up.
							 | 
						
					
						
							
								
									
										
										
										
											2023-01-26 00:13:34 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f'channel from {chan.uid} closed abruptly:\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f'-> {chan.raddr}\n'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # transport **was** disconnected
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-10-09 17:12:50 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    except (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Exception,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        BaseExceptionGroup,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) as err:
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if nursery_cancelled_before_task:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            sn = actor._service_n
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            assert sn and sn.cancel_scope.cancel_called
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            log.cancel(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                f'Service nursery cancelled before it handled {funcname}'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        else:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # ship any "internal" exception (i.e. one from internal
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # machinery not from an rpc task) to parent
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            match err:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                case ContextCancelled():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.cancel(
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        f'Actor: {actor.uid} was context-cancelled with,\n'
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-07 20:07:26 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                        f'str(err)'
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    )
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                case _:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    log.exception("Actor errored:")
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            if actor._parent_chan:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                await try_ship_error_to_parent(actor._parent_chan, err)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # if this is the `MainProcess` we expect the error broadcasting
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # above to trigger an error at consuming portal "checkpoints"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        raise
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    finally:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # msg debugging for when he machinery is brokey
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        log.runtime(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            f"Exiting msg loop for {chan} from {chan.uid} "
							 | 
						
					
						
							
								
									
										
										
										
											2023-04-13 20:03:35 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            f"with last msg:\n{msg}"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        )
							 | 
						
					
						
							
								
									
										
										
										
											2022-08-03 19:14:36 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    # transport **was not** disconnected
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    return False
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								class Arbiter(Actor):
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    A special actor who knows all the other actors and always has
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-26 21:29:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    access to a top level nursery.
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    The arbiter is by default the first actor spawned on each host
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    and is responsible for keeping track of all other actors for
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    coordination purposes. If a new main process is launched and an
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    arbiter is already running that arbiter will be used.
							 | 
						
					
						
							
								
									
										
										
										
											2021-11-04 15:52:08 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    '''
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    is_arbiter = True
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __init__(self, *args, **kwargs) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-12-02 17:34:27 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._registry: dict[
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[str, str],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            tuple[str, int],
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self._waiters: dict[
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            str,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # either an event to sync to receiving an actor uid (which
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # is filled in once the actor has sucessfully registered),
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            # or that uid after registry is complete.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            list[trio.Event | tuple[str, str]]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        ] = {}
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-26 21:29:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        super().__init__(*args, **kwargs)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    async def find_actor(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        name: str,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> tuple[str, int] | None:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for uid, sockaddr in self._registry.items():
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-26 21:29:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if name in uid:
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                return sockaddr
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-31 21:16:24 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return None
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-03 19:40:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def get_registry(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:52:04 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> dict[str, tuple[str, int]]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Return current name registry.
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This method is async to allow for cross-actor invocation.
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-03 22:42:23 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # NOTE: requires ``strict_map_key=False`` to the msgpack
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # unpacker since we have tuples as keys (not this makes the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # arbiter suscetible to hashdos):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # https://github.com/msgpack/msgpack-python#major-breaking-changes-in-msgpack-10
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return {'.'.join(key): val for key, val in self._registry.items()}
							 | 
						
					
						
							
								
									
										
										
										
											2020-08-03 19:40:41 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-26 17:12:29 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def wait_for_actor(
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        name: str,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> list[tuple[str, int]]:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        Wait for a particular actor to register.
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        This is a blocking call if no actor by the provided name is currently
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        registered.
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        '''
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        sockaddrs: list[tuple[str, int]] = []
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        sockaddr: tuple[str, int]
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for (aname, _), sockaddr in self._registry.items():
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if name == aname:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                sockaddrs.append(sockaddr)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not sockaddrs:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            waiter = trio.Event()
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            self._waiters.setdefault(name, []).append(waiter)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            await waiter.wait()
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            for uid in self._waiters[name]:
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								                if not isinstance(uid, trio.Event):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                    sockaddrs.append(self._registry[uid])
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return sockaddrs
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-04-27 12:46:54 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def register_actor(
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 18:52:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid: tuple[str, str],
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        sockaddr: tuple[str, int]
							 | 
						
					
						
							
								
									
										
										
										
											2021-07-01 18:52:52 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-26 17:12:29 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        uid = name, _ = (str(uid[0]), str(uid[1]))
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._registry[uid] = (str(sockaddr[0]), int(sockaddr[1]))
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        # pop and signal all waiter events
							 | 
						
					
						
							
								
									
										
										
										
											2022-12-12 18:18:22 +00:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        events = self._waiters.pop(name, [])
							 | 
						
					
						
							
								
									
										
										
										
											2018-08-13 03:59:19 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._waiters.setdefault(name, []).append(uid)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        for event in events:
							 | 
						
					
						
							
								
									
										
										
										
											2018-09-08 13:40:35 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            if isinstance(event, trio.Event):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								                event.set()
							 | 
						
					
						
							
								
									
										
										
										
											2018-07-14 20:09:05 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    async def unregister_actor(
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self,
							 | 
						
					
						
							
								
									
										
										
										
											2022-02-15 13:48:07 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid: tuple[str, str]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-06 15:41:34 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    ) -> None:
							 | 
						
					
						
							
								
									
										
										
										
											2021-09-08 00:24:02 +00:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        uid = (str(uid[0]), str(uid[1]))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        self._registry.pop(uid)
							 |