Skip to content

common-svc: split bootstrap.rs by facility (pure move) - #567

Merged
ac-pplx merged 2 commits into
mainfrom
ac/split-common-svc-bootstrap
Oct 16, 2026
Merged

ac-pplx merged 2 commits into
mainfrom
ac/split-common-svc-bootstrap

Conversation

@ac-pplx

@ac-pplx ac-pplx commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

crates/libs/common/svc/src/bootstrap.rs (1,071 code lines) is named for when services use it, not for what it does. It holds five unrelated facilities with different callers:

  • gRPC request parameter recording and failed-request logging;
  • Unix socket binding (11 node-local services);
  • the HTTP trace layer (api and data-plane);
  • the gRPC trace layer (every gRPC server);
  • shutdown signal handling (every binary).

This keeps the gRPC server builder and health service in bootstrap.rs and moves each facility into its own module. bootstrap.rs drops to 77 code lines; the largest new file is unix_socket.rs at 338.

This is a pure move, generated by scripts/split_rust_module.py (#562) from the spec below and proved by its verify. It is part of splitting the largest production modules into smaller ones with one job each.

What moved where

Module Holds Code lines
grpc_request_params gRPC request parameters: recording parameters callers have reviewed as safe on the request span, and the opt-in, testing-only logging of them when a request fails, truncated to a byte limit. 109
unix_socket Binding node-local Unix sockets: atomic replacement through a staging path, permissions and group ownership. 338
http_trace The HTTP server trace layer: span naming and redaction, probe filtering, and the traceparent response header. 186
grpc_trace The gRPC server trace layer: the request span, status classification and logging, and the client service and status read from headers. 306
shutdown Process shutdown: SIGINT and SIGTERM handling and the cancellation tokens services drain on. 77
bootstrap.rs (parent) the gRPC server builder, its keepalive and timeout constants, the health service, and the request-id header parsing HTTP and gRPC share 77

How to check it

The spec (item names, not lines):

file = "crates/libs/common/svc/src/bootstrap.rs"

[[module]]
name = "grpc_request_params"
doc = "gRPC request parameters: recording parameters callers have reviewed as safe on the request span, and the opt-in, testing-only logging of them when a request fails, truncated to a byte limit."
items = [
  "const FAILED_GRPC_REQUEST_LOG_ENV", "const MAX_LOGGED_GRPC_REQUEST_PARAMS_BYTES",
  "static FAILED_GRPC_REQUEST_LOGGING_ENABLED", "fn initialize_failed_grpc_request_logging",
  "fn failed_grpc_request_logging_enabled_from_env", "fn format_grpc_request_params",
  "fn record_safe_grpc_request_params", "fn log_failed_grpc_request_params",
  "fn failed_grpc_request_logging_enabled", "fn failed_grpc_request_logging_enabled_for_env",
  "struct TruncatedLogValue", "fn truncate_utf8_for_log", "fn grpc_request_params_for_log",
  "enum GrpcRequestParamsLogSeverity", "fn grpc_request_params_log_severity",
]

[[module]]
name = "unix_socket"
doc = "Binding node-local Unix sockets: atomic replacement through a staging path, permissions and group ownership."
items = [
  "enum SocketGroup", "struct UnixSocketOptions", "enum BindUnixSocketError", "impl BindUnixSocketError",
  "enum UnixSocketStagingPathError", "enum ApplyUnixSocketPermissionsError", "struct UnixGroupLookupError",
  "impl UnixSocketOptions", "fn bind_unix_socket", "fn bind_unix_socket_replacement",
  "fn bind_unix_socket_replacement_at", "const SOCKET_NONCE_ALPHABET", "const SOCKET_STAGING_PREFIX",
  "fn unix_socket_staging_shape", "fn unix_socket_staging_path_for_attempt", "fn apply_unix_socket_permissions",
  "fn apply_socket_group", "fn unix_group_exists", "fn unix_group_gid",
]

[[module]]
name = "http_trace"
doc = "The HTTP server trace layer: span naming and redaction, probe filtering, and the traceparent response header."
items = [
  "const REDACTED_HTTP_PATH_VALUE", "trait HttpSpanMetadata", "fn is_probe_request",
  "struct DefaultHttpSpanMetadata", "impl HttpSpanMetadata for DefaultHttpSpanMetadata",
  "const UNTRACED_HTTP_PATHS", "struct HttpServerMakeSpan", "impl<M> HttpServerMakeSpan<M> *",
  "impl Default for HttpServerMakeSpan<DefaultHttpSpanMetadata>", "impl<M, B> MakeSpan<B> for HttpServerMakeSpan<M> *",
  "struct HttpServerOnResponse", "impl<B> OnResponse<B> for HttpServerOnResponse", "struct HttpServerOnFailure",
  "impl OnFailure<ServerErrorsFailureClass> for HttpServerOnFailure", "type TraceparentResponseLayer",
  "type HttpServerTraceLayer", "fn http_trace_layer", "fn insert_traceparent_header", "const TRACEPARENT_HEADER",
]

[[module]]
name = "grpc_trace"
doc = "The gRPC server trace layer: the request span, status classification and logging, and the client service and status read from headers."
items = [
  "const UNKNOWN_SERVICE", "fn grpc_trace_layer", "struct SandboxSpanLayer", "impl SandboxSpanLayer",
  "impl<S> tower::Layer<S> for SandboxSpanLayer", "struct SandboxSpanService",
  "impl<S, Request> tower::Service<Request> for SandboxSpanService<S> *", "fn grpc_server_status_classifier",
  "fn grpc_application_status_classifier", "fn grpc_status_is_error", "struct GrpcMakeSpan",
  "impl<B> MakeSpan<B> for GrpcMakeSpan", "struct GrpcOnResponse", "impl<B> OnResponse<B> for GrpcOnResponse",
  "struct GrpcOnEos", "impl OnEos for GrpcOnEos", "struct GrpcOnFailure",
  "impl OnFailure<GrpcFailureClass> for GrpcOnFailure", "fn log_grpc_server_status",
  "fn record_grpc_status_from_headers", "fn record_grpc_status_on_span", "fn parse_grpc_path",
  "fn grpc_client_service_from_headers", "fn grpc_status_from_headers",
]

[[module]]
name = "shutdown"
doc = "Process shutdown: SIGINT and SIGTERM handling and the cancellation tokens services drain on."
items = [
  "enum WaitForSignalError", "fn wait_for_sigterm", "fn sigterm_shutdown", "fn shutdown_token",
  "fn shutdown_token_with_drain", "fn shutdown_token_with_drain_signal", "fn install_shutdown_signal_handlers",
]

The tool is scripts/split_rust_module.py from #562 (not on main yet).

  • Regenerate: on main at b9fc395e0, run split_rust_module.py apply spec.toml && cargo fmt --all. This reproduces the first commit.
  • Proof: split_rust_module.py verify origin/main → regenerated and compared 6 files from 1 split parents: identical. verify derives the spec from the diff, regenerates the split from the merge base, and requires HEAD's Rust files to equal the rustfmt'd result byte for byte.
  • Edits inside moved text: 42 private items, fields or methods → pub(super). Each keeps the reach the item had: one module deeper, pub(super) reaches exactly the old module.

Observable changes

  • Log targets: 9 tracing events and 2 spans without an explicit target: now log under the new module paths (pplx_space_common_svc::bootstrap::<module> instead of pplx_space_common_svc::bootstrap). Nothing in the repository selects on these targets exactly.

  • Request spans: the grpc.server and http.server request spans every server opens are created in bootstrap/grpc_trace.rs and bootstrap/http_trace.rs; their names and fields are unchanged, only their callsite metadata.

  • Comments: two Kind chart templates (space-runtime-manager-local's daemonset and space-node-service's _helpers.tpl) cited bootstrap.rs for socket replacement by rename; a docs commit points both at bootstrap/unix_socket.rs.

  • Diagnostics name new locations:

    • panic and backtrace locations of the 1 panic site (expect, unwrap, unreachable!, asserts) in moved code name the new file and line;
    • the 18 tracing callsites in moved code report the new file and line in their metadata, including OpenTelemetry's code.filepath, code.lineno and code.namespace;
    • std::any::type_name of a moved type names its new module;

    The reviews found nothing in the repository that depends on these.

Validation

Run on a Linux development machine at the PR head:

  • cargo check --workspace --all-targets --all-features --locked: pass.
  • Every clippy invocation in run_clippy_checks with -D warnings, including the common-svc --no-default-features run: pass.
  • cargo nextest run -p pplx-space-common-svc --all-features with Postgres and SPACE_CI_REQUIRE_TEST_DEPS=1: 278/278 passed, none skipped. The existing bootstrap/tests.rs calls the moved private helpers through the parent's re-exports, unchanged. No tests of this package are in the privileged group.
  • cargo test --doc -p pplx-space-common-svc: 48/48 passed.
  • archcheck as CI runs it: no required findings. The only new advisory finding is the stale file_size entry below.
  • Nearly every service depends on this crate, so the workspace check is the main evidence that bootstrap::X and the crate-root re-exports still resolve.

Interactions

No open pull request touches bootstrap.rs.

Follow-ups, kept out of this PR because verify allows no other Rust edits: imports in bootstrap.rs that only the child modules use could move to them; and a comment in peer_auth.rs that already named a non-existent GrpcServerMakeSpan before this PR.

The archcheck file_size baseline entry for this file is now stale (an advisory finding). Split PRs leave that table alone, so they don't conflict with each other there; one follow-up prunes the stale entries after they land.

Rollback

Revert the commit(s). No data, configuration, wire or public API change.

🤖 Generated with Claude Code

bootstrap.rs collects five unrelated facilities that services use at
startup: gRPC request parameter recording and logging, Unix socket binding, the
HTTP trace layer, the gRPC trace layer and shutdown signal handling.
Keep the gRPC server builder and health service in bootstrap.rs and
move each facility into its own child module: grpc_request_params,
unix_socket, http_trace, grpc_trace and shutdown.

Generated by scripts/split_rust_module.py (#562) from the spec in the
pull request. Items move verbatim. The only edits keep each item's
reach: 42 private items, fields or methods become pub(super). The parent
re-exports the moved items, so no caller changes.
Two chart comments cite bootstrap.rs for replacing a node-local socket
by rename. That code now lives in bootstrap/unix_socket.rs.
@ac-pplx
ac-pplx force-pushed the ac/split-common-svc-bootstrap branch from e4a801a to cef5cb4 Compare October 16, 2026 06:47
@ac-pplx
ac-pplx marked this pull request as ready for review October 16, 2026 14:49
@the-gigi-pplx

Copy link
Copy Markdown
Collaborator

Review

No findings.

Verified against cef5cb4a79d60bd67d044d92887ebe450100b54c.

What I ran:

  • scripts/split_rust_module.py verify origin/main, using the script from PR scripts: add split_rust_module.py for mechanical, verifiable Rust module splits #562's head: identical, exit 0.
  • apply with the spec in this PR's body, run on the merge base and rustfmt'd: it reproduces every .rs file at the head byte for byte. So the glob patterns in the published spec select the same items as the expanded spec verify --print-spec derives.
  • Each moved child file, grepped for self::/super:: in doc comments. The tool doesn't rewrite comments, so a link like that would point one module off after the move. There are none.
  • The non-split files, grepped for comments that name the old file next to a moved item.
  • Whether main has touched the split file since the merge base: it hasn't.

The non-Rust edits check out: the rename-based socket replacement is at bootstrap/unix_socket.rs:211.

What I didn't check: whether the grouping is the right one. That's a design call, and I took the body's word for it. I also didn't rebuild or retest the crate; CI is green on this head.

@the-gigi-pplx the-gigi-pplx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved. No findings; details in the review comment above.

@ac-pplx
ac-pplx added this pull request to the merge queue Oct 16, 2026
Merged via the queue into main with commit 4461c22 Oct 16, 2026
25 checks passed
@ac-pplx
ac-pplx deleted the ac/split-common-svc-bootstrap branch October 16, 2026 16:41
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.

2 participants