Port service+tests to latest `tractor` APIs

Continue the `repair_tests`-branch mission (already merged
in this stack's ancestry, see f4c4f1e2 which ported
`conftest.py`) by fixing the remaining drift breakage vs.
`tractor` git `main`; without these NOTHING boots since the
`tractor.Address` port in 604e5fcf.

Deats,
- normalize reg addrs via `wrap_address()` in
  `open_pikerd()` before `.unwrap()`-ing; entries may be
  raw `tuple`s when passed in from (test) client code.
- port `check_for_service()` to `query_actor(regaddr=)`
  (was `arbiter_sockaddr=`) incl. its 2-tuple yield and
  the now-required `open_registry(addrs=)` arg.
- `wait_for_actor(registry_addr=)` + `.chan.raddr.unwrap()`
  raw-tuple compares in `test_runtime_boot` and
  `ensure_service()`.
- update `run_test_w_cancel_method()` for modern `tractor`
  cancel semantics: self-requested sub-service cancels are
  absorbed (no `ContextCancelled` raised to the opener) and
  single-exc groups collapse to a bare KBI.
- `RemoteActorError.boxed_type` (was `.type`) and
  `Position.cumsize` (was `.size`) renames in tests.
- bump the paper-EMS startup budget 9 -> 19s; it includes
  a live (kraken) symbology fetch so needs net headroom.
- woops, add the missing comma in `.deribit.api`'s
  `tractor.trionics` import tuple..

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Gud Boi 2026-06-09 17:20:45 -04:00
parent 75cefe10f1
commit fa98290808
5 changed files with 59 additions and 38 deletions

View File

@ -37,7 +37,7 @@ from rapidfuzz import process as fuzzy
import numpy as np
from tractor.trionics import (
broadcast_receiver,
maybe_open_context
maybe_open_context,
collapse_eg,
)
from tractor import to_asyncio

View File

@ -214,7 +214,13 @@ async def open_pikerd(
trio.open_nursery() as service_tn,
):
for addr in reg_addrs:
uaddr: tuple = addr.unwrap()
# normalize to a wrapped `tractor` addr-type;
# entries may be raw `tuple`s when passed in
# from (test) client code.
wladdr = tractor.discovery._addr.wrap_address(
addr,
)
uaddr: tuple = wladdr.unwrap()
if (
uaddr not in root_actor.accept_addrs
):

View File

@ -225,10 +225,13 @@ async def check_for_service(
'''
async with (
open_registry(ensure_exists=False) as reg_addr,
open_registry(
addrs=Registry.addrs,
ensure_exists=False,
) as reg_addrs,
tractor.query_actor(
service_name,
arbiter_sockaddr=reg_addr,
) as sockaddr,
regaddr=reg_addrs[0],
) as (sockaddr, _),
):
return sockaddr

View File

@ -151,7 +151,7 @@ def load_and_check_pos(
# is the same the fqme.
pp: Position = table.pps[ppmsg.symbol]
assert ppmsg.size == pp.size
assert ppmsg.size == pp.cumsize
assert ppmsg.avg_price == pp.ppu
yield pp
@ -179,7 +179,7 @@ def test_ems_err_on_bad_broker(
# NOTE: emsd should error on the actor's enabled modules
# import phase, when looking for a backend named `doggy`.
except tractor.RemoteActorError as re:
assert re.type is ModuleNotFoundError
assert re.boxed_type is ModuleNotFoundError
run_and_tollerate_cancels(load_bad_fqme)

View File

@ -53,11 +53,12 @@ def test_runtime_boot(
tractor.wait_for_actor(
'pikerd',
arbiter_sockaddr=daemon_addr,
registry_addr=daemon_addr,
) as portal,
):
assert pikerd_portal.channel.raddr == daemon_addr
assert pikerd_portal.channel.raddr == portal.channel.raddr
uw_raddr: tuple = pikerd_portal.chan.raddr.unwrap()
assert uw_raddr == daemon_addr
assert uw_raddr == portal.chan.raddr.unwrap()
# no service tasks should be started
assert not services.service_tasks
@ -108,7 +109,7 @@ async def ensure_service(
sockaddr: tuple[str, int] | None = None,
) -> None:
async with find_service(name) as portal:
remote_sockaddr = portal.channel.raddr
remote_sockaddr: tuple = portal.chan.raddr.unwrap()
print(f'FOUND `{name}` @ {remote_sockaddr}')
if sockaddr:
@ -131,41 +132,50 @@ def run_test_w_cancel_method(
"was remotely cancelled by remote actor (\'pikerd\'")
if cancel_method == 'sigint':
with pytest.raises(
# XXX: with modern `tractor` the (single-exc)
# group is collapsed so a bare KBI normally
# propagates; tolerate either form.
with pytest.raises((
KeyboardInterrupt,
BaseExceptionGroup,
) as exc_info:
)) as exc_info:
trio.run(main)
multi = exc_info.value
for suberr in multi.exceptions:
err = exc_info.value
match err:
case BaseExceptionGroup():
for suberr in err.exceptions:
match suberr:
# ensure we receive a remote cancellation error caused
# by the pikerd root actor since we used the
# `.cancel_service()` API above B)
# ensure we receive a remote
# cancellation error caused by the
# pikerd root actor.
case tractor.ContextCancelled():
assert cancelled_msg in suberr.args[0]
assert (
cancelled_msg
in
suberr.args[0]
)
case KeyboardInterrupt():
pass
case _:
pytest.fail(f'Unexpected error {suberr}')
pytest.fail(
f'Unexpected error {suberr}'
)
case KeyboardInterrupt():
pass
elif cancel_method == 'services':
# XXX NOTE: oddly, when you pass --pdb to pytest, i think since
# we also use that to enable the underlying tractor debug mode,
# it causes this to not raise for some reason? So if you see
# that while changing this test.. it's prolly that.
with pytest.raises(
tractor.ContextCancelled
) as exc_info:
# XXX: cancelling our own sub-service via
# `Services.cancel_service()` is a *self*
# requested cancel: modern `tractor` absorbs the
# resulting `ContextCancelled` (canceller is our
# own actor) so the runtime tears down gracefully
# with NO error raised to the opener.
trio.run(main)
assert cancelled_msg in exc_info.value.args[0]
else:
pytest.fail(f'Test is broken due to {cancel_method}')
@ -197,7 +207,9 @@ def test_ensure_ems_in_paper_actors(
# ensure we timeout after is startup is too slow.
# TODO: something like this should be our start point for
# benchmarking end-to-end startup B)
with trio.fail_after(9):
# NOTE: includes a live (kraken) symbology fetch so
# the budget needs some headroom for net latency..
with trio.fail_after(19):
async with (
open_test_pikerd() as (_, _, _, services),