Port service+tests to latest `tractor` APIs
Continue the `repair_tests`-branch mission (already merged in this stack's ancestry, seedatad_servicef4c4f1e2which ported `conftest.py`) by fixing the remaining drift breakage vs. `tractor` git `main`; without these NOTHING boots since the `tractor.Address` port in604e5fcf. 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> Prompt-IO: ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
parent
4485f2b9ce
commit
bc6e18d7b4
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
model: claude-fable-5[1m]
|
||||
service: claude
|
||||
session: 32d15f9a-b2d3-4c26-bdc9-190219141a25
|
||||
timestamp: 2026-06-10T17:10:22Z
|
||||
git_ref: datad_service
|
||||
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
|
||||
scope: code
|
||||
substantive: true
|
||||
raw_file: 20260610T171022Z_4485f2b9_prompt_io.raw.md
|
||||
---
|
||||
|
||||
## Prompt
|
||||
|
||||
Same session-initiating `brokerd`-split instruction (see
|
||||
`20260610T170859Z_75cefe10_prompt_io.md`). Proximate
|
||||
driver: the approved plan's per-stage test gates could
|
||||
not run AT ALL — the branch base was broken vs.
|
||||
`tractor` git `main` (`AttributeError: 'tuple' object
|
||||
has no attribute 'unwrap'` at `pikerd` boot, stale
|
||||
`arbiter_sockaddr`/`.type`/`.size` API refs). The agent
|
||||
fixed forward autonomously to (re)establish the gate
|
||||
baseline, continuing the `repair_tests` branch lineage
|
||||
(verified already merged in ancestry via `git cherry`
|
||||
during a user-requested branch-overlap survey).
|
||||
|
||||
## Response summary
|
||||
|
||||
Port the service layer + test suites to current
|
||||
`tractor` APIs: addr-type normalization in
|
||||
`open_pikerd()`, `query_actor()`/`wait_for_actor()`
|
||||
kwarg renames, modern self-cancel absorption semantics
|
||||
in the cancel-method test harness, exc/position attr
|
||||
renames, a paper-EMS startup-budget bump and a syntax
|
||||
fix in `.deribit.api`.
|
||||
|
||||
## Files changed
|
||||
|
||||
- `piker/service/_actor_runtime.py` — `wrap_address()`
|
||||
normalize before `.unwrap()` in `open_pikerd()`
|
||||
- `piker/service/_registry.py` — `check_for_service()`
|
||||
-> `query_actor(regaddr=)` + 2-tuple yield +
|
||||
`open_registry(addrs=)`
|
||||
- `piker/brokers/deribit/api.py` — missing comma in
|
||||
`tractor.trionics` import tuple
|
||||
- `tests/test_services.py` — `registry_addr=` kwarg,
|
||||
raddr unwraps, cancel-semantics harness rewrite,
|
||||
`fail_after` 9 -> 19s
|
||||
- `tests/test_ems.py` — `.boxed_type`, `pp.cumsize`
|
||||
|
||||
## Human edits
|
||||
|
||||
None — committed as generated.
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
model: claude-fable-5[1m]
|
||||
service: claude
|
||||
timestamp: 2026-06-10T17:10:22Z
|
||||
git_ref: datad_service
|
||||
diff_cmd: git log -1 -p --follow -- ai/prompt-io/claude/20260610T171022Z_4485f2b9_prompt_io.md
|
||||
---
|
||||
|
||||
NOTE: diff-ref mode entry (code committed in the same
|
||||
commit as this log); backfilled from the live dev
|
||||
session transcript per the `/prompt-io` skill rules.
|
||||
|
||||
> `git log -1 -p --follow -- piker/service/_actor_runtime.py`
|
||||
|
||||
Generated: normalize each registry addr via
|
||||
`tractor.discovery._addr.wrap_address()` before
|
||||
`.unwrap()`-ing for the `accept_addrs` bind check —
|
||||
entries may be raw `tuple`s when passed in from (test)
|
||||
client code. Import-path precedent taken from
|
||||
`piker/cli/__init__.py:336`.
|
||||
|
||||
> `git log -1 -p --follow -- piker/service/_registry.py`
|
||||
|
||||
Generated: `check_for_service()` ported to
|
||||
`tractor.query_actor(name, regaddr=...)` (kwarg was
|
||||
`arbiter_sockaddr=`), unpacking the new
|
||||
`(sockaddr, portal)` yield, and passing the
|
||||
now-required `open_registry(addrs=Registry.addrs)`.
|
||||
|
||||
> `git log -1 -p --follow -- tests/test_services.py`
|
||||
> `git log -1 -p --follow -- tests/test_ems.py`
|
||||
> `git log -1 -p --follow -- piker/brokers/deribit/api.py`
|
||||
|
||||
Key diagnostic reasoning (verbatim from session):
|
||||
|
||||
- the "DID NOT RAISE ContextCancelled" failure: in this
|
||||
test the client actor IS pikerd (in-proc), and
|
||||
current `tractor` main absorbs a `ContextCancelled`
|
||||
whose canceller is your own actor — self-requested
|
||||
cancels now exit cleanly instead of raising; the
|
||||
'sigint' variant propagates a bare collapsed
|
||||
`KeyboardInterrupt` rather than a
|
||||
`BaseExceptionGroup`.
|
||||
- the hard-coded `trio.fail_after(9)` startup budget is
|
||||
marginal — full stack boot (pikerd -> emsd ->
|
||||
brokerd.kraken -> paperboi + live kraken symbology
|
||||
fetch) occasionally exceeds 9s -> bumped to 19s.
|
||||
- `RemoteActorError.type` -> `.boxed_type`;
|
||||
`Position.size` -> `.cumsize` (the paper engine
|
||||
populates `BrokerdPosition.size` from `pp.cumsize`).
|
||||
- overlap survey (user-requested): all of the
|
||||
`repair_tests` branch commits are already in this
|
||||
stack's ancestry; this commit finishes that branch's
|
||||
port mission (its f4c4f1e2 fixed `conftest.py`'s
|
||||
`arbiter_sockaddr` usage; this fixes the remaining
|
||||
`test_services.py` + `check_for_service()` sites).
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue