Support a `._state.last_actor()` getter
Not sure if it's really that useful other then for reporting errors from `current_actor()` but at least it alerts `tractor` devs and/or users when the runtime has already terminated vs. hasn't been started yet/correctly. Set the `._last_actor_terminated: tuple` in the root's final block which allows testing for an already terminated tree which is the case where `._state._current_actor == None` and the last is set.modden_spawn_from_client_req
parent
b29d33d603
commit
4c3c3e4b56
|
@ -348,6 +348,7 @@ async def open_root_actor(
|
|||
await actor.cancel(None) # self cancel
|
||||
finally:
|
||||
_state._current_actor = None
|
||||
_state._last_actor_terminated = actor
|
||||
|
||||
# restore built-in `breakpoint()` hook state
|
||||
sys.breakpointhook = builtin_bp_handler
|
||||
|
|
|
@ -18,12 +18,18 @@
|
|||
Per process state
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
from typing import (
|
||||
Optional,
|
||||
Any,
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
|
||||
_current_actor: Optional['Actor'] = None # type: ignore # noqa
|
||||
if TYPE_CHECKING:
|
||||
from ._runtime import Actor
|
||||
|
||||
|
||||
_current_actor: Actor|None = None # type: ignore # noqa
|
||||
_last_actor_terminated: Actor|None = None
|
||||
_runtime_vars: dict[str, Any] = {
|
||||
'_debug_mode': False,
|
||||
'_is_root': False,
|
||||
|
@ -31,14 +37,49 @@ _runtime_vars: dict[str, Any] = {
|
|||
}
|
||||
|
||||
|
||||
def current_actor(err_on_no_runtime: bool = True) -> 'Actor': # type: ignore # noqa
|
||||
def last_actor() -> Actor|None:
|
||||
'''
|
||||
Try to return last active `Actor` singleton
|
||||
for this process.
|
||||
|
||||
For case where runtime already exited but someone is asking
|
||||
about the "last" actor probably to get its `.uid: tuple`.
|
||||
|
||||
'''
|
||||
return _last_actor_terminated
|
||||
|
||||
|
||||
def current_actor(
|
||||
err_on_no_runtime: bool = True,
|
||||
) -> Actor:
|
||||
'''
|
||||
Get the process-local actor instance.
|
||||
|
||||
'''
|
||||
if (
|
||||
err_on_no_runtime
|
||||
and _current_actor is None
|
||||
):
|
||||
msg: str = 'No local actor has been initialized yet'
|
||||
from ._exceptions import NoRuntime
|
||||
if _current_actor is None and err_on_no_runtime:
|
||||
raise NoRuntime("No local actor has been initialized yet")
|
||||
|
||||
if last := last_actor():
|
||||
msg += (
|
||||
f'Apparently the lact active actor was\n'
|
||||
f'|_{last}\n'
|
||||
f'|_{last.uid}\n'
|
||||
)
|
||||
# no actor runtime has (as of yet) ever been started for
|
||||
# this process.
|
||||
else:
|
||||
msg += (
|
||||
'No last actor found?\n'
|
||||
'Did you forget to open one of:\n\n'
|
||||
'- `tractor.open_root_actor()`\n'
|
||||
'- `tractor.open_nursery()`\n'
|
||||
)
|
||||
|
||||
raise NoRuntime(msg)
|
||||
|
||||
return _current_actor
|
||||
|
||||
|
|
|
@ -533,12 +533,15 @@ async def open_nursery(
|
|||
|
||||
'''
|
||||
implicit_runtime: bool = False
|
||||
|
||||
actor = current_actor(err_on_no_runtime=False)
|
||||
actor: Actor = current_actor(
|
||||
err_on_no_runtime=False
|
||||
)
|
||||
|
||||
try:
|
||||
if actor is None and is_main_process():
|
||||
|
||||
if (
|
||||
actor is None
|
||||
and is_main_process()
|
||||
):
|
||||
# if we are the parent process start the
|
||||
# actor runtime implicitly
|
||||
log.info("Starting actor runtime!")
|
||||
|
|
Loading…
Reference in New Issue