Rework landing example onto the `Context` API
`run_in_actor()` is slated to become a hilevel wrapper (`runtime/_supervise.py` "TODO: DEPRECATE THIS"), so the showcase `we_are_processes.py` shouldn't lead with it. Move it to the modern API: each `worker_<i>` subactor runs a `@tractor.context` `endpoint()` that `started()`-hands its name + pid back over `Portal.open_context()` and parks; the root sleeps then raises on purpose so the runtime reaps the whole tree (zero zombies). The subs spawn concurrently from bg `trio.Task`s so each child's cold `import tractor` (~0.4s, see #470) overlaps instead of stacking; a comment flags the coming `main_thread_forkserver` backend (#463) which'll make serial spawns cheap enough to just loop. Match the landing prose to the snippet — name the `Context` + `started()` handshake it now leads with. Also, document `--watch examples` on the `sphinx-autobuild` cmds so edits to `literalinclude`-d example scripts (which live outside `docs/`) live-reload too. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
parent
f406a2d357
commit
b16173482b
|
|
@ -24,8 +24,10 @@ Sixty seconds of why
|
||||||
you can read a ``trio`` program you can read a
|
you can read a ``trio`` program you can read a
|
||||||
``tractor`` one — that's the whole pitch.
|
``tractor`` one — that's the whole pitch.
|
||||||
|
|
||||||
Spawn one actor per core, crash the root on purpose,
|
Spawn one actor per core, open a ``Context`` into
|
||||||
and watch the runtime contain the blast: errors
|
each — the child ``started()``-handshakes its name
|
||||||
|
and pid back — then crash the root on purpose and
|
||||||
|
watch the runtime contain the blast: errors
|
||||||
propagate, *every* child is reaped, zero zombies —
|
propagate, *every* child is reaped, zero zombies —
|
||||||
guaranteed (it's a bug otherwise).
|
guaranteed (it's a bug otherwise).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
"""
|
'''
|
||||||
Run with a process monitor from a terminal using::
|
Run with a process monitor from a terminal using::
|
||||||
|
|
||||||
$TERM -e watch -n 0.1 "pstree -a $$" \
|
$TERM -e watch -n 0.1 "pstree -a $$" \
|
||||||
& python examples/parallelism/we_are_processes.py \
|
& python examples/parallelism/we_are_processes.py \
|
||||||
&& kill $!
|
&& kill $!
|
||||||
|
|
||||||
"""
|
'''
|
||||||
from multiprocessing import cpu_count
|
from multiprocessing import cpu_count
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
@ -13,26 +13,70 @@ import tractor
|
||||||
import trio
|
import trio
|
||||||
|
|
||||||
|
|
||||||
async def target():
|
@tractor.context
|
||||||
print(
|
async def endpoint(
|
||||||
f"Yo, i'm '{tractor.current_actor().name}' "
|
ctx: tractor.Context,
|
||||||
f"running in pid {os.getpid()}"
|
):
|
||||||
)
|
actor_name: str = tractor.current_actor().name
|
||||||
|
pid: int = os.getpid()
|
||||||
|
await ctx.started((actor_name, pid))
|
||||||
await trio.sleep_forever()
|
await trio.sleep_forever()
|
||||||
|
|
||||||
|
|
||||||
|
async def spawn_and_open_ep(
|
||||||
|
an: tractor.ActorNursery,
|
||||||
|
i: int,
|
||||||
|
) -> None:
|
||||||
|
'''
|
||||||
|
Spawn a subactor, start a remote `endpoint()`-task in it.
|
||||||
|
|
||||||
|
'''
|
||||||
|
ptl: tractor.Portal = await an.start_actor(
|
||||||
|
name=f'worker_{i}',
|
||||||
|
enable_modules=[__name__],
|
||||||
|
)
|
||||||
|
ctx: tractor.Context
|
||||||
|
async with ptl.open_context(endpoint) as (
|
||||||
|
ctx,
|
||||||
|
(sub_name, sub_pid),
|
||||||
|
):
|
||||||
|
print(
|
||||||
|
f'Started ep-task in subactor,\n'
|
||||||
|
f'{i}::{sub_name!r}@{sub_pid}\n'
|
||||||
|
)
|
||||||
|
await ctx.wait_for_result()
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
|
'''
|
||||||
|
Spawn a subactor-per-CPU then self-destruct the cluster.
|
||||||
|
|
||||||
async with tractor.open_nursery() as n:
|
'''
|
||||||
|
tn: trio.Nursery
|
||||||
|
an: tractor.ActorNursery
|
||||||
|
async with (
|
||||||
|
tractor.open_nursery(
|
||||||
|
# XXX coming soon!
|
||||||
|
# https://github.com/goodboy/tractor/pull/463
|
||||||
|
# start_method='main_thread_forkserver',
|
||||||
|
) as an,
|
||||||
|
# spawn subs concurrently (in bg `trio.Task`s) so each
|
||||||
|
# actor's cold `import tractor` (~0.4s, see #470) overlaps
|
||||||
|
# instead of stacking; once forkserver (#463) lands, spawn
|
||||||
|
# is cheap enough to just loop sequentially.
|
||||||
|
trio.open_nursery() as tn,
|
||||||
|
):
|
||||||
for i in range(cpu_count()):
|
for i in range(cpu_count()):
|
||||||
await n.run_in_actor(target, name=f'worker_{i}')
|
tn.start_soon(
|
||||||
|
spawn_and_open_ep,
|
||||||
print('This process tree will self-destruct in 1 sec...')
|
an,
|
||||||
await trio.sleep(1)
|
i,
|
||||||
|
)
|
||||||
# you could have done this yourself
|
destruct_in: int = 2
|
||||||
|
print(
|
||||||
|
f'This tree will self-destruct in {destruct_in}s..\n'
|
||||||
|
)
|
||||||
|
await trio.sleep(destruct_in)
|
||||||
raise Exception('Self Destructed')
|
raise Exception('Self Destructed')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,15 @@ Rebuilds + refreshes the browser on every save:
|
||||||
|
|
||||||
```
|
```
|
||||||
nix develop .#docs -c uv run --with sphinx-autobuild \
|
nix develop .#docs -c uv run --with sphinx-autobuild \
|
||||||
--group docs sphinx-autobuild docs docs/_build/html
|
--group docs sphinx-autobuild docs docs/_build/html \
|
||||||
|
--watch examples
|
||||||
# then open http://127.0.0.1:8000
|
# then open http://127.0.0.1:8000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `--watch examples` is what makes edits to ``literalinclude``-d
|
||||||
|
example scripts live-reload too: those files live *outside* `docs/`,
|
||||||
|
so autobuild won't notice them changing without it.
|
||||||
|
|
||||||
## Share it on your LAN
|
## Share it on your LAN
|
||||||
|
|
||||||
To let someone on your subnet view the docs, bind the server to
|
To let someone on your subnet view the docs, bind the server to
|
||||||
|
|
@ -52,7 +57,8 @@ Live-reload, LAN-visible:
|
||||||
|
|
||||||
```
|
```
|
||||||
nix develop .#docs -c uv run --with sphinx-autobuild --group docs \
|
nix develop .#docs -c uv run --with sphinx-autobuild --group docs \
|
||||||
sphinx-autobuild docs docs/_build/html --host 0.0.0.0 --port 8000
|
sphinx-autobuild docs docs/_build/html --host 0.0.0.0 --port 8000 \
|
||||||
|
--watch examples
|
||||||
```
|
```
|
||||||
|
|
||||||
Or just statically serve an already-built `docs/_build/html` (no
|
Or just statically serve an already-built `docs/_build/html` (no
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue