Skip to content

p2p: add MemoryTransport, an in-memory transport for testing#5827

Merged
erikgrinaker merged 1 commit intomasterfrom
erik/memory-transport
Dec 23, 2020
Merged

p2p: add MemoryTransport, an in-memory transport for testing#5827
erikgrinaker merged 1 commit intomasterfrom
erik/memory-transport

Conversation

@erikgrinaker
Copy link
Contributor

This should probably have more tests, but I expect the transport layer to change quite a bit before the P2P refactor is done, so we'll add more later.

@erikgrinaker erikgrinaker added the C:p2p Component: P2P pkg label Dec 23, 2020
@erikgrinaker erikgrinaker self-assigned this Dec 23, 2020
@codecov
Copy link

codecov bot commented Dec 23, 2020

Codecov Report

Merging #5827 (87f775b) into master (0a41711) will decrease coverage by 0.18%.
The diff coverage is 70.76%.

@@            Coverage Diff             @@
##           master    #5827      +/-   ##
==========================================
- Coverage   59.90%   59.72%   -0.19%     
==========================================
  Files         262      263       +1     
  Lines       23688    23834     +146     
==========================================
+ Hits        14190    14234      +44     
- Misses       7991     8073      +82     
- Partials     1507     1527      +20     
Impacted Files Coverage Δ
p2p/transport_memory.go 69.87% <69.87%> (ø)
abci/types/messages.go 7.69% <100.00%> (-12.31%) ⬇️
privval/signer_endpoint.go 69.69% <0.00%> (-12.13%) ⬇️
privval/signer_listener_endpoint.go 77.64% <0.00%> (-11.77%) ⬇️
privval/signer_server.go 89.47% <0.00%> (-5.27%) ⬇️
types/tx.go 82.97% <0.00%> (-4.26%) ⬇️
privval/socket_listeners.go 78.72% <0.00%> (-4.26%) ⬇️
privval/secret_connection.go 72.68% <0.00%> (-3.61%) ⬇️
libs/clist/clist.go 63.74% <0.00%> (-3.51%) ⬇️
consensus/reactor.go 73.58% <0.00%> (-2.65%) ⬇️
... and 12 more

Copy link
Contributor

@melekes melekes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@erikgrinaker erikgrinaker merged commit 84ff991 into master Dec 23, 2020
@erikgrinaker erikgrinaker deleted the erik/memory-transport branch December 23, 2020 12:21
Comment on lines +296 to +301
// check close first, since channels are buffered
select {
case <-c.closeCh:
return 0, nil, io.EOF
default:
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this? The go c.close can be closed between this block and the next select.

Copy link
Contributor Author

@erikgrinaker erikgrinaker Jan 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to make sure that if the connection is already closed, we never receive or send a message. For example, if receiveCh contains a buffered message but the connection has been closed, without this check there is a 50% chance that the buffered message will be returned even though the connection has been closed.

If the connection is closed after this check (concurrently with the select) there is also a 50% chance that the message will be returned, but that is consistent with concurrency semantics where either the receive event or the close event may happen first depending on goroutine/channel scheduling. However, after a close event there should never be a receive event.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, but I don't see what first select buys us since there is still a chance we receive and return a message if the connection is closed before the last select.

Copy link
Contributor Author

@erikgrinaker erikgrinaker Jan 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the select, a single (non-concurrent) client can see this behavior:

connection.Close()
msg := connection.ReceiveMessage() // returns a message!

This is clearly wrong. The first select makes sure this will never happen.

If they are concurrent, however, it is entirely reasonable for there to be a 50% chance of receiving a message:

go func() {
  connection.Close()
}()

go func() {
  msg := connection.ReceiveMessage() // 50% chance of returning, entirely reasonable
}()

The first select is necessary to make connection closures linearizable, i.e. once the connection is closed it stays closed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think that's reasonable 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C:p2p Component: P2P pkg

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants