Correct typed-msg validation docs
Document `Started` as the eager sender-side payload check and `Yield` plus `Return` as receiver-side decoding boundaries without promising a symmetric error relay. Separate the working task-scoped codec encoder from the private per-dialog decoder and the incomplete `@context` hook params. Link the planned typed `Start` contract and sender-side argument validation follow-up in #514. (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))wkt/big_boi_docs_472_follow_ups
parent
38883dca03
commit
a40fb2ebde
|
|
@ -153,14 +153,16 @@ the high-rate stream path.
|
||||||
never even hits the wire. (You can opt out per-call with
|
never even hits the wire. (You can opt out per-call with
|
||||||
``ctx.started(..., validate_pld_spec=False)`` if you measure
|
``ctx.started(..., validate_pld_spec=False)`` if you measure
|
||||||
a real cost.)
|
a real cost.)
|
||||||
- ``Yield`` payloads are **never** checked inside
|
- ``Yield`` and ``Return`` payloads are not checked before sending;
|
||||||
``MsgStream.send()``; they're validated receiver-side on each
|
they're decoded against the dialog's spec by the receiver. A
|
||||||
``MsgStream.receive()``. A violation raises a ``MsgTypeError``
|
violation raises a ``MsgTypeError`` there and terminates that
|
||||||
in the receiver *and* relays an ``Error`` msg back so the
|
dialog. The peer then observes the resulting protocol teardown;
|
||||||
offending sender gets one raised too.
|
it is not guaranteed to receive the same ``MsgTypeError``.
|
||||||
- the remaining control msgs (``Start``, ``Return``) are likewise
|
- ``Start`` arguments are dispatched through the RPC endpoint's
|
||||||
validated such that violations raise in the **sending** actor,
|
Python signature. They are not payloads covered by the dialog's
|
||||||
pointing the traceback at the code that actually goofed.
|
``pld_spec``. A planned follow-up will derive a typed ``Start``
|
||||||
|
contract from endpoint annotations and validate arguments
|
||||||
|
sender-side; see `#514`_.
|
||||||
|
|
||||||
Anatomy of a ``MsgTypeError``
|
Anatomy of a ``MsgTypeError``
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
@ -177,21 +179,21 @@ a msg fails to decode against the active spec. The useful bits:
|
||||||
``.src_uid``, ``.ipc_msg`` and the fancy ``.pformat()`` tb-box
|
``.src_uid``, ``.ipc_msg`` and the fancy ``.pformat()`` tb-box
|
||||||
rendering.
|
rendering.
|
||||||
|
|
||||||
Practical reading guide: a *sender-side* MTE (``Started``,
|
Practical reading guide: a *sender-side* MTE for ``Started`` points
|
||||||
``Return``) points straight at your offending ``await
|
straight at the offending ``await ctx.started()`` call. A
|
||||||
ctx.started()`` or ``return`` statement, while a *receiver-side*
|
*receiver-side* MTE for ``Yield`` or ``Return`` surfaces while the
|
||||||
MTE (``Yield``) surfaces from the consumer's ``receive()`` call
|
peer decodes the payload. Either way the failure is scoped to that
|
||||||
with the relay copy delivered back to the producer. Either way
|
one dialog; sibling contexts on the same channel keep right on
|
||||||
the failure is scoped to that one dialog; sibling contexts on the
|
trucking.
|
||||||
same channel keep right on trucking.
|
|
||||||
|
|
||||||
Custom wire types: ``mk_codec()`` and friends
|
Custom wire types: ``mk_codec()`` and friends
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
msgspec covers a wide set of `builtin types`__ natively; for
|
msgspec covers a wide set of `builtin types`__ natively; for
|
||||||
anything else you teach the codec via extension hooks. The
|
anything else you teach the codec via extension hooks. The complete
|
||||||
easiest path is per-endpoint: ``@tractor.context()`` accepts
|
public path currently available is task-scoped encoding:
|
||||||
``enc_hook``/``dec_hook`` params right alongside ``pld_spec``.
|
``tractor.msg.mk_codec()`` builds a codec with an ``enc_hook``, and
|
||||||
For full control build and apply a codec yourself; encode-side:
|
``tractor.msg.apply_codec()`` installs it for the current task. To
|
||||||
|
build and apply that transport codec:
|
||||||
|
|
||||||
__ https://jcristharif.com/msgspec/supported-types.html
|
__ https://jcristharif.com/msgspec/supported-types.html
|
||||||
|
|
||||||
|
|
@ -206,8 +208,9 @@ __ https://jcristharif.com/msgspec/supported-types.html
|
||||||
with apply_codec(codec): # ContextVar-scoped override
|
with apply_codec(codec): # ContextVar-scoped override
|
||||||
... # msgs sent by this task now encode NSPs
|
... # msgs sent by this task now encode NSPs
|
||||||
|
|
||||||
and decode-side, scoped to an open context (note the import from
|
The context manager which temporarily installs payload-decoder
|
||||||
``tractor.msg._ops``, not yet re-exported):
|
settings on an open context is separate and still private (note
|
||||||
|
the ``tractor.msg._ops`` import):
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
|
|
@ -220,11 +223,15 @@ and decode-side, scoped to an open context (note the import from
|
||||||
):
|
):
|
||||||
... # this dialog's payloads decode as NSPs
|
... # this dialog's payloads decode as NSPs
|
||||||
|
|
||||||
``apply_codec()`` is ``ContextVar``-scoped: it overrides the
|
``apply_codec()`` is ``ContextVar``-scoped: it overrides the codec
|
||||||
codec for the current task (and only that task), not the whole
|
for the current task (and only that task), not the whole process.
|
||||||
process. For complete working flows, including hook pairing rules
|
``@tractor.context()`` accepts ``enc_hook`` and ``dec_hook``
|
||||||
and roundtrip cases, see ``tests/msg/test_ext_types_msgspec.py``
|
parameters, but their runtime wiring is not yet a symmetric,
|
||||||
and ``tests/msg/test_pldrx_limiting.py``.
|
end-to-end public hook pair: the encode hook is not consumed and
|
||||||
|
the decode hook is not applied on both peers. For the working flows
|
||||||
|
and their current boundaries, see
|
||||||
|
``tests/msg/test_ext_types_msgspec.py`` and
|
||||||
|
``tests/msg/test_pldrx_limiting.py``.
|
||||||
|
|
||||||
The runtime dogfoods this pattern with
|
The runtime dogfoods this pattern with
|
||||||
:class:`tractor.msg.NamespacePath`: a ``str``-subtype shaped like
|
:class:`tractor.msg.NamespacePath`: a ``str``-subtype shaped like
|
||||||
|
|
@ -253,13 +260,15 @@ escape hatch. Both are exercised end-to-end in
|
||||||
``tests/msg/test_pldrx_limiting.py`` and
|
``tests/msg/test_pldrx_limiting.py`` and
|
||||||
``tests/msg/test_ext_types_msgspec.py``.
|
``tests/msg/test_ext_types_msgspec.py``.
|
||||||
|
|
||||||
On the codec-hook side, the ``enc_hook``/``dec_hook`` pair is
|
The codec constructor and task-scoped override are public; the
|
||||||
today only reachable via ``tractor.msg._ops``; a public *factory*
|
per-dialog decoder override remains private, and the decorator hook
|
||||||
API for them is drafted in `#376`_ (from
|
parameters remain incomplete. `#376`_ (from
|
||||||
`@guilledk <https://github.com/guilledk>`_, on the
|
`@guilledk <https://github.com/guilledk>`_, on the
|
||||||
`auto_codecs <https://github.com/goodboy/tractor/tree/auto_codecs>`_
|
`auto_codecs <https://github.com/goodboy/tractor/tree/auto_codecs>`_
|
||||||
branch) — the likely long-term home for custom-type
|
branch) instead drafts pair-building factories which derive
|
||||||
(de)serialization.
|
matching ``enc_hook``/``dec_hook`` functions and encoder/decoder
|
||||||
|
pairs from a type spec. That automation, not hook availability,
|
||||||
|
is the proposed long-term home for custom-type (de)serialization.
|
||||||
|
|
||||||
If strongly-typed distributed systems get you going, we'd love
|
If strongly-typed distributed systems get you going, we'd love
|
||||||
your input on any of the above.
|
your input on any of the above.
|
||||||
|
|
@ -282,3 +291,4 @@ Where to next?
|
||||||
.. _#36: https://github.com/goodboy/tractor/issues/36
|
.. _#36: https://github.com/goodboy/tractor/issues/36
|
||||||
.. _#365: https://github.com/goodboy/tractor/issues/365
|
.. _#365: https://github.com/goodboy/tractor/issues/365
|
||||||
.. _#376: https://github.com/goodboy/tractor/pull/376
|
.. _#376: https://github.com/goodboy/tractor/pull/376
|
||||||
|
.. _#514: https://github.com/goodboy/tractor/issues/514
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue