Skip to content

Commit 1f66c69

Browse files
authored
add parallelism to autorust using rayon (#1416)
1 parent 4d394af commit 1f66c69

File tree

5 files changed

+75
-47
lines changed

5 files changed

+75
-47
lines changed

services/autorust/azure-autorust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ publish = false
88
[dependencies]
99
autorust_codegen = { path = "../codegen" }
1010
clap = { version = "4.0", features = ["derive"] }
11+
rayon = "1.8"

services/autorust/azure-autorust/src/main.rs

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use autorust_codegen::{
66
crates::{list_crate_names, list_dirs},
77
gen, get_mgmt_readmes, get_svc_readmes,
88
jinja::{CheckAllServicesYml, PublishSdksYml, PublishServicesYml, WorkspaceCargoToml},
9-
Error, ErrorKind, Result, RunConfig,
9+
ErrorKind, Result, ResultExt, RunConfig, SpecReadme,
1010
};
1111
use clap::Parser;
12+
use rayon::prelude::*;
1213

1314
#[derive(Debug, clap::Parser)]
1415
struct Args {
@@ -43,29 +44,47 @@ fn main() -> Result<()> {
4344
gen_workflow_publish_services()?;
4445
}
4546
}
46-
if args.fmt {
47-
fmt(packages)?;
48-
}
4947
Ok(())
5048
}
5149

52-
fn gen_crates(only_packages: &[&str]) -> Result<()> {
53-
let svc = get_svc_readmes()?.into_iter().map(|x| ("svc", x));
54-
let mgmt = get_mgmt_readmes()?.into_iter().map(|x| ("mgmt", x));
55-
56-
for (i, (crate_type, spec)) in svc.chain(mgmt).enumerate() {
57-
let output_folder = format!("../{crate_type}");
58-
let prefix = format!("azure_{crate_type}_");
50+
fn gen_crate(only_packages: &[&str], crate_type: &str, spec: &SpecReadme) -> Result<Option<(String, Vec<String>)>> {
51+
let output_folder = format!("../{crate_type}");
52+
let prefix = format!("azure_{crate_type}_");
5953

60-
let run_config = RunConfig::new(&prefix);
61-
let package_name = gen::package_name(&spec, &run_config);
62-
if !only_packages.is_empty() && !only_packages.contains(&package_name.as_str()) {
63-
continue;
64-
}
54+
let run_config = RunConfig::new(&prefix);
55+
let package_name = gen::package_name(spec, &run_config);
6556

66-
println!("{package_name} ({i})");
67-
gen::gen_crate(&package_name, &spec, &run_config, &output_folder)?;
57+
if !only_packages.is_empty() && !only_packages.contains(&package_name.as_str()) {
58+
Ok(None)
59+
} else {
60+
let tags = gen::gen_crate(&package_name, spec, &run_config, &output_folder)
61+
.with_context(ErrorKind::CodeGen, || format!("generating {package_name}"))?;
62+
Ok(Some((package_name, tags)))
6863
}
64+
}
65+
66+
fn gen_crates(only_packages: &[&str]) -> Result<()> {
67+
let svc = get_svc_readmes()?.into_iter().map(|x| ("svc".to_string(), x));
68+
let mgmt = get_mgmt_readmes()?.into_iter().map(|x| ("mgmt".to_string(), x));
69+
let crate_iters = svc.chain(mgmt).collect::<Vec<_>>();
70+
71+
let results: Result<Vec<_>> = crate_iters
72+
.par_iter()
73+
.map(|(crate_type, spec)| gen_crate(only_packages, crate_type, spec))
74+
.collect::<Vec<_>>()
75+
.into_iter()
76+
.collect();
77+
78+
(results?).into_iter().flatten().for_each(|(package_name, tags)| {
79+
println!("{package_name}");
80+
if tags.is_empty() {
81+
println!(" No tags");
82+
} else {
83+
for tag in tags {
84+
println!("- {tag}");
85+
}
86+
}
87+
});
6988

7089
Ok(())
7190
}
@@ -124,22 +143,3 @@ fn gen_workflow_publish_services() -> Result<()> {
124143
yml.create("../../.github/workflows/publish-services.yml")?;
125144
Ok(())
126145
}
127-
128-
/// Run `cargo fmt` on the services workspace or a subset of packages.
129-
fn fmt(only_packages: &[&str]) -> Result<()> {
130-
let services_dir = "../";
131-
let mut args = vec!["fmt"];
132-
if !only_packages.is_empty() {
133-
args.push("-p");
134-
for package in only_packages {
135-
args.push(package);
136-
}
137-
}
138-
let out = std::process::Command::new("cargo").current_dir(services_dir).args(args).output()?;
139-
if !out.status.success() {
140-
println!("cargo fmt failed");
141-
println!("{}", std::str::from_utf8(&out.stderr)?);
142-
return Err(Error::new(ErrorKind::Io, "cargo fmt failed"));
143-
}
144-
Ok(())
145-
}

services/autorust/codegen/src/codegen_operations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ impl ToTokens for RequestBuilderIntoFutureCode {
12131213
},
12141214
)
12151215
} else {
1216-
println!("unsupported LRO: {lro_options:?}");
1216+
// println!("unsupported LRO: {lro_options:?}");
12171217

12181218
(
12191219
quote! {

services/autorust/codegen/src/gen.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
autorust_toml, cargo_toml, io, lib_rs,
33
readme_md::{self, ReadmeMd},
4-
CrateConfig, Error, Result, RunConfig, SpecReadme,
4+
run, CrateConfig, Error, Result, RunConfig, SpecReadme,
55
};
66
use std::{collections::HashMap, fs};
77

@@ -11,7 +11,8 @@ pub fn package_name(spec: &SpecReadme, run_config: &RunConfig) -> String {
1111
format!("{}{}", &run_config.crate_name_prefix, &spec.service_name())
1212
}
1313

14-
pub fn gen_crate(package_name: &str, spec: &SpecReadme, run_config: &RunConfig, output_folder: &str) -> Result<()> {
14+
pub fn gen_crate(package_name: &str, spec: &SpecReadme, run_config: &RunConfig, output_folder: &str) -> Result<Vec<String>> {
15+
let mut generated_tags = vec![];
1516
let spec_config = spec.config()?;
1617
let service_name = &spec.service_name();
1718
let output_folder = &io::join(output_folder, service_name)?;
@@ -43,16 +44,15 @@ pub fn gen_crate(package_name: &str, spec: &SpecReadme, run_config: &RunConfig,
4344

4445
let tags = &package_config.filter_tags(spec_config.tags());
4546
if tags.is_empty() {
46-
println!("not generating {} - no tags", spec.spec());
47-
return Ok(());
47+
return Ok(generated_tags);
4848
}
4949

5050
let mut operation_totals = HashMap::new();
5151
let mut api_version_totals = HashMap::new();
5252
let mut api_versions = HashMap::new();
5353
let mut has_xml = false;
5454
for tag in tags {
55-
println!(" {}", tag.name());
55+
generated_tags.push(tag.name().to_owned());
5656
let output_folder = io::join(&src_folder, tag.rust_mod_name())?;
5757
let input_files: Result<Vec<_>> = tag
5858
.input_files()
@@ -65,7 +65,7 @@ pub fn gen_crate(package_name: &str, spec: &SpecReadme, run_config: &RunConfig,
6565
output_folder,
6666
input_files,
6767
};
68-
let cg = crate::run(crate_config, &package_config)?;
68+
let cg = run(crate_config, &package_config)?;
6969
let operations = cg.spec.operations()?;
7070
operation_totals.insert(tag.name(), operations.len());
7171
let mut versions = cg.spec.api_versions();
@@ -95,5 +95,5 @@ pub fn gen_crate(package_name: &str, spec: &SpecReadme, run_config: &RunConfig,
9595
};
9696
readme.create(&readme_path)?;
9797

98-
Ok(())
98+
Ok(generated_tags)
9999
}

services/autorust/codegen/src/lib.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ pub mod lib_rs;
1515
pub mod readme_md;
1616
pub mod spec;
1717
mod status_codes;
18+
1819
use autorust_toml::PackageConfig;
1920
use camino::{Utf8Path, Utf8PathBuf};
2021
use config_parser::Configuration;
2122
pub use error::{Error, ErrorKind, Result, ResultExt};
2223
use proc_macro2::TokenStream;
2324
use quote::ToTokens;
24-
use std::io::Write;
2525
use std::{
2626
collections::HashSet,
2727
fs::{self, File},
28+
io::Write,
29+
process::{Command, Stdio},
2830
};
2931

3032
pub use self::{
@@ -124,15 +126,40 @@ pub fn run<'a>(crate_config: &'a CrateConfig, package_config: &'a PackageConfig)
124126
Ok(cg)
125127
}
126128

129+
fn rustfmt(input: &str) -> Result<Vec<u8>> {
130+
let mut cmd = Command::new("rustfmt");
131+
cmd.args(["--emit", "stdout", "--edition", "2021"]);
132+
let mut child = cmd
133+
.stdin(Stdio::piped())
134+
.stdout(Stdio::piped())
135+
.spawn()
136+
.with_context(ErrorKind::Io, || "spawn rustfmt")?;
137+
child
138+
.stdin
139+
.as_mut()
140+
.ok_or_else(|| Error::message(ErrorKind::Io, "rustfmt stdin is not available"))?
141+
.write_all(input.as_bytes())
142+
.with_context(ErrorKind::Io, || "write to rustfmt stdin")?;
143+
let output = child.wait_with_output().with_context(ErrorKind::Io, || "wait for rustfmt")?;
144+
if !output.status.success() {
145+
return Err(Error::message(
146+
ErrorKind::Io,
147+
format!("rustfmt failed: {}", String::from_utf8_lossy(&output.stderr)),
148+
));
149+
}
150+
Ok(output.stdout)
151+
}
152+
127153
fn write_file<P: AsRef<Utf8Path>>(file: P, tokens: &TokenStream, print_writing_file: bool) -> Result<()> {
128154
let file = file.as_ref();
129155
if print_writing_file {
130156
println!("writing file {}", &file);
131157
}
132158
let code = tokens.to_string();
159+
let code = rustfmt(&code)?;
133160
let mut buffer = File::create(file).with_context(ErrorKind::Io, || format!("create file {file}"))?;
134161
buffer
135-
.write_all(code.as_bytes())
162+
.write_all(&code)
136163
.with_context(ErrorKind::Io, || format!("write file {file}"))?;
137164
Ok(())
138165
}

0 commit comments

Comments
 (0)