Skip to content

[Nullable] Enable project nullability on Akka.Cluster.Metrics#8067

Open
MattKotsenas wants to merge 10 commits intoakkadotnet:devfrom
MattKotsenas:nullable/cluster-metrics
Open

[Nullable] Enable project nullability on Akka.Cluster.Metrics#8067
MattKotsenas wants to merge 10 commits intoakkadotnet:devfrom
MattKotsenas:nullable/cluster-metrics

Conversation

@MattKotsenas
Copy link
Contributor

Changes

Enable nullable project-wide for Akka.Cluster.Metrics. This is annotation-only - no behavioral changes, no new null guards. Two files (Metric.cs, NodeMetrics.cs) already had per-file #nullable enable; those directives are removed since the project-level setting now covers them.

Nullable annotation decisions

Marked nullable (these can genuinely be null):

Location Rationale
AdaptiveLoadBalancingRoutingLogic(metricsSelector?) Optional parameter, defaults to MixMetricsSelector.Instance via ??
AdaptiveLoadBalancingPool(metricsSelector?, supervisorStrategy?, routerDispatcher?) Optional parameters, all ??-coalesced to defaults in constructor body or base call
AdaptiveLoadBalancingGroup(metricsSelector?, paths?, routerDispatcher?) Same pattern. Group base constructor already handles null paths via paths?.ToArray() ?? Array.Empty<string>()
Resizer override Returns null - this pool does not support resizing
Process[]? processes in GetCpuUsages Initialized to null, assigned in try block, null-checked in finally
EWMA.Equals(EWMA?) / Equals(object?) Standard IEquatable<T> and object.Equals override signatures
All surrogate properties (MetricsSelector, SupervisorStrategy, RouterDispatcher, Paths) Surrogates are DTOs with no constructor - a default-constructed instance has all nulls. Marking them ? is honest. FromSurrogate passes them to constructors that already accept nullable params, so no behavioral change.

Null-forgiving ! (trusted to be non-null by contract):

Location Rationale
typeof(DefaultCollector).AssemblyQualifiedName! Concrete type loaded in the current assembly - AssemblyQualifiedName is never null for loaded types
Deserialize(...) as IMetricsSelector)! (3 sites in serializer) Serialization round-trip: ToBinary only serializes IMetricsSelector subtypes, so FromBinary is guaranteed to get the right type back. Existing comment says "should be safe because we serialized only the right subtypes." Pre-existing as casts; we added ! to satisfy nullable analysis without changing the cast pattern.

Checklist

MattKotsenas and others added 10 commits February 27, 2026 02:21
Add #nullable enable to DateTimeExtensions, IMetricsCollector, and
AnyNumber. These are leaf types with no nullable reference concerns -
purely value types and a simple interface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…trics

Add #nullable enable to EWMA, ClusterMetricMessages, MetricsGossip,
and ClusterMetricsMessageSerializer. Use null-forgiving operator on
Deserialize-as-IMetricsSelector casts that are trusted to succeed per
existing comments and serialization contracts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add #nullable enable to ClusterMetricsSettings,
ClusterMetricsEvents, and StandardMetrics. All reference type
properties are initialized in constructors with no nullable concerns.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add #nullable enable to DefaultCollector and MetricsCollectorBuilder.
Mark processes array as nullable in GetCpuUsages (initialized to null,
used in finally block). Use null-forgiving on AssemblyQualifiedName
for the concrete DefaultCollector type.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add #nullable enable to MetricSelectors, WeightedRoutees, and
ClusterMetricsRouting. Mark optional constructor parameters as
nullable (metricsSelector, supervisorStrategy, routerDispatcher,
paths). Use null! for surrogate properties populated via
deserialization. Mark Resizer override return as nullable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add #nullable enable to ClusterMetrics, ClusterMetricsCollector,
ClusterMetricsSupervisor, and ClusterMetricsStrategy. No nullable
concerns - all reference fields are initialized in constructors.

This completes nullable annotation coverage for all source files
in Akka.Cluster.Metrics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Now that all source files are annotated, replace per-file #nullable
enable directives with a single <Nullable>enable</Nullable> in
the csproj. This matches the pattern used by TestKit.Xunit and
TestKit.Xunit2.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Surrogate DTOs are populated via object initializers in ToSurrogate,
but their public properties should honestly reflect that they have no
constructor - marking them nullable is accurate since a default-
constructed surrogate has all nulls. The FromSurrogate methods pass
these values to constructors that already accept nullable parameters,
so no behavioral change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Approve public API surface changes from nullable annotations:
constructor parameters marked nullable, surrogate properties marked
nullable, Resizer override return marked nullable, EWMA.Equals
parameter marked nullable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant