-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
review of file controller_routing #28
Comments
This is an interesting point. Parcel is indeed the structure for both internal network messages and external application messages. The reasoning why they're the same is mostly because Golang is a painful language for these kind of "dynamic" types. It's not an object oriented language but it does have interfaces. The way I'd implement your vision is to have "Parcel" be an interface with various implementations:
the interface would look like this:
This is a rather cumbersome approach that requires a fair amount of copypasting, though it could work. A different approach would be to keep it as it is and just make both It would be much easier than interface juggling, though you'd still have to compare parcel.Address with p2p.Broadcast and the likes. Thoughts? |
I'm okay with Peer having Ping/Pong functions, PeerRequest would be better suited for the controller.
Around three years ago, the P2P package split all application messages into 1000 byte "messageparts", though that was deemed unnecessary since TCP will already split large messages into small chunks. Instead of removing the code, they just raised the limit to 1000000000 bytes (1 gigabyte), which means P2P1 will always send out "MessagePart" messages. P2P2 only sends out "Message" types, and converts "MessagePart"s to regular "Message" types for consistency. There is no functional difference between Message and MessagePart anymore, so they're handled by the same switch case now |
This is the new route: factom-p2p/controller_routing.go Lines 6 to 39 in 6459677
Not sure if it's worth factoring out each switch-case into its own function as before. I'm open to it if you think it's a good idea in regards to potential unit testing. This is already a big improvement over the previous code though, imo. |
Great question! I have no idea and am changing it.
I originally intended to rename |
Yes, that is intended functionality at the moment, taken over from P2P1: https://github.com/FactomProject/factomd/blob/6f0164ba51dc1776d1ca44a3555ae1dd510bc5fb/p2p/controller.go#L666-L674 If the special peers are counted inside count, there are situations where if you have more special nodes than regular peers, you could end up never broadcasting to non-special peers at all. It also impacts the probability of packet routing, with special peers receiving an abnormal amount of "random" selections. Tacking special peers on top of regular peers doesn't have either of those problems, although you're paying with more bandwidth. At the moment, the only nodes using special peers are ANOs to establish the backhaul network. |
I haven't been clear enough in my comment about case "A":
fallthrough
case "B":
// handle case A and B is better written in Go: case "A", "B":
// handle case A and B Golang switch supports list of cases. |
I still need to think more about 1. I also want to understand how currently the application layer uses the network layer (p2p module). |
Ah, my apologies! |
The short explanation: RoutingFactomd has its own simulated p2p network inside the node, which is used to test "simulated nodes" (SimNode). By default, there is only one other simulated "node" in this network: p2pproxy. The proxy bridges the internal factom p2p network with the p2p package. The messages in the internal network are of type "FactomMessage", the proxy converts them to the p2p network parcels: and vice-versa for incoming p2p parcels, it converts them to factom messages: FactomMessages are just a carrier for internal node messages, summarizing the whole message flow as: IMsg => (internal network) FactomMessage[IMsg] => (p2p package) Parcel[IMsg] => (tcp) V10Parcel[IMsg] ProcessingFactomd checks two things of network messages: duplication and validity. There are some p2p libraries that will have their own duplicate filter, but p2p2 doesn't have one because factomd handles this aspect. Validity checks the IMsg to ensure it's properly signed, has the right time, is supposed to be a network messages, etc. Only valid messages are then sent back to the network to be rebroadcasted. |
For 1. with the lack of generics I couldn't find a good solution not requiring duplicate code. So maybe un-exporting |
I added a fix for most of the scheduling in 9433d6d I played around with channel sizes in my testapp and found that the channel most likely to drop parcels was "FromNetwork", meaning the application isn't reading from it fast enough. I added a I ended up just baking |
Reviewing file https://github.com/WhoSoup/factom-p2p/blob/master/controller_routing.go
ToNetwork
/FromNetwork
are the interfaces between the application and the p2p package. I think those communication channels should not use the Parcel struct but its own structure specific to the communication with the application layer; Parcel is an object that belongs to the networking layer and should not leak outside. Here are some elements that brought me to this conclusion:-first just from a layering point of view it's better to have things well defined and isolated. It's very similar to the classic DTO vs DAO pattern
-the only Parcel that should go in/out to the Application must be of type
TypeMessage/TypeMessagePart
, having a specific type for application communication would definitively rule out any possibility to mistakenly send in/out unwanted Parcel types (prevent bugs ahead thanks to typing mechanism)."" or nil for broadcast, otherwise the destination peer's hash.
but that's not completely true, when coming from the application it is filled with "", "" or "". That's another hint that you may be overloading your Parcel struct with 2 different meanings in 2 different contexts.manageData
method: I think it's better if there is as little logic as possible within the cases of the switch. In theTypePing
case I see a comment "// Move": I say yes! Let's create a Pong method of peer and just call that in in the switch case (also maybe create a Ping method for Peer for symmetry). Similarly theTypePeerRequest
case contains a bit too much logic for my personal taste that would be better encapsulated. It seems you don't need that distinction between TypeMessage and TypeMessagePart any more, I guess you can merge them instead of usingfallthrough
?Broadcast
why does it take a boolean as an argument while the type could be determined within by using the Parcel type? Technically speaking this method could receive inconsistent information between this boolean and the parcel type, by relying solely on the type you protect programmers against this risk.randomPeers
andrandomPeersConditional
return results that are a bit surprising/inconsistent to me in the case you have less elements thancount
, you will not fulfill your promise of randomness, but still return some peers. It looks like a half-baked results. If the contract is to returned exactlycount
peers and you cannot meet that demand then make it clear by returning an empty slice (or nil). Also you separate the caselen(peers) == 0
but it seems to me it fits the general case, it's not particularly special.This snippet looks suspicious to me as
len(special)+len(regular)
may end up greater than count, should that be a possibility? I'd find that surprising as a client of this function.The text was updated successfully, but these errors were encountered: