105 lines
2.4 KiB
Python
105 lines
2.4 KiB
Python
|
|
'''
|
||
|
|
`tractor` over `AF_TIPC` on a single host.
|
||
|
|
|
||
|
|
Every actor's IPC address is a TIPC *service name*, and binding
|
||
|
|
one publishes it into the kernel's cluster-wide name table. So
|
||
|
|
`tipc nametable show` lists your live actor tree — no registrar
|
||
|
|
query, no `tractor` API, just the kernel telling you what's up.
|
||
|
|
|
||
|
|
Run,
|
||
|
|
|
||
|
|
sudo modprobe tipc
|
||
|
|
python single_host.py
|
||
|
|
|
||
|
|
'''
|
||
|
|
from __future__ import annotations
|
||
|
|
import subprocess
|
||
|
|
|
||
|
|
import trio
|
||
|
|
import tractor
|
||
|
|
from tractor.ipc._tipc import (
|
||
|
|
TRACTOR_STYPE,
|
||
|
|
is_tipc_available,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def show_nametable(tag: str) -> None:
|
||
|
|
'''
|
||
|
|
Dump the kernel name-table rows belonging to `tractor`.
|
||
|
|
|
||
|
|
'''
|
||
|
|
print(f'\n--- `tipc nametable show` :: {tag} ---')
|
||
|
|
out = subprocess.run(
|
||
|
|
['tipc', 'nametable', 'show'],
|
||
|
|
capture_output=True,
|
||
|
|
text=True,
|
||
|
|
)
|
||
|
|
for line in out.stdout.splitlines():
|
||
|
|
# header, or one of *our* service-type rows
|
||
|
|
if (
|
||
|
|
line.startswith('Type')
|
||
|
|
or
|
||
|
|
line.startswith(str(TRACTOR_STYPE))
|
||
|
|
):
|
||
|
|
print(f' {line}')
|
||
|
|
|
||
|
|
|
||
|
|
@tractor.context
|
||
|
|
async def wait_until_cancelled(
|
||
|
|
ctx: tractor.Context,
|
||
|
|
) -> None:
|
||
|
|
await ctx.started()
|
||
|
|
await trio.sleep_forever()
|
||
|
|
|
||
|
|
|
||
|
|
async def main() -> None:
|
||
|
|
async with tractor.open_nursery(
|
||
|
|
enable_transports=['tipc'],
|
||
|
|
) as an:
|
||
|
|
|
||
|
|
show_nametable('root only')
|
||
|
|
|
||
|
|
portals: list[tractor.Portal] = []
|
||
|
|
for name in ('donny', 'walter', 'dude'):
|
||
|
|
portals.append(
|
||
|
|
await an.start_actor(
|
||
|
|
name,
|
||
|
|
enable_modules=[__name__],
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
async with trio.open_nursery() as tn:
|
||
|
|
for ptl in portals:
|
||
|
|
tn.start_soon(
|
||
|
|
_hold_open,
|
||
|
|
ptl,
|
||
|
|
)
|
||
|
|
await trio.sleep(0.5)
|
||
|
|
|
||
|
|
# XXX the money shot: 4 actors, 4 published names
|
||
|
|
show_nametable('root + 3 subactors')
|
||
|
|
|
||
|
|
tn.cancel_scope.cancel()
|
||
|
|
|
||
|
|
await an.cancel()
|
||
|
|
|
||
|
|
show_nametable('after teardown (all withdrawn)')
|
||
|
|
|
||
|
|
|
||
|
|
async def _hold_open(
|
||
|
|
ptl: tractor.Portal,
|
||
|
|
) -> None:
|
||
|
|
async with ptl.open_context(
|
||
|
|
wait_until_cancelled,
|
||
|
|
) as (ctx, _):
|
||
|
|
await trio.sleep_forever()
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
if not is_tipc_available():
|
||
|
|
raise RuntimeError(
|
||
|
|
'The `tipc` kernel module is not loaded!\n'
|
||
|
|
' |_try: `sudo modprobe tipc`\n'
|
||
|
|
)
|
||
|
|
trio.run(main)
|