Replies: 1 comment
-
Implementation Approach: Simplifying Upgrader with GenericMultistreamSelectorPR #1233 addresses issue #313 by consolidating duplicated multistream-select negotiation logic and fixing a critical bug in ProblemCode Duplication: Critical Bug: SolutionCreated Implementation
Results
Files ModifiedNew Files
Modified Files
References
This approach successfully consolidates duplicated code, fixes a critical bug, maintains backward compatibility, and follows the design direction outlined in the original issue and discussion. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This discussion continues the design conversation from issue #313 (Simplify upgrader components?), so the issue stays easy to manage. Please carry on here.
Relation to #395
#313 is about simplifying the upgrader (less duplication, minimal abstractions). Issue #395 is about restructuring and interfaces. They’re related: simplifying the upgrader by depending on minimal interfaces (e.g.
ReadWriteCloser+ initiator) and consolidating multistream-select usage fits the “depend on interfaces, not special-case wrappers” direction of #395.1. Duplication between the two multistream classes
SecurityMultistreamandMuxerMultistreamshare the same pattern:OrderedDictof protocol → transport (or muxer class)Multiselect()andMultiselectClient()add_transport(protocol, x)that does: pop if present, store in dict,multiselect.add_handler(protocol, None)MultiselectCommunicator(conn), then eithermultiselect_client.select_one_of(protocols, communicator[, timeout])(initiator) ormultiselect.negotiate(communicator[, timeout])(listener), then return the chosen transport/classOnly the type of stored value (security transport vs muxer class) and what you do after selection (call
secure_inbound/secure_outboundvs instantiate muxer with(conn, peer_id)) differ.Conclusion: The specialization doesn’t justify two full classes. We can introduce a generic “multistream selector” (one class or helper) that holds the protocol → handler/factory map and exposes
select(conn, is_initiator, timeout?) -> (protocol, value), usingMultiselect/MultiselectClient/MultiselectCommunicatorinternally. Security and muxer layers then use that selector for negotiation only and apply the chosen security transport or muxer class. That gives one place for multistream-select behaviour and less maintenance.2.
ISecureConnvsReadWriteCloserin the muxer pathMultiselectCommunicatoralready takesReadWriteCloser; it only does read/write. So for negotiation, it doesn’t needISecureConn.MuxerMultistreamuses the connection for: (1) buildingMultiselectCommunicator(conn), (2) readingconn.is_initiator, (3) passingconninto the muxer constructor. For (1) and (2) the minimal type is ReadWriteCloser +is_initiator. For (3) the muxer still needs a full secure connection (e.g.ISecureConn).Conclusion: We can relax the negotiation path to depend on a minimal interface (e.g. a small Protocol “ReadWriteCloser + is_initiator”). The return of the security layer (what gets passed into the muxer) should stay
ISecureConn. So: “MuxerMultistream’s negotiation step doesn’t require the fullISecureConninterface, only read/write + initiator.”3. Inbound / outbound handling
Security uses explicit in/out methods; muxer uses
conn.is_initiator. A unified selector can take(conn, is_initiator, timeout?)and do the same client/listener branching. No need for two different abstractions.4. Bug in current code
In
MuxerMultistream:self.multistream_clientin__init__(line 62).select_transportusesself.multiselect_client(line 92), which is never assigned.new_connusesself.multistream_client(line 117).So
select_transportwould raiseAttributeErrorif ever used. Fix: use a single name everywhere (e.g.multiselect_client) for the client instance.5. Suggested direction (for a possible PR)
select(conn, is_initiator, timeout?) -> chosen_value, implemented with oneMultiselect, oneMultiselectClient, andMultiselectCommunicator(conn).transport.secure_inbound(conn)ortransport.secure_outbound(conn, peer_id); muxer uses selector to pick muxer class, thenmuxer_class(conn, peer_id)(Yamux special-case in one place).ISecureConninto the muxer constructor.multistream_client/multiselect_clientnaming bug so one attribute is used consistently.If there’s consensus, we can turn this into a short design note and reference it from issue #313 and any follow-up PRs.
Beta Was this translation helpful? Give feedback.
All reactions