Compare commits
3 Commits
ca436aa9ec
...
bc132f0b4c
| Author | SHA1 | Date |
|---|---|---|
|
|
bc132f0b4c | |
|
|
8e428527ff | |
|
|
9d1e476d04 |
|
|
@ -14,10 +14,11 @@ 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
|
||||||
|
|
||||||
Addresses are "unwrapped" tuples at the API edges:
|
Address declarations still accept the legacy ``(host, port)``
|
||||||
``('host', port)`` for TCP, filesystem-path pairs for UDS. For
|
TCP pair and ``(directory, filename)`` UDS pair. Wrapped addresses
|
||||||
the full layering story — transport protocols, the IPC server,
|
emit canonical, protocol-tagged tuples: ``('tcp', host, port)``
|
||||||
address types and the msg loop — see
|
and ``('unix', path)``. For the full layering story — transport
|
||||||
|
protocols, the IPC server, address types and the msg loop — see
|
||||||
:doc:`/explain/architecture`.
|
:doc:`/explain/architecture`.
|
||||||
|
|
||||||
.. currentmodule:: tractor
|
.. currentmodule:: tractor
|
||||||
|
|
|
||||||
|
|
@ -104,17 +104,24 @@ 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`).
|
||||||
|
|
||||||
Addresses come in two spellings:
|
Address declarations and serialized values have distinct spellings:
|
||||||
|
|
||||||
- *unwrapped*: the plain-tuple form you pass to user APIs —
|
- *legacy declarations*: the plain tuples accepted from existing
|
||||||
``('127.0.0.1', 1616)`` for tcp, or a
|
callers — ``('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``).
|
||||||
|
|
||||||
You only ever need the tuple form; the runtime wraps and
|
The runtime accepts either declaration spelling, wraps it at the
|
||||||
unwraps at the boundaries.
|
boundary and emits the canonical tagged form.
|
||||||
|
|
||||||
|
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
|
||||||
***********************
|
***********************
|
||||||
|
|
|
||||||
|
|
@ -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=[(overlay_host, 0)],
|
bind_addrs=[('tcp', 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'],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
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.
|
||||||
|
|
@ -3,10 +3,13 @@ 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
|
||||||
|
|
||||||
|
|
@ -98,3 +101,59 @@ 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],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 = tuple(addr)
|
addr_tup: tuple = waddr.unwrap()
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue