Skip to content

Commit

Permalink
Auto merge of #240 - lennart/CLOUD-5-scuffle-bootstrap, r=TroyKomodo
Browse files Browse the repository at this point in the history
scuffle-bootstrap: test coverage and docs
- Add test coverage
- Add docs

Closes CLOUD-5

Requested-by: TroyKomodo <[email protected]>
Reviewed-by: TroyKomodo <[email protected]>
  • Loading branch information
scuffle-brawl[bot] authored Jan 13, 2025
2 parents 52205ce + 44b6b4a commit 3ed7ebd
Show file tree
Hide file tree
Showing 18 changed files with 691 additions and 82 deletions.
48 changes: 48 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ scuffle-http = { path = "crates/http", version = "0.0.4" }
scuffle-metrics = { path = "crates/metrics", version = "0.0.4" }
scuffle-pprof = { path = "crates/pprof", version = "0.0.2" }
scuffle-batching = { path = "crates/batching", version = "0.0.4" }
scuffle-postcompile = { path = "crates/postcompile", version = "0.0.5" }
postcompile = { path = "crates/postcompile", version = "0.0.5" }
scuffle-ffmpeg = { path = "crates/ffmpeg", version = "0.0.2" }
scuffle-h3-webtransport = { path = "crates/h3-webtransport", version = "0.0.2" }
scuffle-metrics-derive = { path = "crates/metrics/derive", version = "0.0.2" }
Expand Down
3 changes: 3 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ test *args:
cargo +{{RUST_TOOLCHAIN}} llvm-cov report --lcov --output-path ./lcov.info
cargo +{{RUST_TOOLCHAIN}} llvm-cov report --html

doc *args:
cargo +{{RUST_TOOLCHAIN}} doc --no-deps --all-features {{args}}

deny *args:
cargo +{{RUST_TOOLCHAIN}} deny {{args}} --all-features check

Expand Down
7 changes: 0 additions & 7 deletions crates/batching/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
//! # scuffle-batching
//!
//! > WARNING
//! > This crate is under active development and may not be stable.
//!
//! [![crates.io](https://img.shields.io/crates/v/scuffle-batching.svg)](https://crates.io/crates/scuffle-batching) [![docs.rs](https://img.shields.io/docsrs/scuffle-batching)](https://docs.rs/scuffle-batching)
//!
//! ---
//!
//! A crate designed to batch multiple requests into a single request.
//!
//! ## Why do we need this?
Expand Down
9 changes: 9 additions & 0 deletions crates/bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ documentation = "https://docs.rs/scuffle-bootstrap"
license = "MIT OR Apache-2.0"
keywords = ["bootstrap", "binary", "cli", "config"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }

[dependencies]
anyhow = "1.0"
tokio = { version = "1", features = ["full"] }
Expand All @@ -19,3 +22,9 @@ pin-project-lite = "0.2"
scuffle-context.workspace = true
scuffle-bootstrap-derive.workspace = true
scuffle-workspace-hack.workspace = true

[dev-dependencies]
insta = "1.42.0"
postcompile = { workspace = true, features = ["prettyplease"] }
scuffle-future-ext.workspace = true
scuffle-signal = { workspace = true, features = ["bootstrap"] }
43 changes: 41 additions & 2 deletions crates/bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,54 @@
> [!WARNING]
> This crate is under active development and may not be stable.
[![crates.io](https://img.shields.io/crates/v/scuffle-bootstrap.svg)](https://crates.io/crates/scuffle-bootstrap) [![docs.rs](https://img.shields.io/docsrs/scuffle-bootstrap)](https://docs.rs/scuffle-bootstrap)
[![crates.io](https://img.shields.io/crates/v/scuffle-bootstrap.svg)](https://crates.io/crates/scuffle-bootstrap) [![docs.rs](https://img.shields.io/docsrs/scuffle-bootstrap)](https://docs.rs/scuffle-bootstrap)

---

A utility crate for creating binaries.

Refer to `Global`, `Service`, and `main` for more information.

## Usage

TODO(troy): Add usage examples to readme.
```rust
use std::sync::Arc;

/// Our global state
struct Global;

// Required by the signal service
impl scuffle_signal::SignalConfig for Global {}

impl scuffle_bootstrap::global::GlobalWithoutConfig for Global {
async fn init() -> anyhow::Result<Arc<Self>> {
Ok(Arc::new(Self))
}
}

/// Our own custom service
struct MySvc;

impl scuffle_bootstrap::service::Service<Global> for MySvc {
async fn run(self, global: Arc<Global>, ctx: scuffle_context::Context) -> anyhow::Result<()> {
println!("running");

// Do some work here

// Wait for the context to be cacelled by the signal service
ctx.done().await;
Ok(())
}
}

// This generates the main function which runs all the services
scuffle_bootstrap::main! {
Global {
scuffle_signal::SignalSvc,
MySvc,
}
}
```

## License

Expand Down
7 changes: 7 additions & 0 deletions crates/bootstrap/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ license = "MIT OR Apache-2.0"
description = "Derive macros for scuffle-bootstrap."
keywords = ["bootstrap", "derive", "macros"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }

[lib]
proc-macro = true

Expand All @@ -19,3 +22,7 @@ proc-macro2 = "1"
quote = "1"
darling = "0.20"
scuffle-workspace-hack.workspace = true

[dev-dependencies]
insta = "1"
prettyplease = "0.2"
137 changes: 131 additions & 6 deletions crates/bootstrap/derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]

use proc_macro::TokenStream;

mod main_impl;
// mod service_impl;

// #[proc_macro_attribute]
// pub fn service(args: TokenStream, input: TokenStream) -> TokenStream {
// handle_error(service_impl::impl_service(args.into(), input.into()))
// }

#[proc_macro]
pub fn main(input: TokenStream) -> TokenStream {
Expand All @@ -19,3 +15,132 @@ fn handle_error(input: Result<proc_macro2::TokenStream, syn::Error>) -> TokenStr
Err(err) => err.to_compile_error().into(),
}
}

#[cfg(test)]
#[cfg_attr(all(test, coverage_nightly), coverage(off))]
mod tests {
use super::*;

#[test]
fn test_main() {
let input = quote::quote! {
MyGlobal {
MyService,
}
};

let output = match main_impl::impl_main(input) {
Ok(value) => value,
Err(err) => err.to_compile_error(),
};

let syntax_tree = prettyplease::unparse(&syn::parse_file(&output.to_string()).unwrap());

insta::assert_snapshot!(syntax_tree, @r##"
#[automatically_derived]
fn main() -> ::scuffle_bootstrap::prelude::anyhow::Result<()> {
#[doc(hidden)]
pub const fn impl_global<G: ::scuffle_bootstrap::global::Global>() {}
const _: () = impl_global::<MyGlobal>();
::scuffle_bootstrap::prelude::anyhow::Context::context(
<MyGlobal as ::scuffle_bootstrap::global::Global>::pre_init(),
"pre_init",
)?;
let runtime = <MyGlobal as ::scuffle_bootstrap::global::Global>::tokio_runtime();
let config = ::scuffle_bootstrap::prelude::anyhow::Context::context(
runtime
.block_on(
<<MyGlobal as ::scuffle_bootstrap::global::Global>::Config as ::scuffle_bootstrap::config::ConfigParser>::parse(),
),
"config parse",
)?;
let ctx_handle = ::scuffle_bootstrap::prelude::scuffle_context::Handler::global();
let mut shared_global = ::core::option::Option::None;
let mut services_vec = ::std::vec::Vec::<
::scuffle_bootstrap::service::NamedFuture<
::scuffle_bootstrap::prelude::tokio::task::JoinHandle<anyhow::Result<()>>,
>,
>::new();
let result = runtime
.block_on(async {
let global = <MyGlobal as ::scuffle_bootstrap::global::Global>::init(config)
.await?;
shared_global = ::core::option::Option::Some(global.clone());
{
#[doc(hidden)]
pub async fn spawn_service(
svc: impl ::scuffle_bootstrap::service::Service<MyGlobal>,
global: &::std::sync::Arc<MyGlobal>,
ctx_handle: &::scuffle_bootstrap::prelude::scuffle_context::Handler,
name: &'static str,
) -> anyhow::Result<
Option<
::scuffle_bootstrap::service::NamedFuture<
::scuffle_bootstrap::prelude::tokio::task::JoinHandle<
anyhow::Result<()>,
>,
>,
>,
> {
let name = ::scuffle_bootstrap::service::Service::<
MyGlobal,
>::name(&svc)
.unwrap_or_else(|| name);
if ::scuffle_bootstrap::prelude::anyhow::Context::context(
::scuffle_bootstrap::service::Service::<
MyGlobal,
>::enabled(&svc, &global)
.await,
name,
)? {
Ok(
Some(
::scuffle_bootstrap::service::NamedFuture::new(
name,
::scuffle_bootstrap::prelude::tokio::spawn(
::scuffle_bootstrap::service::Service::<
MyGlobal,
>::run(svc, global.clone(), ctx_handle.context()),
),
),
),
)
} else {
Ok(None)
}
}
let res = spawn_service(MyService, &global, &ctx_handle, "MyService")
.await;
if let Some(spawned) = res? {
services_vec.push(spawned);
}
}
<MyGlobal as ::scuffle_bootstrap::global::Global>::on_services_start(&global)
.await?;
macro_rules! handle_service_exit {
($remaining:ident) => {
{ let ((name, result), _, remaining) =
::scuffle_bootstrap::prelude::futures::future::select_all($remaining)
. await; let result =
::scuffle_bootstrap::prelude::anyhow::Context::context(::scuffle_bootstrap::prelude::anyhow::Context::context(result,
name) ?, name); < MyGlobal as ::scuffle_bootstrap::global::Global >
::on_service_exit(& global, name, result). await ?; remaining }
};
}
let mut remaining = handle_service_exit!(services_vec);
while !remaining.is_empty() {
remaining = handle_service_exit!(remaining);
}
::scuffle_bootstrap::prelude::anyhow::Ok(())
});
let ::core::option::Option::Some(global) = shared_global else {
return result;
};
runtime
.block_on(
<MyGlobal as ::scuffle_bootstrap::global::Global>::on_exit(&global, result),
)
}
"##);
}
}
2 changes: 2 additions & 0 deletions crates/bootstrap/derive/src/main_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ pub fn impl_main(input: TokenStream) -> Result<TokenStream, syn::Error> {

#(#services)*

#entry_as_global::on_services_start(&#global_ident).await?;

macro_rules! handle_service_exit {
($remaining:ident) => {{
let ((name, result), _, remaining) = #crate_path::prelude::futures::future::select_all($remaining).await;
Expand Down
7 changes: 0 additions & 7 deletions crates/bootstrap/derive/src/service_impl.rs

This file was deleted.

Loading

0 comments on commit 3ed7ebd

Please sign in to comment.