Skip to content

perf(fabric): stop rebuilding fabric-manager clients for every call#3256

Open
chet wants to merge 1 commit into
NVIDIA:mainfrom
chet:gh-issue-3212
Open

perf(fabric): stop rebuilding fabric-manager clients for every call#3256
chet wants to merge 1 commit into
NVIDIA:mainfrom
chet:gh-issue-3212

Conversation

@chet

@chet chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Every operation against a fabric manager built a complete client from scratch: fetch credentials from the secret store, read TLS certificates off disk, open a fresh TCP+TLS connection, make one call, throw it all away. On a busy fabric that meant a few hundred client builds per monitor pass -- three per fabric plus one per port change -- and the NVLink manager reconnected to every chassis on every tick, which drops to once per second while changes are pending. The partition controller built a client on every reconcile whether or not the state arm talks to UFM at all.

The goal is to build a client once and use it for everything it's needed for. A fabric's UFM client is now cached for the life of the process and rebuilt only when its credentials -- or its endpoint -- change: every pass still reads each fabric's credentials from the secret manager, so rotations are picked up promptly, while the per-pass memo keeps that to one read per fabric and shares the client across the health check, the reads, and every port change the pass makes. A client that lives across passes keeps its connections warm in its own pool, so a steady-state pass builds nothing and re-handshakes nothing. NMX-C channels are cached per endpoint across ticks and rebuilt when the TLS material on disk changes -- the same staleness policy the repo's gRPC clients use -- while dropped connections heal on their own. The partition controller connects only in the arms that actually query UFM, so a secrets hiccup no longer fails reconciles that never needed the fabric manager.

  • ib-fabric: one client per fabric, cached across monitor passes and rebuilt only on a credential or endpoint change; within a pass it is shared across the health check, port and partition reads, and port changes.
  • ib-partition-controller: connect (and read the manager config) only where the work uses them.
  • libnmxc: per-endpoint channel cache with a file-mtime staleness check on the TLS material.

Counting tests pin the build counts: a full fabric pass builds exactly one client (was three plus one per port change), partition arms that skip UFM build none, one connect serves a cached endpoint, and rotating the certificate on disk triggers a rebuild. The client cache has its own contracts under test: while credentials are unchanged every call returns the same client, a rotated credential rebuilds it, and each fabric holds a separate entry.

This supports #3212

@chet chet requested a review from a team as a code owner July 8, 2026 16:39
@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@chet, you're welcome! I'll perform a full review of all changes in this PR now.

🐇✨

✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary by CodeRabbit

  • New Features

    • Improved reuse of connection and client resources across fabric operations, reducing repeated setup during monitoring and changes.
    • Added better handling for changing credentials and TLS materials, so updated settings are picked up automatically.
  • Bug Fixes

    • Fixed cases where clients were created more often than needed during status checks and updates.
    • Improved stability when cached connections become invalid or when locks are interrupted.
  • Tests

    • Expanded automated coverage for client reuse, cache refresh, and controller behavior across common states.

Walkthrough

This PR adds IB fabric test support, reuses IB fabric clients in the monitor and REST manager, defers partition-controller fabric connections until needed, and refactors NMXC client pooling around endpoint caches with TLS staleness checks.

Changes

Connection reuse across IB fabric, partition controller, and NMXC

Layer / File(s) Summary
IB fabric test support
crates/ib-fabric/Cargo.toml, crates/ib-fabric/src/ib/mod.rs, crates/ib-fabric/src/ib/fakes.rs
Enables test-support, exposes fakes, and adds stub fabric and counting manager test helpers.
IB fabric REST client cache
crates/ib-fabric/src/ib/mod.rs
Adds fingerprint-based REST client caching, poisoned-lock recovery, and tests for credential and fabric changes.
IB fabric monitor client reuse
crates/ib-fabric/src/lib.rs
Reuses one per-fabric IB client across monitoring and apply phases, with refactored data loading and reuse tests.
Partition controller fabric connection
crates/ib-partition-controller/Cargo.toml, crates/ib-partition-controller/src/handler.rs
Adds test dependencies, defers fabric client creation into state branches, and validates client build counts in handler tests.
NMXC channel cache
crates/libnmxc/Cargo.toml, crates/libnmxc/src/lib.rs
Refactors client pooling into a connector-backed endpoint cache with TLS staleness checks and cache tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main performance change: reusing fabric-manager clients instead of rebuilding them every call.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the caching, reconnect, and test updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
crates/ib-partition-controller/src/handler.rs (1)

287-543: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing test for the Ready + active (not-deleted) path.

The test suite exercises Provisioning, Error, Ready (marked-deleted), and Deleting (live network), but never the Ready branch's "not marked as deleted" sub-branch (Lines 162-243) — the second call site of connect_ib_fabric. That's the primary QoS-reconciliation path this PR touches; a regression there (e.g., accidentally building an extra client, or skipping the connect) wouldn't be caught.

✅ Suggested additional test
+    #[tokio::test]
+    async fn ready_active_builds_one_ufm_client() {
+        let (builds, outcome) = run_handler(
+            IBPartitionControllerState::Ready,
+            make_partition(Some(0x101), false),
+        )
+        .await;
+
+        assert!(outcome.is_ok());
+        assert_eq!(builds, 1, "the arm that queries UFM for QoS builds one client");
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-partition-controller/src/handler.rs` around lines 287 - 543, Add a
test covering the Ready state when the partition is not deleted, since this is
the untested QoS-reconciliation path in
IBPartitionStateHandler::handle_object_state. Reuse the existing test helpers
(make_partition, run_handler, CountingFabricManager, StubIBFabric) and assert
the Ready/non-deleted branch transitions as expected while exercising the second
connect_ib_fabric call site. Also verify the client build count matches the
intended behavior so a regression in client creation or skipping the connect is
caught.
crates/libnmxc/src/lib.rs (1)

277-422: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider collapsing the fifteen delegating RPC methods into a declarative macro.

Every Nmxc method here follows an identical three-line contract: invoke self.inner, feed the result through note_result, then return it. Beyond the ~140 lines of ceremony, the pattern is load-bearing — a future method added to the Nmxc trait that omits the note_result call would silently disable transport-error eviction for that RPC, with no compile-time signal. A small macro_rules! makes the delegation uniform and self-enforcing.

♻️ Illustrative delegation macro
macro_rules! delegate_with_eviction {
    ($( async fn $name:ident(&mut self $(, $arg:ident: $ty:ty)*) -> $ret:ty; )*) => {
        $(
            async fn $name(&mut self $(, $arg: $ty)*) -> $ret {
                let result = self.inner.$name($($arg),*).await;
                self.note_result(&result);
                result
            }
        )*
    };
}

#[async_trait::async_trait]
impl Nmxc for PooledNmxc {
    delegate_with_eviction! {
        async fn hello(&mut self, gateway_id: &str) -> Result<nmxc_model::ServerHello, NmxcError>;
        async fn get_domain_properties(&mut self, context: Option<nmxc_model::Context>, gateway_id: &str) -> Result<nmxc_model::DomainProperties, NmxcError>;
        // ... remaining RPCs ...
    }
}

Please confirm the macro expands cleanly through #[async_trait::async_trait] in this toolchain before adopting it, as the attribute macro rewrites the method signatures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libnmxc/src/lib.rs` around lines 277 - 422, The `impl Nmxc for
PooledNmxc` block repeats the same delegate-and-evict pattern across every RPC
method, so replace the manual boilerplate with a `macro_rules!` helper that
expands each method to call `self.inner.<method>`, pass the `Result` through
`note_result`, and return it. Keep the macro definition close to `PooledNmxc` so
it can cover all the `Nmxc` trait methods consistently, and verify it works
cleanly with `#[async_trait::async_trait]` before wiring the existing methods
through the macro.

Source: Path instructions

crates/ib-fabric/src/lib.rs (1)

614-676: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Emit these log sites as structured fields rather than interpolated strings.

fabric, guid, pkey, and the error are interpolated into the message across Lines 614, 618, 632 and 674-676, which defeats logfmt-based filtering. Promote them to attributes so operators can query by fabric/pkey.

As per coding guidelines: "prefer placing common fields as attributes passed to tracing functions instead of using string interpolation" (e.g. tracing::error!(%fabric, %pkey, error=%e, "...")).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-fabric/src/lib.rs` around lines 614 - 676, The bind/unbind logging
in the ib-fabric flow is using interpolated strings instead of structured
tracing fields, which makes `fabric`, `guid`, `pkey`, and the error harder to
filter. Update the `client_for_fabric` bind and unbind paths in the
report-processing loop to pass these values as tracing attributes on the
`tracing::error!`/`warn!` calls rather than embedding them in the message. Keep
the human-readable message short, and expose the key values via fields like
`%fabric`, `%guid`, `%pkey`, and `error=%e` so logfmt-based querying works
reliably.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ib-fabric/src/lib.rs`:
- Around line 384-391: The error branch in the client-creation path is logging
the wrong operation name: in the match on fabric_manager.new_client(...),
replace the "IB fabric health check failed" message with one that clearly
identifies the new_client/client-construction failure, while keeping the same
fabric, endpoints, and error fields. Use the unique symbols
fabric_manager.new_client and fabric_metrics.fabric_error to locate the branch,
and leave the actual health-check failure log elsewhere unchanged.

---

Nitpick comments:
In `@crates/ib-fabric/src/lib.rs`:
- Around line 614-676: The bind/unbind logging in the ib-fabric flow is using
interpolated strings instead of structured tracing fields, which makes `fabric`,
`guid`, `pkey`, and the error harder to filter. Update the `client_for_fabric`
bind and unbind paths in the report-processing loop to pass these values as
tracing attributes on the `tracing::error!`/`warn!` calls rather than embedding
them in the message. Keep the human-readable message short, and expose the key
values via fields like `%fabric`, `%guid`, `%pkey`, and `error=%e` so
logfmt-based querying works reliably.

In `@crates/ib-partition-controller/src/handler.rs`:
- Around line 287-543: Add a test covering the Ready state when the partition is
not deleted, since this is the untested QoS-reconciliation path in
IBPartitionStateHandler::handle_object_state. Reuse the existing test helpers
(make_partition, run_handler, CountingFabricManager, StubIBFabric) and assert
the Ready/non-deleted branch transitions as expected while exercising the second
connect_ib_fabric call site. Also verify the client build count matches the
intended behavior so a regression in client creation or skipping the connect is
caught.

In `@crates/libnmxc/src/lib.rs`:
- Around line 277-422: The `impl Nmxc for PooledNmxc` block repeats the same
delegate-and-evict pattern across every RPC method, so replace the manual
boilerplate with a `macro_rules!` helper that expands each method to call
`self.inner.<method>`, pass the `Result` through `note_result`, and return it.
Keep the macro definition close to `PooledNmxc` so it can cover all the `Nmxc`
trait methods consistently, and verify it works cleanly with
`#[async_trait::async_trait]` before wiring the existing methods through the
macro.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 36f3813f-6eb3-4e9a-9c29-77805ef40c13

📥 Commits

Reviewing files that changed from the base of the PR and between f5bf35d and 447fa85.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/src/lib.rs

Comment thread crates/ib-fabric/src/lib.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
crates/ib-partition-controller/src/handler.rs (1)

287-543: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing positive-path test for the Ready branch's UFM build count.

The test suite verifies exactly one client build for Deleting with a live network (Line 533-542), but the symmetric Ready (pkey present, not marked deleted) success path — which also calls connect_ib_fabric and additionally reuses the client for update_partition_qos_conf — has no equivalent build-count assertion. Only the early-exit "marked deleted" Ready case is tested for 0 builds. Given this branch is central to this PR's "single client reused across query + update" change, a positive test would close the loop.

🧪 Suggested additional test
+    #[tokio::test]
+    async fn ready_with_pkey_builds_one_ufm_client_and_reuses_it() {
+        let (builds, outcome) = run_handler(
+            IBPartitionControllerState::Ready,
+            make_partition(Some(0x101), false),
+        )
+        .await;
+
+        assert!(matches!(outcome, Ok(StateHandlerOutcome::DoNothing { .. })));
+        assert_eq!(
+            builds, 1,
+            "the Ready arm builds one client and reuses it for get_ib_network + update_partition_qos_conf"
+        );
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-partition-controller/src/handler.rs` around lines 287 - 543, The
test coverage is missing the positive-path assertion for the Ready branch where
a live partition should build exactly one UFM client and reuse it for both
connect and update. Add a new test alongside provisioning_builds_no_ufm_client
and deleting_with_live_network_builds_one_ufm_client that drives
IBPartitionStateHandler::handle_object_state through
IBPartitionControllerState::Ready with make_partition(Some(...), false), and
assert the outcome is the expected transition while
CountingFabricManager::build_count() is 1. Use run_handler, make_partition, and
IBPartitionStateHandler as the key entry points.
crates/libnmxc/src/lib.rs (1)

222-229: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Coalesce concurrent cache misses per endpoint.

Two concurrent create_client calls for the same uncached URI can both miss, both connect, and then race to insert. That preserves correctness, but it weakens the PR’s connection-reuse goal under concurrent callers. Consider caching an in-flight per-URI initialization, e.g. a OnceCell<Channel> entry, so concurrent misses share the same connect attempt.

Potential direction
-type ChannelCache = Arc<Mutex<HashMap<String, Channel>>>;
+type ChannelCache = Arc<Mutex<HashMap<String, Arc<tokio::sync::OnceCell<Channel>>>>>;

 async fn channel_for(&self, endpoint: &Endpoint, uri: &str) -> Result<Channel, NmxcError> {
-    if let Some(channel) = lock_channels(&self.channels).get(uri) {
-        return Ok(channel.clone());
-    }
-
-    let channel = self.connector.connect(endpoint).await?;
-    lock_channels(&self.channels).insert(uri.to_string(), channel.clone());
-    Ok(channel)
+    let cell = {
+        let mut channels = lock_channels(&self.channels);
+        Arc::clone(
+            channels
+                .entry(uri.to_string())
+                .or_insert_with(|| Arc::new(tokio::sync::OnceCell::new())),
+        )
+    };
+
+    cell.get_or_try_init(|| async { self.connector.connect(endpoint).await })
+        .await
+        .cloned()
 }

As per path instructions, crates/**/*.rs reviews should prioritize behavior, concurrency, resource lifetimes, and missing tests over style-only comments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libnmxc/src/lib.rs` around lines 222 - 229, The channel cache in
channel_for still allows concurrent uncached lookups for the same URI to race,
so multiple create_client calls can perform duplicate connector.connect attempts
before insert. Change the per-URI caching in channel_for (and the channels map
used by create_client) to store an in-flight initialization, such as a OnceCell
or similar shared async entry, so the first caller performs the connect and all
concurrent callers await the same result. Update the cache insertion/retrieval
logic to reuse that shared initialization path and add a concurrency-focused
test covering simultaneous create_client calls for the same endpoint/URI.

Source: Path instructions

crates/ib-fabric/src/lib.rs (1)

614-675: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use structured tracing fields for the new apply-path logs.

The new warn/error logs interpolate fabric, guid, pkey, and error into message strings, making logfmt querying harder.

Suggested logfmt-friendly rewrite
-                tracing::warn!("Missing pkey {pkey} does not map to a Partition ID");
+                tracing::warn!(%pkey, "Missing pkey does not map to a Partition ID");
@@
-                tracing::warn!("Missing pkey {pkey} does not map to a Partition");
+                tracing::warn!(%pkey, "Missing pkey does not map to a Partition");
@@
-                    tracing::error!("Failed to bind {guid} to pkey {pkey} on fabric {fabric}: {e}");
+                    tracing::error!(
+                        %fabric,
+                        %guid,
+                        %pkey,
+                        error = %e,
+                        "Failed to bind GUID to pkey"
+                    );
@@
-                    tracing::error!(
-                        "Failed to unbind {guid} from pkey {pkey} on fabric {fabric}: {e}"
-                    );
+                    tracing::error!(
+                        %fabric,
+                        %guid,
+                        %pkey,
+                        error = %e,
+                        "Failed to unbind GUID from pkey"
+                    );

As per coding guidelines, “For Rust logging, use plain tracing:: macros with structured fields for ordinary log messages.” As per path instructions, review Rust code against STYLE_GUIDE.md, including structured tracing fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-fabric/src/lib.rs` around lines 614 - 675, The new apply-path logs
in the bind/unbind flow should use structured tracing fields instead of
interpolated strings. Update the `tracing::warn!` and `tracing::error!` calls in
the `bind_ib_ports` and `unbind_ib_ports` paths to pass `fabric`, `guid`,
`pkey`, and the error as named fields with a static message, so the logs remain
queryable in logfmt. Keep the existing control flow and status handling in
`apply`/the surrounding loop, just change the logging style to match the Rust
tracing conventions used elsewhere.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/libnmxc/src/lib.rs`:
- Around line 638-647: The refused_endpoint helper in lib.rs is flaky because it
drops the TcpListener before the test uses the URI, allowing the port to be
rebound and the transport error to disappear. Update refused_endpoint (or the
related hello() test setup) to use a deterministic failure path, such as a local
accept-and-close listener whose task is awaited, or a test double that forces
PooledNmxc::note_result to observe a transport error. Keep the endpoint-building
logic in refused_endpoint, but ensure the failure mode cannot race with the
caller.

---

Nitpick comments:
In `@crates/ib-fabric/src/lib.rs`:
- Around line 614-675: The new apply-path logs in the bind/unbind flow should
use structured tracing fields instead of interpolated strings. Update the
`tracing::warn!` and `tracing::error!` calls in the `bind_ib_ports` and
`unbind_ib_ports` paths to pass `fabric`, `guid`, `pkey`, and the error as named
fields with a static message, so the logs remain queryable in logfmt. Keep the
existing control flow and status handling in `apply`/the surrounding loop, just
change the logging style to match the Rust tracing conventions used elsewhere.

In `@crates/ib-partition-controller/src/handler.rs`:
- Around line 287-543: The test coverage is missing the positive-path assertion
for the Ready branch where a live partition should build exactly one UFM client
and reuse it for both connect and update. Add a new test alongside
provisioning_builds_no_ufm_client and
deleting_with_live_network_builds_one_ufm_client that drives
IBPartitionStateHandler::handle_object_state through
IBPartitionControllerState::Ready with make_partition(Some(...), false), and
assert the outcome is the expected transition while
CountingFabricManager::build_count() is 1. Use run_handler, make_partition, and
IBPartitionStateHandler as the key entry points.

In `@crates/libnmxc/src/lib.rs`:
- Around line 222-229: The channel cache in channel_for still allows concurrent
uncached lookups for the same URI to race, so multiple create_client calls can
perform duplicate connector.connect attempts before insert. Change the per-URI
caching in channel_for (and the channels map used by create_client) to store an
in-flight initialization, such as a OnceCell or similar shared async entry, so
the first caller performs the connect and all concurrent callers await the same
result. Update the cache insertion/retrieval logic to reuse that shared
initialization path and add a concurrency-focused test covering simultaneous
create_client calls for the same endpoint/URI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 62651a40-0b71-4dc5-9ea6-fa51fdbc6313

📥 Commits

Reviewing files that changed from the base of the PR and between f5bf35d and 447fa85.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/src/lib.rs

Comment thread crates/libnmxc/src/lib.rs Outdated
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
boot-artifacts-aarch64 3 0 0 3 0 0
boot-artifacts-x86_64 3 0 0 3 0 0
forge-admin-cli-x86_64 271 13 34 91 7 126
machine-validation-runner 776 37 223 281 40 195
machine_validation 776 37 223 281 40 195
machine_validation-aarch64 776 37 223 281 40 195
nvmetal-carbide 776 37 223 281 40 195
TOTAL 3381 161 926 1221 167 906

Per-CVE detail lives in the per-service grype-* artifacts (JSON + SARIF). Severity counts only — no CVE IDs published here.

@chet chet force-pushed the gh-issue-3212 branch from 447fa85 to 1b9290e Compare July 8, 2026 18:20
@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@chet, sounds good — kicking off a fresh full review of all changes in this PR now.

🐇✨

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/libnmxc/src/lib.rs (1)

256-274: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Concurrent cache misses on the same endpoint can trigger duplicate connects.

channel_for reads the cache, drops the lock, then connects and re-acquires the lock to insert — there is no per-endpoint synchronization across that window. Two concurrent create_client calls for the same uncached (or just-evicted) endpoint will both miss the cache, both call self.connector.connect(...), and the loser's channel is silently discarded when the winner's insert overwrites it. Functionally harmless (the discarded channel just gets dropped), but it undercuts the PR's stated goal of building at most one client per fabric per pass, especially in the eviction path where a rotation could briefly cause a connect storm from multiple waiting callers.

Consider guarding the connect-and-insert path with a per-endpoint lock (e.g., an Entry-style API using tokio::sync::OnceCell per URI, or a dedicated tokio::sync::Mutex per endpoint) so concurrent callers for the same endpoint await one connect instead of racing.

♻️ Sketch: single-flight per-endpoint connect
-type ChannelCache = Arc<Mutex<HashMap<String, (Channel, SystemTime)>>>;
+type ChannelCache = Arc<Mutex<HashMap<String, Arc<tokio::sync::OnceCell<(Channel, SystemTime)>>>>>;

The exact shape depends on how staleness re-checks should interact with the single-flight cell, but the key idea is: reserve the cache slot before connecting, so concurrent callers await the same in-flight connect instead of each starting their own.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libnmxc/src/lib.rs` around lines 256 - 274, `channel_for` currently
releases the cache lock before calling `self.connector.connect`, so concurrent
callers for the same URI can both miss and race to create duplicate channels.
Update the caching flow in `channel_for` (and the
`self.channels`/`lock_channels` access pattern) to use per-URI single-flight
synchronization so only one connect runs for a given endpoint while others await
it. Preserve the existing stale-entry recheck and eviction behavior, but ensure
the connect-and-insert path is guarded by a per-endpoint lock or
`OnceCell`-style in-flight entry rather than a read-then-connect race.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/libnmxc/src/lib.rs`:
- Around line 256-274: `channel_for` currently releases the cache lock before
calling `self.connector.connect`, so concurrent callers for the same URI can
both miss and race to create duplicate channels. Update the caching flow in
`channel_for` (and the `self.channels`/`lock_channels` access pattern) to use
per-URI single-flight synchronization so only one connect runs for a given
endpoint while others await it. Preserve the existing stale-entry recheck and
eviction behavior, but ensure the connect-and-insert path is guarded by a
per-endpoint lock or `OnceCell`-style in-flight entry rather than a
read-then-connect race.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 63c4b91f-1c98-44d9-b36a-86a4c78b0d63

📥 Commits

Reviewing files that changed from the base of the PR and between 447fa85 and 1b9290e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/Cargo.toml
  • crates/libnmxc/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/src/handler.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/ib-fabric/src/lib.rs (1)

639-717: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the shared bind/unbind change-recording logic.

The missing_guid_pkeys and unexpected_guid_pkeys loops duplicate the same shape (get client, invoke operation, map status, record metrics.applied_changes) apart from the specific IBFabric call and UfmOperation variant. A small helper taking the operation as a closure/enum could remove this duplication.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-fabric/src/lib.rs` around lines 639 - 717, The bind and unbind
loops in the report handling code duplicate the same client lookup, operation
execution, status mapping, and metrics recording flow. Extract that shared logic
into a small helper in this area of ib-fabric::lib (near the report-processing
loops), and pass in the specific IBFabric call and UfmOperation variant as
parameters or a closure so only the bind/unbind-specific parts differ. Keep the
existing tracing and AppliedChange recording behavior intact, but centralize the
common change-recording path to avoid maintaining two nearly identical branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ib-fabric/src/lib.rs`:
- Line 642: The tracing calls in this area are interpolating values like pkey,
guid, fabric, and e directly into the message instead of emitting them as
structured fields. Update the relevant tracing::warn! and tracing::error! sites
in lib.rs, including the Partition ID lookup and related error paths, to pass
these values as attributes on the tracing macros so they can be filtered and
aggregated by key. Keep the human-readable message short and move the variable
data into fields, using the existing symbols around the affected logging calls.
- Around line 639-663: The batch processing in apply_guid_pkey_changes is
aborting on a single fabric client creation failure because
client_for_fabric(...).await? propagates the error instead of handling it per
fabric. Change both the bind and unbind paths to catch client_for_fabric errors
locally, log the failure, record an error status if needed, and continue to the
next fabric/report just like the existing bind_ib_ports and unbind_ib_ports
error handling does.

---

Nitpick comments:
In `@crates/ib-fabric/src/lib.rs`:
- Around line 639-717: The bind and unbind loops in the report handling code
duplicate the same client lookup, operation execution, status mapping, and
metrics recording flow. Extract that shared logic into a small helper in this
area of ib-fabric::lib (near the report-processing loops), and pass in the
specific IBFabric call and UfmOperation variant as parameters or a closure so
only the bind/unbind-specific parts differ. Keep the existing tracing and
AppliedChange recording behavior intact, but centralize the common
change-recording path to avoid maintaining two nearly identical branches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e69f10cc-a8a9-423d-b503-9dddf0a8da19

📥 Commits

Reviewing files that changed from the base of the PR and between f884199 and 1b9290e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/Cargo.toml
  • crates/libnmxc/src/lib.rs

Comment thread crates/ib-fabric/src/lib.rs
Comment thread crates/ib-fabric/src/lib.rs Outdated
@chet chet force-pushed the gh-issue-3212 branch from 1b9290e to 9fd5708 Compare July 8, 2026 19:53
@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@chet, got it — kicking off another full review of all changes in this PR now.

🐇✨

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
crates/ib-fabric/src/ib/fakes.rs (1)

70-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

StubIBFabric::get_ib_network can't exercise the Ready-arm QoS-update reuse path.

This stub always returns qos_conf: None. In ib-partition-controller/src/handler.rs, the Ready (not-deleted) arm does ibnetwork.qos_conf.as_ref().ok_or_else(...)? immediately after calling get_ib_network — with this fake it will always short-circuit into the MissingData error, never reaching the QoS-comparison/update_partition_qos_conf call. As a result, the handler's own reuse claim (one connect_ib_fabric() client serving both get_ib_network and update_partition_qos_conf) has no test coverage; the four new handler.rs tests only cover Provisioning, Error, Ready+deleted, and Deleting.

Consider returning a populated qos_conf: Some(IBQosConf::default()) (or accepting it as a make_partition-style parameter) so a Ready-arm test can assert build_count() == 1 across both UFM calls.

🧪 Sketch of the fix
     async fn get_ib_network(
         &self,
         pkey: u16,
         _options: GetPartitionOptions,
     ) -> Result<IBNetwork, IbError> {
         Ok(IBNetwork {
             name: "stub".to_string(),
             pkey,
             ipoib: false,
-            qos_conf: None,
+            qos_conf: Some(IBQosConf {
+                mtu: IBMtu::default(),
+                rate_limit: IBRateLimit::default(),
+                service_level: IBServiceLevel::default(),
+            }),
             associated_guids: Some(HashSet::new()),
             membership: None,
         })
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-fabric/src/ib/fakes.rs` around lines 70 - 83, The
StubIBFabric::get_ib_network fake always returns qos_conf as None, which
prevents the Ready arm in ib-partition-controller/src/handler.rs from reaching
the QoS comparison and update_partition_qos_conf path. Update
StubIBFabric::get_ib_network in ib/fakes.rs so it can return a populated QoS
config (for example a default IBQosConf, or make it configurable like
make_partition) while keeping the other fields intact. This will let a
Ready-state handler test exercise the reuse path and verify the single-client
behavior across get_ib_network and update_partition_qos_conf, including
build_count() == 1.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/libnmxc/src/lib.rs`:
- Around line 119-146: `NmxcTlsConfig::material_newer_than` is doing synchronous
filesystem metadata checks on the async hot path. Update this stale-check logic
to avoid blocking the executor by switching to an async-safe approach such as
`tokio::fs::metadata` or moving the sync work into `spawn_blocking`, and make
sure the call path from `is_stale`/`channel_for` and `create_client` uses that
async flow consistently with `build_https_tls_config`. Keep the existing
behavior and logging, but ensure the TLS-material freshness check no longer
performs `std::fs::metadata(...).modified()` directly during cache hits.
- Around line 256-274: The channel_for cache path currently releases the
channels lock before awaiting connector.connect, which allows concurrent
create_client calls for the same URI to race and duplicate TLS handshakes.
Update channel_for in crates/libnmxc/src/lib.rs to serialize in-flight connects
per URI by introducing a per-URI shared in-progress state (such as a OnceCell or
shared future) so cache misses and stale-entry rebuilds reuse the same connect
work instead of creating multiple channels. Keep the existing cache behavior
around Channel, created timestamps, and stale eviction, but ensure only one
connect runs per URI at a time.

---

Nitpick comments:
In `@crates/ib-fabric/src/ib/fakes.rs`:
- Around line 70-83: The StubIBFabric::get_ib_network fake always returns
qos_conf as None, which prevents the Ready arm in
ib-partition-controller/src/handler.rs from reaching the QoS comparison and
update_partition_qos_conf path. Update StubIBFabric::get_ib_network in
ib/fakes.rs so it can return a populated QoS config (for example a default
IBQosConf, or make it configurable like make_partition) while keeping the other
fields intact. This will let a Ready-state handler test exercise the reuse path
and verify the single-client behavior across get_ib_network and
update_partition_qos_conf, including build_count() == 1.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 412b93cc-cb94-414b-9135-7a395d31fd18

📥 Commits

Reviewing files that changed from the base of the PR and between 13b4f13 and 9fd5708.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/Cargo.toml
  • crates/libnmxc/src/lib.rs

Comment thread crates/libnmxc/src/lib.rs
Comment thread crates/libnmxc/src/lib.rs
@chet chet force-pushed the gh-issue-3212 branch from 9fd5708 to 02efec2 Compare July 8, 2026 21:42
@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@chet, got it — kicking off another full review of all changes in this PR now.

🐇✨

✅ Action performed

Full review finished.

@Matthias247

Copy link
Copy Markdown
Contributor

I think we just need one client ("channel") for the whole application. Auth is credentials that can be passed to each request, so maybe you'd want to have a wrapper of (http_client, credentials), but the client itself shouldn't need to get rebuilt.

That is unless we'd do mTLS and there is a different client cert per UFM endpoint we are talking to, but I don't think that's the case.

@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

I think we just need one client ("channel") for the whole application. Auth is credentials that can be passed to each request, so maybe you'd want to have a wrapper of (http_client, credentials), but the client itself shouldn't need to get rebuilt.

That is unless we'd do mTLS and there is a different client cert per UFM endpoint we are talking to, but I don't think that's the case.

@Matthias247 Yeah I like it. Updated!

The client is now used for the life of the application (one per fabric, since each fabric can have its own manager), and [only] gets rebuilt when its credentials (or endpoint) actually change; it reads the credentials from the secret manager each pass so rotations get picked up.

There are also a few tests for the behavior too (same creds → same client, rotated creds → rebuilt, etc).

Every operation against a fabric manager built a complete client from scratch: fetch credentials from the secret store, read TLS certificates off disk, open a fresh TCP+TLS connection, make one call, throw it all away. On a busy fabric that meant a few hundred client builds per monitor pass -- three per fabric plus one per port change -- and the NVLink manager reconnected to every chassis on every tick, which drops to once per second while changes are pending. The partition controller built a client on every reconcile whether or not the state arm talks to UFM at all.

The goal is to build a client once and use it for everything it's needed for. A fabric's UFM client is now cached for the life of the process and rebuilt only when its credentials -- or its endpoint -- change: every pass still reads each fabric's credentials from the secret manager, so rotations are picked up promptly, while the per-pass memo keeps that to one read per fabric and shares the client across the health check, the reads, and every port change the pass makes. A client that lives across passes keeps its connections warm in its own pool, so a steady-state pass builds nothing and re-handshakes nothing. NMX-C channels are cached per endpoint across ticks and rebuilt when the TLS material on disk changes -- the same staleness policy the repo's gRPC clients use -- while dropped connections heal on their own. The partition controller connects only in the arms that actually query UFM, so a secrets hiccup no longer fails reconciles that never needed the fabric manager.

- `ib-fabric`: one client per fabric, cached across monitor passes and rebuilt only on a credential or endpoint change; within a pass it is shared across the health check, port and partition reads, and port changes.
- `ib-partition-controller`: connect (and read the manager config) only where the work uses them.
- `libnmxc`: per-endpoint channel cache with a file-mtime staleness check on the TLS material.

Counting tests pin the build counts: a full fabric pass builds exactly one client (was three plus one per port change), partition arms that skip UFM build none, one connect serves a cached endpoint, and rotating the certificate on disk triggers a rebuild. The client cache has its own contracts under test: while credentials are unchanged every call returns the same client, a rotated credential rebuilds it, and each fabric holds a separate entry.

This supports NVIDIA#3212

Signed-off-by: Chet Nichols III <chetn@nvidia.com>
@chet chet force-pushed the gh-issue-3212 branch from 02efec2 to fa26d26 Compare July 8, 2026 22:49
@chet

chet commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full_review, thanks!

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

@chet, got it — kicking off another full review of all changes in this PR now.

🐇✨

✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/ib-fabric/src/ib/mod.rs`:
- Around line 183-187: The concurrent build path for the fabric client is not
fully safe because an older in-flight build can overwrite a newer cached client
after credentials rotate. Update the client creation/cache insertion logic in
ib::mod so that the result is revalidated against the latest credentials
immediately before storing it, or serialize per-fabric builds to prevent stale
inserts. Also add a concurrent rotation test that exercises the new_client path
used by crates/api-core/src/handlers/ib_fabric.rs and verifies the newer
credentials win under overlap.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 33aa9ded-23ed-494b-89b5-05171dd29c0c

📥 Commits

Reviewing files that changed from the base of the PR and between 02efec2 and fa26d26.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/Cargo.toml
  • crates/libnmxc/src/lib.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/libnmxc/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (6)
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/lib.rs
  • crates/libnmxc/src/lib.rs
  • crates/ib-partition-controller/src/handler.rs

Comment thread crates/ib-fabric/src/ib/mod.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
crates/libnmxc/src/lib.rs (1)

119-148: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: collapse the redundant match in the freshness check.

The Err(e) => Err(e) arm is an identity mapping; the whole expression reduces to a single combinator, which reads more clearly.

♻️ Proposed simplification
-        for path in paths.into_iter().flatten() {
-            let modified = match tokio::fs::metadata(path).await {
-                Ok(metadata) => metadata.modified(),
-                Err(e) => Err(e),
-            };
-            if let Ok(mtime) = modified
+        for path in paths.into_iter().flatten() {
+            let modified = tokio::fs::metadata(path).await.and_then(|m| m.modified());
+            if let Ok(mtime) = modified
                 && mtime > created
             {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/libnmxc/src/lib.rs` around lines 119 - 148, The freshness check in
NmxcTlsConfig::material_newer_than has a redundant Err(e) => Err(e) arm that is
just an identity mapping. Simplify the tokio::fs::metadata(path).await handling
to use a single combinator or direct result propagation while keeping the
existing mtime comparison and tracing::info! behavior unchanged. Keep the logic
inside material_newer_than intact and only collapse the unnecessary match for
readability.
crates/ib-partition-controller/src/handler.rs (1)

143-248: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the Ready (not-deleted) lazy-build path.

Tests exist for every branch that builds zero clients, and for Deleting building one, but not for the Ready/not-deleted branch (Lines 160-165) — the other arm this layer changed to lazily connect. Worth closing the gap so a future regression (e.g. reintroducing an eager build, or dropping the lazy connect) is caught.

✅ Proposed test addition
#[tokio::test]
async fn ready_not_deleted_builds_one_ufm_client() {
    let (builds, outcome) = run_handler(
        IBPartitionControllerState::Ready,
        make_partition(Some(0x101), false),
    )
    .await;

    // StubIBFabric returns `qos_conf: None`, so this arm errors out on the
    // missing QoS data -- but the client must still be built exactly once.
    assert!(matches!(
        outcome,
        Err(StateHandlerError::MissingData { missing: "qos_conf", .. })
    ));
    assert_eq!(builds, 1, "the arm that queries UFM builds one client");
}

Also applies to: 338-399

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/ib-partition-controller/src/handler.rs` around lines 143 - 248, Add a
test that covers the Ready state when the partition is not marked as deleted,
since this is the lazy-connect path now handled in
IBPartitionControllerState::Ready. Use the existing handler test helpers around
run_handler and make_partition to assert that this branch still builds exactly
one UFM/IB fabric client, even if the call later returns MissingData for
qos_conf. This closes the gap alongside the Deleting and zero-client cases and
protects the Ready/not-deleted flow from regressions in connect_ib_fabric or the
Ready match arm.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/ib-partition-controller/src/handler.rs`:
- Around line 143-248: Add a test that covers the Ready state when the partition
is not marked as deleted, since this is the lazy-connect path now handled in
IBPartitionControllerState::Ready. Use the existing handler test helpers around
run_handler and make_partition to assert that this branch still builds exactly
one UFM/IB fabric client, even if the call later returns MissingData for
qos_conf. This closes the gap alongside the Deleting and zero-client cases and
protects the Ready/not-deleted flow from regressions in connect_ib_fabric or the
Ready match arm.

In `@crates/libnmxc/src/lib.rs`:
- Around line 119-148: The freshness check in NmxcTlsConfig::material_newer_than
has a redundant Err(e) => Err(e) arm that is just an identity mapping. Simplify
the tokio::fs::metadata(path).await handling to use a single combinator or
direct result propagation while keeping the existing mtime comparison and
tracing::info! behavior unchanged. Keep the logic inside material_newer_than
intact and only collapse the unnecessary match for readability.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e5c42bf1-408d-49e1-b655-711d1958e6da

📥 Commits

Reviewing files that changed from the base of the PR and between ae83827 and fa26d26.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • crates/ib-fabric/Cargo.toml
  • crates/ib-fabric/src/ib/fakes.rs
  • crates/ib-fabric/src/ib/mod.rs
  • crates/ib-fabric/src/lib.rs
  • crates/ib-partition-controller/Cargo.toml
  • crates/ib-partition-controller/src/handler.rs
  • crates/libnmxc/Cargo.toml
  • crates/libnmxc/src/lib.rs

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