Assign `ctx._local_error` ASAP from `.open_context()`

Such that `.outcome` related fields render nicely asap for logging
withing `Portal.open_context()` itself.
modden_spawn_from_client_req
Tyler Goodlet 2024-03-08 15:48:13 -05:00
parent 7cafb59ab7
commit c56d4b0a79
1 changed files with 13 additions and 8 deletions

View File

@ -30,7 +30,7 @@ from typing import (
Any, Any,
Callable, Callable,
AsyncGenerator, AsyncGenerator,
Type, # Type,
) )
from functools import partial from functools import partial
from dataclasses import dataclass from dataclasses import dataclass
@ -41,8 +41,7 @@ from async_generator import asynccontextmanager
from .trionics import maybe_open_nursery from .trionics import maybe_open_nursery
from .devx import ( from .devx import (
# acquire_debug_lock, # _debug,
# pause,
maybe_wait_for_debugger, maybe_wait_for_debugger,
) )
from ._state import ( from ._state import (
@ -673,6 +672,7 @@ class Portal:
# `Nursery.cancel_scope.cancel()`) # `Nursery.cancel_scope.cancel()`)
except ContextCancelled as ctxc: except ContextCancelled as ctxc:
scope_err = ctxc scope_err = ctxc
ctx._local_error: BaseException = scope_err
ctxc_from_callee = ctxc ctxc_from_callee = ctxc
# XXX TODO XXX: FIX THIS debug_mode BUGGGG!!! # XXX TODO XXX: FIX THIS debug_mode BUGGGG!!!
@ -684,7 +684,7 @@ class Portal:
# debugging the tractor-runtime itself using it's # debugging the tractor-runtime itself using it's
# own `.devx.` tooling! # own `.devx.` tooling!
# #
# await pause() # await _debug.pause()
# CASE 2: context was cancelled by local task calling # CASE 2: context was cancelled by local task calling
# `.cancel()`, we don't raise and the exit block should # `.cancel()`, we don't raise and the exit block should
@ -745,18 +745,20 @@ class Portal:
) as caller_err: ) as caller_err:
scope_err = caller_err scope_err = caller_err
ctx._local_error: BaseException = scope_err
# XXX: ALWAYS request the context to CANCEL ON any ERROR. # XXX: ALWAYS request the context to CANCEL ON any ERROR.
# NOTE: `Context.cancel()` is conversely NEVER CALLED in # NOTE: `Context.cancel()` is conversely NEVER CALLED in
# the `ContextCancelled` "self cancellation absorbed" case # the `ContextCancelled` "self cancellation absorbed" case
# handled in the block above ^^^ !! # handled in the block above ^^^ !!
# await _debug.pause()
log.cancel( log.cancel(
'Context terminated due to\n\n' 'Context terminated due to\n\n'
f'{caller_err}\n' f'.outcome => {ctx.repr_outcome()}\n'
) )
if debug_mode(): if debug_mode():
# async with acquire_debug_lock(self.actor.uid): # async with _debug.acquire_debug_lock(self.actor.uid):
# pass # pass
# TODO: factor ^ into below for non-root cases? # TODO: factor ^ into below for non-root cases?
was_acquired: bool = await maybe_wait_for_debugger( was_acquired: bool = await maybe_wait_for_debugger(
@ -818,6 +820,7 @@ class Portal:
# this task didn't know until final teardown # this task didn't know until final teardown
# / value collection. # / value collection.
scope_err = berr scope_err = berr
ctx._local_error: BaseException = scope_err
raise raise
# yes! this worx Bp # yes! this worx Bp
@ -927,8 +930,10 @@ class Portal:
# should be stored as the `Context._local_error` and # should be stored as the `Context._local_error` and
# used in determining `Context.cancelled_caught: bool`. # used in determining `Context.cancelled_caught: bool`.
if scope_err is not None: if scope_err is not None:
ctx._local_error: BaseException = scope_err # sanity, tho can remove?
etype: Type[BaseException] = type(scope_err) assert ctx._local_error is scope_err
# ctx._local_error: BaseException = scope_err
# etype: Type[BaseException] = type(scope_err)
# CASE 2 # CASE 2
if ( if (