Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Companion PR for Move subcommands from sc-cli to nodes #6948 #1635

Merged
merged 5 commits into from
Sep 1, 2020

Conversation

expenses
Copy link
Contributor

@expenses expenses added A0-please_review Pull request needs code review. B0-silent Changes should not be mentioned in any release notes A4-companion A PR that needs a companion PR to merge in parallel for one of its downstream dependencies. C1-low PR touches the given topic and has a low impact on builders. labels Aug 25, 2020
@expenses expenses requested review from cecton and bkchr August 25, 2020 09:42
/// Validate blocks.
CheckBlock(sc_cli::CheckBlockCmd),

/// Export blocks.
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice if those comments could be moved to sc-cli instead so people don't need to duplicate them on every project.

(I don't know if this is possible!)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, not sure. If I don't comment these lines there's still some text for them in the --help display, but it's for some of the options for the command, not the command itself. Weird.

},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
runner.sync_run(|config| cmd.run(config.database))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not 100% sure but since we do have to repeat ourselves a lot, we'd better make it easier by using the same pattern everywhere. Is it possible to use async_run everywhere? Even if the code is blocking, it doesn't really matter that it in a future or not (little bit of overhead, that's ok).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You need a TaskManager to pass into async_run (unless we make that an Option<TaskManager>?), and it seems like a waste to build one just for that.

Copy link
Contributor

Choose a reason for hiding this comment

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

TaskManager?? 😁 That was not my idea when I made it. The run_node_until_exit was meant to use a task manager but sync_run and async_run where meant to run without task manager. Apparently it has been changed in paritytech/substrate#6543

On the bright side: async_run seems not to be used at all anywhere except in this PR. Not even here in polkadot. So we can still change the course if we want.

It might be worth considering really only using a future in async_run and let the code inside handle any task manager they night have (and call clean_shutdown when the command needs to stop the node for example).

Comment on lines 253 to 284
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;

set_default_ss58_version(chain_spec);

if chain_spec.is_kusama() {
runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) = service::new_chain_ops::<
service::kusama_runtime::RuntimeApi,
service::KusamaExecutor,
>(&mut config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
} else if chain_spec.is_westend() {
runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) = service::new_chain_ops::<
service::westend_runtime::RuntimeApi,
service::WestendExecutor,
>(&mut config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
} else {
runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) = service::new_chain_ops::<
service::polkadot_runtime::RuntimeApi,
service::PolkadotExecutor,
>(&mut config)?;
Ok((cmd.run(client, import_queue), task_manager))
})
}
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible for us to have an fn that does all this?

and we call it so

async_run(&cli, cmd)

where cmd is a generic trait with the run method

and it internally does all these runtime checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I tried, this and came up with:

fn run_cmd<CMD, FN, B>(cli: &Cli, cmd: &CMD, func: FN) -> Result<()>
	where
		FN: FnOnce(sc_cli::Runner<Cli>, &CMD) -> Result<()>,
		CMD: sc_cli::CliConfiguration + sc_cli::SubstrateCli,
{
	let runner = cli.create_runner(cmd)?;
	let chain_spec = &runner.config().chain_spec;

	set_default_ss58_version(chain_spec);

	if chain_spec.is_kusama() {
		func::<service::kusama_runtime::Block, service::KusamaExecutor>(runner, cmd)
	} else if chain_spec.is_westend() {
		func::<service::westend_runtime::Block, service::WestendExecutor>(runner, cmd)
	} else {
		func::<service::polkadot_runtime::Block, service::PolkadotExecutor>(runner, cmd)
	}
}

Unfortunately, rust does not allow you to put generics on a FnOnce like this:

error[E0109]: type arguments are not allowed for this type
   --> cli/src/command.rs:366:10
    |
366 |         func::<service::kusama_runtime::Block, service::KusamaExecutor>(runner, cmd)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type argument not allowed

error[E0109]: type arguments are not allowed for this type
   --> cli/src/command.rs:368:10
    |
368 |         func::<service::westend_runtime::Block, service::WestendExecutor>(runner, cmd)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type argument not allowed

error[E0109]: type arguments are not allowed for this type
   --> cli/src/command.rs:370:10
    |
370 |         func::<service::polkadot_runtime::Block, service::PolkadotExecutor>(runner, cmd)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type argument not allowed

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0109`.
error: could not compile `polkadot-cli`.

You get the same problem with a macro as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

What about:

fn run_cmd<CMD, B>(cli: &Cli, cmd: &CMD) -> Result<()>
	where
		CMD: sc_cli::CliConfiguration + sc_cli::SubstrateCli,
{
	let runner = cli.create_runner(cmd)?;
	let chain_spec = &runner.config().chain_spec;

	set_default_ss58_version(chain_spec);

	if chain_spec.is_kusama() {
    runner.async_run(|mut config| {
		  let (client, _, import_queue, task_manager) = service::new_chain_ops::<
			  service::kusama_runtime::RuntimeApi,
			  service::KusamaExecutor,
		  >(&mut config)?;
		  Ok((cmd.run(client, import_queue), task_manager))
	  })
	} else if chain_spec.is_westend() {
    runner.async_run(|mut config| {
		  let (client, _, import_queue, task_manager) = service::new_chain_ops::<
			  service::westend_runtime::RuntimeApi,
			  service::WestEndExecutor,
		  >(&mut config)?;
		  Ok((cmd.run(client, import_queue), task_manager))
	  })
	} else {
    runner.async_run(|mut config| {
		  let (client, _, import_queue, task_manager) = service::new_chain_ops::<
			  service::polkadot_runtime::RuntimeApi,
			  service::PolkadotExecutor,
		  >(&mut config)?;
		  Ok((cmd.run(client, import_queue), task_manager))
	  })
	}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The different subcommands have different inputs unfortunately.

Copy link
Contributor

Choose a reason for hiding this comment

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

In that case i think it's fine for now

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can achieve this if you use the Client enum that Basti introduced recently: https://github.com/paritytech/polkadot/blob/master/service/src/client.rs#L138

You would need to make the cmd.run accepts that Client enum.

Ideally we should move the if kusama { ... } else if westend { ... } else ... { ... } pattern to polkadot service instead of the binary.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, that works.

Copy link
Contributor

@seunlanlege seunlanlege left a comment

Choose a reason for hiding this comment

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

So much better 👏🏾

@ghost
Copy link

ghost commented Sep 1, 2020

Waiting for commit status.

@ghost
Copy link

ghost commented Sep 1, 2020

Checks failed; merge aborted.

@expenses
Copy link
Contributor Author

expenses commented Sep 1, 2020

bot merge

@ghost
Copy link

ghost commented Sep 1, 2020

Missing process info; check that the PR belongs to a project column.

Merge can be attempted if:

  • The PR has approval from two core-devs (or one if the PR is labelled insubstantial).
  • The PR has approval from a member of substrateteamleads.
  • The PR is attached to a project column and has approval from the project owner.

See https://github.com/paritytech/parity-processbot#faq

@expenses expenses merged commit e2ebf25 into master Sep 1, 2020
@expenses expenses deleted the ashley-remove-subcommand branch September 1, 2020 09:27
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A0-please_review Pull request needs code review. A4-companion A PR that needs a companion PR to merge in parallel for one of its downstream dependencies. B0-silent Changes should not be mentioned in any release notes C1-low PR touches the given topic and has a low impact on builders.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants