-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[transport] Add binding port to SpawnedServer #861
Conversation
625cbe4
to
2c27da9
Compare
098f813
to
bf957fd
Compare
bf957fd
to
d5dc98d
Compare
d5dc98d
to
866e2a6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two main things:
- I think we should expose the whole
SocketAddr
, we can write theget_port
in this PR and we'll deal with e.g.get_address
later. - We can probably rename things to be closer than what they are:
create_network
is actually astart_network
,start
is actually amonitor
/wait_for_completion
/run_to_end
.
network_utils/src/transport.rs
Outdated
tokio::spawn(run_tcp_server(listener, state, receiver, buffer_size)) | ||
}; | ||
Ok(SpawnedServer { complete, handle }) | ||
// see https://fly.io/blog/the-tokio-1-x-upgrade/#tcplistener-from_std-needs-to-be-set-to-nonblocking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is too detached from the line it's commenting on.
network_utils/src/transport.rs
Outdated
@@ -86,22 +91,23 @@ where | |||
S: MessageHandler<TcpDataStream> + Send + Sync + 'static, | |||
{ | |||
let (complete, receiver) = futures::channel::oneshot::channel(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a cancellation channel, to make this idiiomatic with the rest of the codebase, we could rename (here and in the struct definition), to:
let (tx_cancellation, rx_cancellation) = futures::channel::oneshot::channel();
network_utils/src/transport.rs
Outdated
let local_addr = std_listener.local_addr()?; | ||
let host = local_addr.ip(); | ||
let port = local_addr.port(); | ||
info!("Listening to TCP traffic on {}:{}", host, port); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I think captured identifiers are nice.
sui/src/sui_commands.rs
Outdated
}); | ||
info!("Started {} authorities", handles.len()); | ||
join_all(handles).await; | ||
info!("All server stopped."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: plural
sui/src/sui_commands.rs
Outdated
} | ||
}); | ||
info!("Started {} authorities", handles.len()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the time you log this, these have long been started. You want to log at the end of create_network
instead.
sui/src/sui_commands.rs
Outdated
let mut spawned_authorities = Vec::new(); | ||
for authority in &config.authorities { | ||
let server = make_server(authority, &committee, config.buffer_size).await?; | ||
spawned_authorities.push(server.spawn().await?); | ||
} | ||
Ok(SuiNetwork { | ||
spawned_authorities, | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This create_network
now requires a comment indicating that if we finish the caller's task (and drop the SuiNetwork
) without calling start
, all servers are dropped as well.
If we drop the SuiNetwork
. but not the caller's task, the servers will continue in detached mode (which is probably why the logging-on-error done currently in start
should probably be an obligation on the server).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm didn't realise this is behaving this way.... thanks for pointing this out!
In this case I think maybe better moving the create_network into SuiNetwork, so we don't have detached network running unexpectedly.
sui/src/unit_tests/cli_tests.rs
Outdated
let network = create_network(&network_config).await?; | ||
|
||
SuiCommand::Genesis { | ||
working_dir, | ||
config: Some(genesis_conf_path), | ||
let network_config = network_config.persisted(&network_path); | ||
network_config.save()?; | ||
keystore.save(&keystore_path)?; | ||
|
||
let authorities = network_config.get_authority_infos(); | ||
let authorities = authorities | ||
.into_iter() | ||
.zip(&network.spawned_authorities) | ||
.map(|(mut info, server)| { | ||
info.base_port = server.get_port(); | ||
info | ||
}) | ||
.collect(); | ||
|
||
// Create wallet.conf with stated authorities port | ||
WalletConfig { | ||
accounts, | ||
keystore: KeystoreType::File(keystore_path), | ||
gateway: GatewayType::Embedded(EmbeddedGatewayConfig { | ||
db_folder_path, | ||
authorities, | ||
..Default::default() | ||
}), | ||
} | ||
.execute() | ||
.await?; | ||
.persisted(&wallet_path) | ||
.save()?; | ||
|
||
// Start network | ||
let network = task::spawn(async move { | ||
SuiCommand::Start { | ||
config: network_conf_path, | ||
} | ||
.execute() | ||
.await | ||
}); | ||
Ok(network) | ||
Ok(network.start()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The renames I'm suggesting should make this function a lot more understandable: the network is actually started way before start
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love this! The tests are so much cleaner now.
sui/src/unit_tests/cli_tests.rs
Outdated
let (network_config, accounts, keystore) = genesis(genesis_config).await?; | ||
let network = create_network(&network_config).await?; | ||
|
||
SuiCommand::Genesis { | ||
working_dir, | ||
config: Some(genesis_conf_path), | ||
let network_config = network_config.persisted(&network_path); | ||
network_config.save()?; | ||
keystore.save(&keystore_path)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will these files ever get deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use temp_dir in test, so the folder will get deleted automatically after the test
sui/src/sui_commands.rs
Outdated
|
||
impl SuiNetwork { | ||
pub fn start(self) -> JoinHandle<Result<(), anyhow::Error>> { | ||
task::spawn(async move { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
N00b question: why do we spawn these spawned_server
(which have been spawned on line 129) again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This extra spawn is redundant! we can wait for completion in the same thread.
.into_iter() | ||
.zip(&network.spawned_authorities) | ||
.map(|(mut info, server)| { | ||
info.base_port = server.get_port(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how does the non-test code path work? Where do we ensure the port number stored in network.conf
matches the one in spawned servers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in non-test path, if the user decided to start the server using port 0, is their responsibility to manually change the wallet.conf to align the port.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the servers will be spawned using ports provided by network.conf, we will not modify the config to align the port.
When the configured port number is 0, the user can get the actual binding port number from the console/log output.
* cli test use SpawnedServer's binding port instead of hardcoding ports * remove wait for "Listening to TCP traffic on 127.0.0.1" log output, `start_test_network` now block until authorities are up
f3da9b6
to
0cbcc65
Compare
I have addressed all comments, more review please :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a bunch, with the rename things make much more sense!
So happy we'll now be killing this bug!
This is an improvement to SpawnedServer to expose actual binding tcp port, this allow us to start the server with port 0 and retrieve the binding port for later use.
SpawnedServer
start_test_network
now block until authorities are up