refactor(peer): run Manager connections through the protocol core
peer.Manager made its own pre-CER, packet, control, watchdog and
retirement decisions for every connection it owned. Each dialed and
accepted connection generation now runs through one private protocol
core, the one StateMachine and Client already use. Manager keeps what
lies above a single connection: peer authorization and selection,
election (RFC 6733 §5.6.4), dialing, routing, the shared identifier
space, queues, pending requests and failover (RFC 6733 §5.5.4),
reconnection, notifications, renewal and retirement. Native connections
are still supervised through DispatchDone, and the public API does not
change.
Behaviour changes, each with a test that fails on main:
- Inbound activity that did not refresh the watchdog interval on main now
does, without counting toward health: a malformed or repeated CER,
other recoverable decode errors, an invalid header, invalid grammar, a
request rejected by optional validation, a wrong bound host, an
unsolicited CEA or DPA, and decoded traffic while reopening. - During local Closing, the first DPR received records the peer's cause;
a later DPR no longer replaces reconnect suppression. - For every adapter, a request rejected during Closing is now dropped
before its error answer is built. When building that answer failed,
StateMachine and Client used to close the connection, report
ProtocolReplyFailed and end Disconnect with ErrDisconnectClosed;
Closing now continues to its DPA or deadline.
Where Manager still differs from StateMachine, a named core option
selects each diagnostic or disposition policy. A differential test of
StateMachine and Client against main matches 3,758 of 3,760
observations; the two differences are the Closing change above.
Core effects shrink from 1,208 to 304 bytes and are appended into
storage the caller lends; a successful queued answer completes without
waking the Manager's actor; each core keeps one spare operation record.
BenchmarkInboundMessages at one processor, bytes and allocations per
exchange, main → this change (dialed exchanges match accepted ones):
| Exchange | B/op | allocs/op |
|---|---|---|
| peer Accepted/ApplicationRequestRejection | 7627 → 6394 | 141 → 126 |
| peer Accepted/CorrelatedApplicationAnswer | 5441 → 5169 | 121 → 118 |
| peer Accepted/UnsolicitedApplicationAnswer | 3312 → 3104 | 59 → 57 |
| peer Accepted/WatchdogExchange | 3928 → 2264 | 75 → 57 |
| sm Accepted/ApplicationRequest | 11041 → 4128 | 60 → 59 |
| sm Accepted/ApplicationAnswer | 9760 → 2848 | 23 → 22 |
| sm Accepted/WatchdogExchange | 14409 → 5176 | 84 → 81 |
Closes #112.
Summary by cubic
Runs all peer.Manager connections through the shared protocol core that StateMachine and Client already use, removing duplicate pre-CER, packet, control, watchdog, and retirement logic. The public API is unchanged; Manager still handles peer selection, election, dialing, routing, queuing, failover, and renewal.
Behavior changes
- Inbound activity that previously didn't refresh the watchdog interval now does, without counting toward health: malformed or repeated CERs, recoverable decode errors, invalid headers, invalid grammar, rejected requests, wrong bound hosts, unsolicited CEAs/DPAs, and traffic while reopening.
- During local Closing, the first received DPR records the peer's cause; a later DPR no longer replaces reconnect suppression.
- Requests rejected during Closing are now dropped before building an error answer. If answer building fails, Closing continues to its DPA or deadline instead of closing the connection and ending Disconnect with ErrDisconnectClosed.
Performance
- Core effects shrink from 1,208 to 304 bytes and are appended into caller-lent storage; a successful queued answer no longer wakes the Manager's actor.
- Allocates noticeably less per exchange; see BenchmarkInboundMessages numbers in the diff.
Closes #112.