diff --git a/piker/brokers/deribit/api.py b/piker/brokers/deribit/api.py index eb70bfa0..85d490be 100644 --- a/piker/brokers/deribit/api.py +++ b/piker/brokers/deribit/api.py @@ -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 diff --git a/piker/service/_actor_runtime.py b/piker/service/_actor_runtime.py index 5bb67c5b..b0f180e4 100644 --- a/piker/service/_actor_runtime.py +++ b/piker/service/_actor_runtime.py @@ -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 ): diff --git a/piker/service/_registry.py b/piker/service/_registry.py index e24539e2..2d787d7c 100644 --- a/piker/service/_registry.py +++ b/piker/service/_registry.py @@ -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 diff --git a/tests/test_ems.py b/tests/test_ems.py index 07e28c33..a6adbbf8 100644 --- a/tests/test_ems.py +++ b/tests/test_ems.py @@ -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) diff --git a/tests/test_services.py b/tests/test_services.py index 433e97f3..69771c09 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -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,40 +132,49 @@ 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 + 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. + case tractor.ContextCancelled(): + assert ( + cancelled_msg + in + suberr.args[0] + ) - for suberr in multi.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) - case tractor.ContextCancelled(): - assert cancelled_msg in suberr.args[0] + case KeyboardInterrupt(): + pass - case KeyboardInterrupt(): - pass + case _: + pytest.fail( + f'Unexpected error {suberr}' + ) - case _: - 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: - trio.run(main) - - assert cancelled_msg in exc_info.value.args[0] + # 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) 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),