Compare commits

..

No commits in common. "bc132f0b4c44e611730d89bbd2626cbfd5c9376e" and "ca436aa9ec1c3fd34829037f010c36b44c57e1a8" have entirely different histories.

6 changed files with 12 additions and 82 deletions

View File

@ -14,11 +14,10 @@ transport may currently be enabled per actor.
:margin: :margin:
:alt: layered runtime stack from app code down to transports :alt: layered runtime stack from app code down to transports
Address declarations still accept the legacy ``(host, port)`` Addresses are "unwrapped" tuples at the API edges:
TCP pair and ``(directory, filename)`` UDS pair. Wrapped addresses ``('host', port)`` for TCP, filesystem-path pairs for UDS. For
emit canonical, protocol-tagged tuples: ``('tcp', host, port)`` the full layering story — transport protocols, the IPC server,
and ``('unix', path)``. For the full layering story — transport address types and the msg loop — see
protocols, the IPC server, address types and the msg loop — see
:doc:`/explain/architecture`. :doc:`/explain/architecture`.
.. currentmodule:: tractor .. currentmodule:: tractor

View File

@ -104,24 +104,17 @@ msg-spec *is* the protocol, which is exactly what lets payloads
be type-limited per-context (see ``pld_spec`` in be type-limited per-context (see ``pld_spec`` in
:doc:`/guide/context`). :doc:`/guide/context`).
Address declarations and serialized values have distinct spellings: Addresses come in two spellings:
- *legacy declarations*: the plain tuples accepted from existing - *unwrapped*: the plain-tuple form you pass to user APIs —
callers — ``('127.0.0.1', 1616)`` for tcp, or a ``('127.0.0.1', 1616)`` for tcp, or a
``(<filedir>, <filename>)`` path-pair for uds; ``(<filedir>, <filename>)`` path-pair for uds;
- *canonical serialized values*: protocol-tagged tuples emitted by
address objects — ``('tcp', '127.0.0.1', 1616)`` and
``('unix', <path>)``;
- *wrapped*: the internal ``TCPAddress``/``UDSAddress`` struct - *wrapped*: the internal ``TCPAddress``/``UDSAddress`` struct
types (plus libp2p-style multiaddr helpers over in types (plus libp2p-style multiaddr helpers over in
``tractor.discovery``). ``tractor.discovery``).
The runtime accepts either declaration spelling, wraps it at the You only ever need the tuple form; the runtime wraps and
boundary and emits the canonical tagged form. unwraps at the boundaries.
Actors sharing a registrar are expected to run the same Tractor
version; the runtime does not negotiate address formats between
versions.
TCP: the boring default TCP: the boring default
*********************** ***********************

View File

@ -58,10 +58,10 @@ async def main():
registry_addrs=[addr.overlay], registry_addrs=[addr.overlay],
enable_transports=[addr.overlay.proto_key], enable_transports=[addr.overlay.proto_key],
) as an: ) as an:
_, overlay_host, _ = addr.unwrap() overlay_host, _ = addr.unwrap()
await an.start_actor( await an.start_actor(
'echo_srv', 'echo_srv',
bind_addrs=[('tcp', overlay_host, 0)], bind_addrs=[(overlay_host, 0)],
enable_transports=[addr.overlay.proto_key], enable_transports=[addr.overlay.proto_key],
enable_modules=['host_a_srv'], enable_modules=['host_a_srv'],
) )

View File

@ -1,3 +0,0 @@
Add transparent ``TunnelledAddress`` declarations for WireGuard
multiaddrs and emit canonical protocol-tagged TCP and Unix transport
addresses. Legacy untagged address pairs remain accepted as inputs.

View File

@ -3,13 +3,10 @@ Canonical tagged-address decoding and legacy input compatibility.
''' '''
from pathlib import Path from pathlib import Path
from types import SimpleNamespace
import pytest import pytest
import trio
from tractor.discovery._addr import wrap_address from tractor.discovery._addr import wrap_address
from tractor.discovery._registry import Registrar
from tractor.ipc._tcp import TCPAddress from tractor.ipc._tcp import TCPAddress
from tractor.ipc._uds import UDSAddress from tractor.ipc._uds import UDSAddress
@ -101,59 +98,3 @@ def test_tcp_from_native_ipv6_sockname():
) )
assert addr.unwrap() == ('tcp', '::1', 1616) assert addr.unwrap() == ('tcp', '::1', 1616)
@pytest.mark.parametrize(
'legacy, canonical',
[
(
('127.0.0.1', 1616),
('tcp', '127.0.0.1', 1616),
),
(
('/tmp/tractor', 'registry.sock'),
('unix', '/tmp/tractor/registry.sock'),
),
],
)
def test_registrar_stores_canonical_addresses(
legacy: tuple,
canonical: tuple,
):
'''
Normalize registrar entries before stale-address eviction.
During the tagged-address migration an older actor can register
an untagged address before a newer actor reuses that endpoint with
its canonical tag. Store the first declaration canonically, then
register the tagged spelling under another uid. The old uid must
be evicted and the registry must retain exactly one canonical
address for the replacement actor.
'''
registrar = SimpleNamespace(
_registry={},
_waiters={},
)
old_uid = ('old', 'old-uid')
new_uid = ('new', 'new-uid')
async def register_both():
await Registrar.register_actor(
registrar,
old_uid,
legacy,
)
assert registrar._registry[old_uid] == [canonical]
await Registrar.register_actor(
registrar,
new_uid,
canonical,
)
trio.run(register_both)
assert registrar._registry == {
new_uid: [canonical],
}

View File

@ -184,7 +184,7 @@ class Registrar(Actor):
# should never be 0-dynamic-os-alloc # should never be 0-dynamic-os-alloc
await debug.pause() await debug.pause()
addr_tup: tuple = waddr.unwrap() addr_tup: tuple = tuple(addr)
# Evict stale entries: if a *different* uid claims # Evict stale entries: if a *different* uid claims
# this addr (e.g. after unclean shutdown or # this addr (e.g. after unclean shutdown or