71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
'''
|
|
Demonstrate the "service daemon" pattern: a named,
|
|
long-lived actor spawned via `ActorNursery.start_actor()`
|
|
which any other task can locate through the registrar using
|
|
`tractor.find_actor()` / `tractor.wait_for_actor()` - no
|
|
spawn-portal required - and RPC into directly.
|
|
|
|
Teardown is explicit and graceful via `portal.cancel_actor()`
|
|
once the clients are done.
|
|
|
|
'''
|
|
import trio
|
|
import tractor
|
|
|
|
_quotes: dict[str, float] = {
|
|
'btcusdt': 66_000.5,
|
|
'ethusdt': 3_500.25,
|
|
}
|
|
|
|
|
|
async def get_quote(sym: str) -> float:
|
|
'''
|
|
Look up the "current" quote for a symbol.
|
|
|
|
'''
|
|
name: str = tractor.current_actor().name
|
|
print(f'{name}: serving quote for {sym!r}')
|
|
return _quotes[sym]
|
|
|
|
|
|
async def client_task() -> None:
|
|
'''
|
|
Locate the quote service by name and RPC it; note no
|
|
spawn-nursery/portal reference is ever passed in here!
|
|
|
|
'''
|
|
# a lookup miss yields `None` (not an error).
|
|
async with tractor.find_actor('no_such_svc') as portal:
|
|
assert portal is None
|
|
print('client: "no_such_svc" is not registered')
|
|
# block until the service shows up in the registry,
|
|
# then call into it through the delivered portal.
|
|
async with tractor.wait_for_actor('quote_svc') as portal:
|
|
quote: float = await portal.run(
|
|
get_quote,
|
|
sym='btcusdt',
|
|
)
|
|
print(f'client: got btcusdt quote {quote}')
|
|
|
|
|
|
async def main() -> None:
|
|
an: tractor.ActorNursery
|
|
async with tractor.open_nursery() as an:
|
|
portal: tractor.Portal = await an.start_actor(
|
|
'quote_svc',
|
|
enable_modules=[__name__],
|
|
)
|
|
# run the client in a separate task which discovers
|
|
# the daemon purely by its registered name.
|
|
tn: trio.Nursery
|
|
async with trio.open_nursery() as tn:
|
|
tn.start_soon(client_task)
|
|
# explicit graceful teardown of the daemon.
|
|
print('root: cancelling quote_svc')
|
|
await portal.cancel_actor()
|
|
print('root: service shut down cleanly')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
trio.run(main)
|