Add per-actor parent-main replay opt-out
Let actor callers skip replaying the parent __main__ during child startup so downstream integrations can avoid inheriting incompatible bootstrap state without changing the default spawn behavior.subint_spawner_backend
parent
9f8e9eb739
commit
f5301d3fb0
|
|
@ -197,3 +197,50 @@ def test_loglevel_propagated_to_subactor(
|
||||||
# ensure subactor spits log message on stderr
|
# ensure subactor spits log message on stderr
|
||||||
captured = capfd.readouterr()
|
captured = capfd.readouterr()
|
||||||
assert 'yoyoyo' in captured.err
|
assert 'yoyoyo' in captured.err
|
||||||
|
|
||||||
|
|
||||||
|
def test_start_actor_can_skip_parent_main_replay(monkeypatch, reg_addr):
|
||||||
|
captured_parent_main_data: list[dict[str, str]] = []
|
||||||
|
from tractor.runtime import _supervise as supervise_module
|
||||||
|
|
||||||
|
async def fake_new_proc(
|
||||||
|
name: str,
|
||||||
|
actor_nursery,
|
||||||
|
subactor,
|
||||||
|
errors,
|
||||||
|
bind_addrs,
|
||||||
|
parent_addr,
|
||||||
|
_runtime_vars,
|
||||||
|
*,
|
||||||
|
infect_asyncio: bool = False,
|
||||||
|
task_status=trio.TASK_STATUS_IGNORED,
|
||||||
|
proc_kwargs: dict[str, Any] = {},
|
||||||
|
) -> None:
|
||||||
|
captured_parent_main_data.append(dict(subactor._parent_main_data))
|
||||||
|
task_status.started(object())
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
supervise_module._spawn,
|
||||||
|
'new_proc',
|
||||||
|
fake_new_proc,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def main() -> None:
|
||||||
|
async with tractor.open_root_actor(
|
||||||
|
registry_addrs=[reg_addr],
|
||||||
|
):
|
||||||
|
async with tractor.open_nursery() as an:
|
||||||
|
await an.start_actor(
|
||||||
|
'replaying-parent-main',
|
||||||
|
enable_modules=[__name__],
|
||||||
|
)
|
||||||
|
await an.start_actor(
|
||||||
|
'isolated-parent-main',
|
||||||
|
enable_modules=[__name__],
|
||||||
|
replay_parent_main=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
trio.run(main)
|
||||||
|
|
||||||
|
assert captured_parent_main_data[0]
|
||||||
|
assert captured_parent_main_data[1] == {}
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ class ActorNursery:
|
||||||
loglevel: str|None = None, # set log level per subactor
|
loglevel: str|None = None, # set log level per subactor
|
||||||
debug_mode: bool|None = None,
|
debug_mode: bool|None = None,
|
||||||
infect_asyncio: bool = False,
|
infect_asyncio: bool = False,
|
||||||
|
replay_parent_main: bool = True,
|
||||||
|
|
||||||
# TODO: ideally we can rm this once we no longer have
|
# TODO: ideally we can rm this once we no longer have
|
||||||
# a `._ria_nursery` since the dependent APIs have been
|
# a `._ria_nursery` since the dependent APIs have been
|
||||||
|
|
@ -206,6 +207,10 @@ class ActorNursery:
|
||||||
Start a (daemon) actor: an process that has no designated
|
Start a (daemon) actor: an process that has no designated
|
||||||
"main task" besides the runtime.
|
"main task" besides the runtime.
|
||||||
|
|
||||||
|
Pass ``replay_parent_main=False`` to keep this child on its own
|
||||||
|
bootstrap module instead of re-running the parent's ``__main__``
|
||||||
|
during startup.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
__runtimeframe__: int = 1 # noqa
|
__runtimeframe__: int = 1 # noqa
|
||||||
loglevel: str = (
|
loglevel: str = (
|
||||||
|
|
@ -246,6 +251,8 @@ class ActorNursery:
|
||||||
# verbatim relay this actor's registrar addresses
|
# verbatim relay this actor's registrar addresses
|
||||||
registry_addrs=current_actor().registry_addrs,
|
registry_addrs=current_actor().registry_addrs,
|
||||||
)
|
)
|
||||||
|
if not replay_parent_main:
|
||||||
|
subactor._parent_main_data = {}
|
||||||
parent_addr: UnwrappedAddress = self._actor.accept_addr
|
parent_addr: UnwrappedAddress = self._actor.accept_addr
|
||||||
assert parent_addr
|
assert parent_addr
|
||||||
|
|
||||||
|
|
@ -289,6 +296,7 @@ class ActorNursery:
|
||||||
enable_modules: list[str] | None = None,
|
enable_modules: list[str] | None = None,
|
||||||
loglevel: str | None = None, # set log level per subactor
|
loglevel: str | None = None, # set log level per subactor
|
||||||
infect_asyncio: bool = False,
|
infect_asyncio: bool = False,
|
||||||
|
replay_parent_main: bool = True,
|
||||||
proc_kwargs: dict[str, any] = {},
|
proc_kwargs: dict[str, any] = {},
|
||||||
|
|
||||||
**kwargs, # explicit args to ``fn``
|
**kwargs, # explicit args to ``fn``
|
||||||
|
|
@ -320,6 +328,7 @@ class ActorNursery:
|
||||||
# use the run_in_actor nursery
|
# use the run_in_actor nursery
|
||||||
nursery=self._ria_nursery,
|
nursery=self._ria_nursery,
|
||||||
infect_asyncio=infect_asyncio,
|
infect_asyncio=infect_asyncio,
|
||||||
|
replay_parent_main=replay_parent_main,
|
||||||
proc_kwargs=proc_kwargs
|
proc_kwargs=proc_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue