As per some discussion in the trio gitter and starting something
toward #22 and supporting our debugger crash mode from within
a trio-compat task nursery.
Idea: a trio.Nursery API for optionally allowing a user to define a per-task manager
But why?
Well if you wanted any of the following (some of which are implemented
in the module script in this patch):
generally gain access to lower level trio.Nursery"internals" for any
per-task oriented purpose.
some way to wrap your own "task handle" so you could do things like
waiting on a task to finish and get its result.
allow hooking into each task's exit/teardown (phase) for the purposes
of debugging crashes, (unexpected) cancels or just generally tracing
the trio per task control flow.
enable more granular task supervision strategies like one_for_one
from erlang/elixir and friends.
ToDo:
[x] offer a task_manager context-manager-as-generator API such
that the current TaskOutcome struct is not tied to the
internals of the ScopePerTaskNursery.start_soon() implementation.
[x] ideally the outcome: Outcome = yield (cs, ..) is delivered to
the user defined mngr via a Outcome.send(mngr) call such that only
raw trio (dependency) internal types are provided to the user for
wrapping / adjusting.
NOTE: didn't use Outcome.send() bc it would send the underlying
value, not the outcome instance; not sure if that's best?
[ ] way better naming since most of this was whipped up on the
first try and getting good names is probably going to be tricky :joy:
[x] @task_manager is maybe better? @task_scope_manager?
[x] ScopePerTaskNursery is terrible.. how about TaskScopedNursery?
now i'm thinking you don't need much at all, TaskManagerNursery?
[x] TaskOutcome.unwrap() seems wrong, despite it being an example of
a user defined handle.
[x] @Fuyukai suggested .wait_for_result() which is a lot more
pythonic in terms of plain-ol'-simple-semantics :surfer:
~~maybe .unwind() is more descriptive? as in unwinding the outcome
from the task would imply you both have to:~~
wait for the result or error from the underlying task
retrieve that outcome's value or raise it's error by unwrapping/boxing?
stack unwinding is normally synonymous with the end of
a function call and the subsequent popping of the stack ..?
the nixed above ends up going down the rabbit hole of describing
an imperative lang in terms of lower level fp abstractions which
is not only confusing but a bit moot: we don't need to hear math
about stuff we can't change in (python and) the semantics of
a method..:joy:
[ ] test the waters in trio core for interest in this idea
[x] had a decent discussion on it with the anyio author and njs but
don't think they understood what i was proposing (hence this proto
:joy:)
[ ] the main spot to start digging into how this might be implemented
inside trio's scheduler would be about here:
https://github.com/python-trio/trio/blob/master/trio/_core/_run.py#L1601
since this is where the nursery-global cancel scope's CancelStatus
is activated on the currently spawning task.
obviously it's going to require quite a bit of reworking to try
and offer the generator-style @cancel_scope_manager thing
because we'll need to call __enter__/__exit__ from two
different Runner methods -> .spawn_impl() and .task_exited()
[ ] probably just eventually accept that no-one will comment on this
PR (nor care?) and it'll get relegated to our trionics secret
sauces pantry yet again :joy:
[ ] figure out if it's possible to swap in thisopen_nursery()
for all uses of trio.open_nursery() when our users enable debug mode
:joy:
pretty sure we can do it at appropriate spots during (sub)actor boot?
As per some discussion in the
trio
gitter and starting something toward #22 and supporting our debugger crash mode from within atrio
-compat task nursery.Idea: a
trio.Nursery
API for optionally allowing a user to define a per-task managerBut why?
Well if you wanted any of the following (some of which are implemented in the module script in this patch):
trio.Nursery
"internals" for any per-task oriented purpose.trio
per task control flow.one_for_one
from erlang/elixir and friends.ToDo:
[x] offer a
task_manager
context-manager-as-generator API such that the currentTaskOutcome
struct is not tied to the internals of theScopePerTaskNursery.start_soon()
implementation.outcome: Outcome = yield (cs, ..)
is delivered to the user defined mngrvia asuch that only rawOutcome.send(mngr)
calltrio
(dependency) internal types are provided to the user for wrapping / adjusting.Outcome.send()
bc it would send the underlying value, not the outcome instance; not sure if that's best?[ ] way better naming since most of this was whipped up on the first try and getting good names is probably going to be tricky :joy:
@task_manager
is maybe better?@task_scope_manager
?ScopePerTaskNursery
is terrible.. how aboutTaskScopedNursery
?TaskManagerNursery
?TaskOutcome.unwrap()
seems wrong, despite it being an example of a user defined handle..wait_for_result()
which is a lot more pythonic in terms of plain-ol'-simple-semantics :surfer:.unwind()
is more descriptive? as in unwinding the outcome from the task would imply you both have to:~~[ ] test the waters in
trio
core for interest in this ideaanyio
author and njs but don't think they understood what i was proposing (hence this proto :joy:)trio
's scheduler would be about here: https://github.com/python-trio/trio/blob/master/trio/_core/_run.py#L1601 since this is where the nursery-global cancel scope'sCancelStatus
is activated on the currently spawning task.@cancel_scope_manager
thing because we'll need to call__enter__
/__exit__
from two differentRunner
methods ->.spawn_impl()
and.task_exited()
trionics
secret sauces pantry yet again :joy:[ ] figure out if it's possible to swap in this
open_nursery()
for all uses oftrio.open_nursery()
when our users enable debug mode :joy:Hopefully much more to come!