fed-sx-m2: Step 5c — peer-actors cache + 19 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 34s
New next/kernel/peer_actors.erl is the federation-side cache for
{PeerActorId, PeerActorState} entries. PeerAS is exactly the shape
envelope:verify_signature/2 reads (proplist with :public_keys), so
the inbox handler can pipe the cache hit straight into
pipeline:validate_inbound/3 from Step 5b.
Pure-functional API:
new/0
lookup/2(PeerId, State) -> {ok, PeerAS} | not_found
store/3(PeerId, PeerAS, State) -> NewState
evict/2(PeerId, State) -> NewState
peers/1(State) -> [PeerId]
lookup_or_fetch/3(PeerId, FetchFn, State)
-> {ok, PeerAS, NewState} cache hit returns unchanged State,
miss stores FetchFn result.
| {error, Reason, State} FetchFn failure preserves cache.
| {error, {bad_fetch_return, X}, State}
FetchFn contract: (PeerId) -> {ok, PeerAS} | {error, Reason}.
Failed fetches do NOT poison the cache so callers can retry on
transient HTTP failures.
gen_server wrapper (registered name peer_actors):
start_link/0,1 start_link/1 accepts initial proplist for fixtures
stop/0
lookup_srv/1
store_srv/2
lookup_or_fetch_srv/2
peers_srv/0
evict_srv/1
handle_call dispatches mirror the pure-fn paths exactly.
The actual HTTP-GET fetch implementation (peer's actor doc -> peer
AS proplist) is Step 5d's responsibility — for 5c, FetchFn is just
the contract callers fill in.
19/19 in next/tests/peer_actors.sh:
- new/0 -> []
- lookup miss -> not_found
- store + lookup round-trip
- peers/1 in insertion order
- evict + evict-unknown no-op
- lookup_or_fetch miss invokes FetchFn, hits cache after
- lookup_or_fetch hit skips FetchFn (verified by tombstone fn)
- fetch error preserves cache state
- bad fetch return shape captured
- gen_server start_link + miss/hit/fetch/evict round-trips
- start_link/1 pre-populates cache from initial state
Conformance 761/761. 139/139 across 9 Step-5-adjacent suites
(inbox_pipeline, inbox_bucket, pipeline_signature, registry_server,
projection_server, nx_kernel_multi, bootstrap_start, http_publish,
smoke_app_pure, plus the new peer_actors).
This commit is contained in:
@@ -360,11 +360,21 @@ actor *received*), and broadcasts to projections.
|
||||
(rejected by stage_envelope before sig runs), wrong peer AS
|
||||
(bad_signature), replay against inbox, distinct activities both
|
||||
verify, stage short-circuit ordering verified.
|
||||
- [ ] **5c** — Peer-actors cache projection (`peer_actors.erl`):
|
||||
on first inbound from a new peer, fetches the peer's actor doc
|
||||
and caches the public-keys. v2: synchronous fetch via the
|
||||
http-client native primitive. Per design §13.6, stale-key
|
||||
invalidation is v3.
|
||||
- [x] **5c** — Peer-actors cache (`peer_actors.erl`). State shape
|
||||
`[{PeerActorId, PeerActorState}, ...]` keyed by atom; PeerAS is
|
||||
exactly the shape `envelope:verify_signature/2` reads (proplist
|
||||
with `:public_keys`). Pure exports: `new/0`, `lookup/2`,
|
||||
`store/3`, `evict/2`, `peers/1`, and the load-bearing
|
||||
`lookup_or_fetch/3(PeerId, FetchFn, State)` that calls the
|
||||
caller-supplied `FetchFn :: (PeerId) -> {ok, PeerAS} | {error, _}`
|
||||
on miss and stores the successful result. Failed fetches do NOT
|
||||
poison the cache so callers can retry on transient errors.
|
||||
gen_server wrapper: `start_link/0,1`, `lookup_srv/1`,
|
||||
`store_srv/2`, `lookup_or_fetch_srv/2`, `peers_srv/0`,
|
||||
`evict_srv/1`. `start_link/1` accepts an initial state proplist
|
||||
for tests / fixtures. 19/19 in `peer_actors.sh`. The actual
|
||||
fetch implementation (HTTP GET of the peer's actor doc) is
|
||||
Step 5d's responsibility — for 5c, FetchFn is just a contract.
|
||||
- [ ] **5d** — http_server inbox handler wires the chain:
|
||||
`POST /actors/<id>/inbox` body is the signed activity wire bytes;
|
||||
parse → resolve peer-AS → `validate_inbound` → `append_inbox` →
|
||||
@@ -780,6 +790,20 @@ proceed.
|
||||
|
||||
Newest first.
|
||||
|
||||
- **2026-06-06** — Step 5c: peer-actors cache (`peer_actors.erl`).
|
||||
Pure-functional cache of `{PeerActorId, PeerAS}` entries with
|
||||
the load-bearing `lookup_or_fetch/3(PeerId, FetchFn, State)`
|
||||
entry: cache hit returns stored PeerAS unchanged; miss calls
|
||||
`FetchFn(PeerId)`, stores success, returns `{ok, PeerAS,
|
||||
NewState}`. Fetch errors don't poison the cache so callers can
|
||||
retry on transient HTTP failures. gen_server wrapper exposes
|
||||
the same shape under registered name `peer_actors`;
|
||||
`start_link/1` accepts an initial proplist for tests.
|
||||
Per-design v2 fetches are synchronous over plaintext HTTP; the
|
||||
actual http-client call lands in Step 5d. 19/19 in
|
||||
`peer_actors.sh`. Conformance 761/761. 139/139 across 9
|
||||
Step-5-adjacent suites.
|
||||
|
||||
- **2026-06-06** — Step 5b: federation inbound pipeline.
|
||||
`pipeline:validate_inbound/3(Activity, PeerAS, InboxLog)` runs
|
||||
`stage_envelope` → `stage_signature(PeerAS)` → `stage_replay(InboxLog)`
|
||||
|
||||
Reference in New Issue
Block a user