tractor/tests
Tyler Goodlet c5985169cc Init def of "SC shuttle prot" with "msg-spec-limiting"
As per the long outstanding GH issue this starts our rigorous journey
into an attempt at a type-safe, cross-actor SC, IPC protocol Bo

boop -> https://github.com/goodboy/tractor/issues/36

The idea is to "formally" define our SC "shuttle (dialog) protocol" by
specifying a new `.msg.types.Msg` subtype-set which can fully
encapsulate all IPC msg schemas needed in order to accomplish
cross-process SC!

The msg set deviated a little in terms of (type) names from the existing
`dict`-msgs currently used in the runtime impl but, I think the name
changes are much better in terms of explicitly representing the internal
semantics of the actor runtime machinery/subsystems and the
IPC-msg-dialog required for SC enforced RPC.

------ - ------

In cursory, the new formal msgs-spec includes the following msg-subtypes
of a new top-level `Msg` boxing type (that holds the base field schema
for all msgs):

- `Start` to request RPC task scheduling by passing a `FuncSpec` payload
  (to replace the currently used `{'cmd': ... }` dict msg impl)

- `StartAck` to allow the RPC task callee-side to report a `IpcCtxSpec`
  payload immediately back to the caller (currently responded naively via
  a `{'functype': ... }` msg)

- `Started` to deliver the first value from `Context.started()`
  (instead of the existing `{'started': ... }`)

- `Yield` to shuttle `MsgStream.send()`-ed values (instead of
  our `{'yield': ... }`)

- `Stop` to terminate a `Context.open_stream()` session/block
  (over `{'stop': True }`)

- `Return` to deliver the final value from the `Actor.start_remote_task()`
  (which is a `{'return': ... }`)

- `Error` to box `RemoteActorError` exceptions via a `.pld: ErrorData`
  payload, planned to replace/extend the current `RemoteActorError.msgdata`
  mechanism internal to `._exceptions.pack/unpack_error()`

The new `tractor.msg.types` includes all the above msg defs as well an API
for rendering a "payload type specification" using a
`payload_type_spec: Union[Type]` that can be passed to
`msgspec.msgpack.Decoder(type=payload_type_spec)`. This ensures that
(for a subset of the above msg set) `Msg.pld: PayloadT` data is
type-parameterized using `msgspec`'s new `Generic[PayloadT]` field
support and thus enables providing for an API where IPC `Context`
dialogs can strictly define the allowed payload-datatype-set via type
union!

Iow, this is the foundation for supporting `Channel`/`Context`/`MsgStream`
IPC primitives which are type checked/safe as desired in GH issue:
- https://github.com/goodboy/tractor/issues/365

Misc notes on current impl(s) status:
------ - ------
- add a `.msg.types.mk_msg_spec()` which uses the new `msgspec` support
  for `class MyStruct[Struct, Generic[T]]` parameterize-able fields and
  delivers our boxing SC-msg-(sub)set with the desired `payload_types`
  applied to `.pld`:
  - https://jcristharif.com/msgspec/supported-types.html#generic-types
  - as a note this impl seems to need to use `type.new_class()` dynamic
    subtype generation, though i don't really get *why* still.. but
    without that the `msgspec.msgpack.Decoder` doesn't seem to reject
    `.pld` limited `Msg` subtypes as demonstrated in the new test.

- around this ^ add a `.msg._codec.limit_msg_spec()` cm which exposes
  this payload type limiting API such that it can be applied per task
  via a `MsgCodec` in app code.

- the orig approach in https://github.com/goodboy/tractor/pull/311 was
  the idea of making payload fields `.pld: Raw` wherein we could have
  per-field/sub-msg decoders dynamically loaded depending on the
  particular application-layer schema in use. I don't want to lose the
  idea of this since I think it might be useful for an idea I have about
  capability-based-fields(-sharing, maybe using field-subset
  encryption?), and as such i've kept the (ostensibly) working impls in
  TODO-comments in `.msg._codec` wherein maybe we can add
  a `MsgCodec._payload_decs: dict` table for this later on.
  |_ also left in the `.msg.types.enc/decmsg()` impls but renamed as
    `enc/dec_payload()` (but reworked to not rely on the lifo codec
    stack tables; now removed) such that we can prolly move them to
    `MsgCodec` methods in the future.

- add an unused `._codec.mk_tagged_union_dec()` helper which was
  originally factored out the #311 proto-code but didn't end up working
  as desired with the new parameterized generic fields approach (now
  in `msg.types.mk_msg_spec()`)

Testing/deps work:
------ - ------
- new `test_limit_msgspec()` which ensures all the `.types` content is
  correct but without using the wrapping APIs in `._codec`; i.e. using
  a in-line `Decoder` instead of a `MsgCodec`.

- pin us to `msgspec>=0.18.5` which has the needed generic-types support
  (which took me way too long yester to figure out when implementing all
  this XD)!
2025-03-24 14:04:49 -04:00
..
__init__.py Add `tests/__init__.py` for `.conftest` imports 2025-03-20 20:53:54 -04:00
conftest.py Rename fixture `arb_addr` -> `reg_addr` and set the session value globally as `._root._default_lo_addrs` 2025-03-20 19:50:31 -04:00
test_2way.py Move context-streaming operational tests into one mod 2021-12-06 16:45:44 -05:00
test_advanced_faults.py Add missing `consider_namespace_packages=False,` to `import_path()` 2025-03-20 20:58:56 -04:00
test_advanced_streaming.py Tweak some tests for spurious failues 2025-03-16 15:22:01 -04:00
test_cancellation.py Add `tests/__init__.py` for `.conftest` imports 2025-03-20 20:53:54 -04:00
test_caps_msging.py Init def of "SC shuttle prot" with "msg-spec-limiting" 2025-03-24 14:04:49 -04:00
test_child_manages_service_nursery.py Adjust all `RemoteActorError.type` using tests 2025-03-20 20:35:02 -04:00
test_clustering.py Add (back) a `tractor._testing` sub-pkg 2025-03-16 15:28:28 -04:00
test_context_stream_semantics.py Adjust all `RemoteActorError.type` using tests 2025-03-20 20:35:02 -04:00
test_debugger.py Refine and test `tractor.pause_from_sync()` 2025-03-20 22:37:51 -04:00
test_discovery.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_docs_examples.py Get remaining suites passing.. 2025-03-20 20:35:02 -04:00
test_infected_asyncio.py Provision for infected-`asyncio` debug mode support 2025-03-20 22:37:51 -04:00
test_inter_peer_cancellation.py Extend inter-peer cancel tests for "inceptions" 2025-03-20 20:35:02 -04:00
test_legacy_one_way_streaming.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_local.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_multi_program.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_pubsub.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_resource_cache.py Bump timeout on resource cache test a bitty bit. 2025-03-14 14:14:53 -04:00
test_rpc.py Adjust all `RemoteActorError.type` using tests 2025-03-20 20:35:02 -04:00
test_runtime.py Drop now-deprecated deps on modern `trio`/Python 2025-03-16 16:06:24 -04:00
test_spawning.py Get remaining suites passing.. 2025-03-20 20:35:02 -04:00
test_task_broadcasting.py Reapply "Port all tests to new `reg_addr` fixture name" 2025-03-20 19:50:31 -04:00
test_trioisms.py Drop now-deprecated deps on modern `trio`/Python 2025-03-16 16:06:24 -04:00