tractor/examples/multihost/tipc_cluster/single_host.py

105 lines
2.4 KiB
Python
Raw Normal View History

'''
`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)