Key `TIPCAddress` instances by actor UUID
TIPC service names span the cluster while PIDs remain host-local. Hashing only `(name, pid)` could therefore make same-named actors on different hosts silently share one round-robin service name. Derive the live-runtime seed from `Aid.uid` so the actor UUID separates those names while keeping each identity reproducible. Pin both properties with a deterministic regression test. Review: PR #493 (copilot-pull-request-reviewer[bot],goodboy) https://github.com/goodboy/tractor/pull/493 (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))wkt/pr493_review
parent
a19a639ddf
commit
d52c78c106
|
|
@ -232,6 +232,43 @@ def test_get_random_collision_resistance():
|
|||
assert all(addr.is_valid for addr in addrs)
|
||||
|
||||
|
||||
def test_get_random_keys_live_actors_by_uuid(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
):
|
||||
'''
|
||||
TIPC names are cluster-wide while PIDs are host-local. Hashing
|
||||
only `(actor name, pid)` therefore made same-named actors with
|
||||
equal PIDs on different hosts publish one service name, where
|
||||
TIPC silently round-robins connects between them.
|
||||
|
||||
Hold the actor name and PID fixed while changing only its UUID;
|
||||
distinct instances prove the globally unique identity field is
|
||||
now part of the derivation.
|
||||
|
||||
'''
|
||||
monkeypatch.setattr(_tipc.os, 'getpid', lambda: 1616)
|
||||
|
||||
def get_addr(uuid: str) -> TIPCAddress:
|
||||
actor = SimpleNamespace(
|
||||
aid=Aid(
|
||||
name='worker',
|
||||
uuid=uuid,
|
||||
pid=1616,
|
||||
)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
_tipc,
|
||||
'current_actor',
|
||||
lambda **kwargs: actor,
|
||||
)
|
||||
return TIPCAddress.get_random()
|
||||
|
||||
first: TIPCAddress = get_addr('actor-uuid-a')
|
||||
second: TIPCAddress = get_addr('actor-uuid-b')
|
||||
assert first._instance != second._instance
|
||||
assert get_addr('actor-uuid-a')._instance == first._instance
|
||||
|
||||
|
||||
def test_get_random_honors_bindspace():
|
||||
addr: TIPCAddress = TIPCAddress.get_random(
|
||||
bindspace=TIPC_NODE_SCOPE,
|
||||
|
|
|
|||
|
|
@ -369,10 +369,11 @@ class TIPCAddress(
|
|||
between them (verified). I.e. a collision manifests as
|
||||
*silent crosstalk*, not an error.
|
||||
|
||||
So the instance is a `blake2b` digest of a per-call-unique
|
||||
seed, giving a well-spread 32b value. Being a pure fn of the
|
||||
seed it is also *reproducible*, which the (follow-up)
|
||||
registrar-less discovery fast-path wants.
|
||||
So the instance is a `blake2b` digest of the actor UUID, or
|
||||
a per-call token outside a live runtime, giving a well-spread
|
||||
32b value. Being a pure fn of the seed it is also
|
||||
*reproducible*, which the (follow-up) registrar-less
|
||||
discovery fast-path wants.
|
||||
|
||||
NOTE the residual risk is birthday-bounded: ~1.2e-2 for 10k
|
||||
names sharing one `_stype`. See plan 01 §9 for the
|
||||
|
|
@ -384,7 +385,7 @@ class TIPCAddress(
|
|||
err_on_no_runtime=False,
|
||||
)
|
||||
if actor:
|
||||
seed: str = f'{actor.aid.name}@{pid}'
|
||||
seed: str = '.'.join(actor.aid.uid)
|
||||
else:
|
||||
if is_root_process():
|
||||
prefix: str = 'no_runtime_root'
|
||||
|
|
|
|||
Loading…
Reference in New Issue