Skip to content

feat: gate the server behind a default feature - #19

Closed
jonasz-lasut wants to merge 2 commits into
mainfrom
feat/server-feature
Closed

jonasz-lasut wants to merge 2 commits into
mainfrom
feat/server-feature

Conversation

@jonasz-lasut

Copy link
Copy Markdown
Collaborator

Motivation

The crate has no Cargo features, so everything it links is unconditional: tokio (rt-multi-thread, signal), tonic with tls-aws-lc, tonic-health, tonic-reflection, clap, prometheus-client, tracing-subscriber and the generated tonic client and server. A WebAssembly guest that wants only the protocol messages and the request/response/resource helpers cannot depend on it, because tokio and aws-lc-sys do not build for wasm targets.

What the server feature gates

[features] default = ["server"]. The feature enables the optional dependencies (bytes, clap, http, http-body, prometheus-client, tokio, tonic, tonic-health, tonic-prost, tonic-reflection, tower-layer, tower-service, tracing, tracing-subscriber) and, under #[cfg(feature = "server")]:

  • server.rs (serve, Args, the re-exports), metrics.rs, logging.rs
  • the server-side Error variants: InvalidAddress, MissingTlsCertsDir, ReadCertificate, Transport, Reflection, and with them their From impls
  • the generated function_runner_service_client / function_runner_service_server modules under proto::v1
  • proto::FILE_DESCRIPTOR_SET
  • the serve integration test (required-features = ["server"])

Every existing dependent keeps the whole crate, the feature being on by default. The feature is documented in the README (a "Features" section), the crate README, the crate docs and sdk/Cargo.toml.

What default-features = false builds

The protocol messages with their protojson serde impls, plus context, request, response and resource. That set builds natively and for wasm32-wasip1 and wasm32-wasip2, and is what a function compiled to a WebAssembly module depends on (function-wasm's Rust scaffold, whose host serves the gRPC side). A new no-server CI job builds, tests and lints that set natively and builds it for wasm32-wasip1.

How the generated code stays reproducible

No generated output was edited by hand. tonic's service generator used to append the gRPC client and server to prost's message file; codegen now wraps it in a prost_build::ServiceGenerator that routes its output into a buffer of its own, written to sdk/src/generated/v1.tonic.rs. proto.rs includes that file under the cfg, next to the unconditional v1.rs and v1.serde.rs. The bytes are unchanged: the old v1.rs is the new v1.rs followed by v1.tonic.rs, and v1.serde.rs did not move. cargo run -p codegen regenerates all three as before, and the existing codegen-drift job covers the new file through its sdk/src/generated/*.rs glob. The committed fileset.bin was left as is (it differs only by local protoc version, which that job tolerates).

The change is two commits: the codegen split on its own (builds and tests exactly as before, with the new file included unconditionally), then the feature gate.

Verified

All on stable Rust 1.97.1, macOS arm64:

  • cargo fmt --all --check: clean
  • cargo clippy --workspace --tests -- -D warnings (CI's command) and cargo clippy --workspace --all-targets -- -D warnings: clean
  • cargo clippy -p function-sdk-rust --no-default-features --all-targets -- -D warnings: clean
  • cargo test --workspace: all pass (5 unit, 18 helpers, 1 serve, doc tests)
  • cargo test -p function-sdk-rust --no-default-features: all pass (18 helpers, doc tests; serve skipped by required-features)
  • cargo build -p function-sdk-rust --no-default-features: ok
  • cargo build -p function-sdk-rust --no-default-features --target wasm32-wasip1: ok
  • cargo build -p function-sdk-rust --no-default-features --target wasm32-wasip2: ok
  • RUSTDOCFLAGS="-D warnings" cargo doc --no-deps -p function-sdk-rust, with and without --no-default-features: clean
  • cargo run -p codegen then diff <(cat v1.rs v1.tonic.rs) <(git show main:sdk/src/generated/v1.rs): identical
  • cargo publish -p function-sdk-rust --dry-run: ok, v1.tonic.rs packaged
  • Cargo.lock: unchanged

Fixes #18

tonic's service generator appended the gRPC client and server to prost's
message file. A wrapping ServiceGenerator routes its output into
sdk/src/generated/v1.tonic.rs instead, so the messages and the gRPC code
can be included independently. The generated bytes are unchanged: the
old v1.rs is the new v1.rs followed by v1.tonic.rs.

Signed-off-by: Jonasz Małecki <jonasz@upbound.io>
The crate had no Cargo features: tokio, tonic with its TLS stack, clap,
prometheus-client and the generated tonic client and server were
unconditional, so a WebAssembly guest that wants only the messages and
the request/response/resource helpers could not depend on it.

A server feature, on by default, now carries server.rs, metrics.rs,
logging.rs, the server-side Error variants, the generated tonic client
and server and FILE_DESCRIPTOR_SET, with their dependencies optional
behind it. Every current dependent keeps the whole crate; with
default-features = false the messages and the helpers remain and build
for wasm32-wasip1 and wasm32-wasip2. CI builds that set natively and
for wasm32-wasip1.

Fixes #18

Signed-off-by: Jonasz Małecki <jonasz@upbound.io>
@jonasz-lasut

Copy link
Copy Markdown
Collaborator Author

Closing: the split is more invasive than the gain for its one consumer justifies. function-wasm keeps vendoring run_function.proto for its rust scaffold instead (jonasz-lasut/function-wasm#129).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gate the server side behind a default server feature

1 participant