Add resilient HttpClientFactory and AOT-safe AssemblyInfo (v4.0)#392
Merged
Conversation
Add a reusable HttpClientFactory built on Microsoft.Extensions.Http.Resilience (Polly) with retry, circuit breaker, and connection pooling, tunable via HttpClientOptions and exposing a shared client, caller-owned clients, and the resilience handler. Add AssemblyInfo, an AOT-safe identity helper whose For<T>() substitutes for Assembly.GetExecutingAssembly(). Route Download through the factory (signatures unchanged). Gate the library's reference AOT verification behind an explicit PublishAot opt-in (suppressing the advisory IL3058 for the unannotated Polly graph), and turn Sandbox into a Native AOT smoke test (Main + standalone sample classes) that proves identity resolution and the Polly pipeline run under Native AOT. Also resolve the analyzer cleanups: List<T> public members to Collection<T> / ReadOnlyCollection<T> (CA1002), await-using ConfigureAwait(false) disposal (CA2007), and test-code fixes for CA2000/CA1849/CA5394, trimming the test .editorconfig to only the required xUnit suppressions. Docs: HISTORY.md v4.0 entry, README.md release notes, cspell Polly term. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #392 +/- ##
===========================================
+ Coverage 40.62% 46.20% +5.58%
===========================================
Files 10 13 +3
Lines 1024 1160 +136
Branches 99 107 +8
===========================================
+ Hits 416 536 +120
- Misses 580 593 +13
- Partials 28 31 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
There was a problem hiding this comment.
Pull request overview
This PR evolves ptr727.Utilities into a v4.0 release by introducing a reusable resilient HTTP client factory (Polly v8 via Microsoft.Extensions.Http.Resilience), adding an AOT-safe assembly/application identity helper, and updating related APIs, docs, and tests to align with analyzer guidance and Native AOT verification.
Changes:
- Add
HttpClientFactory+HttpClientOptions(retry + circuit breaker + connection pooling) and updateDownloadto use the factory. - Add
AssemblyInfofor AOT-safe assembly identity and a default User-Agent, plus Sandbox samples to exercise identity + resilience under managed and Native AOT. - Apply analyzer-driven API adjustments (
List<T>->Collection<T>/ReadOnlyCollection<T>) and update tests/docs/versioning accordingly.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| version.json | Bumps the library version to 4.0. |
| Directory.Packages.props | Adds Microsoft.Extensions.Http.Resilience package version. |
| Utilities/Utilities.csproj | Adds resilience package reference and gates reference-AOT verification behind PublishAot. |
| Utilities/HttpClientOptions.cs | Introduces configurable defaults for retry/circuit breaker/pooling/timeouts/user-agent/base address. |
| Utilities/HttpClientFactory.cs | Adds resilient HttpClient creation APIs (singleton + caller-owned + handler). |
| Utilities/AssemblyInfo.cs | Adds AOT-safe assembly identity + app name/version + default User-Agent helper. |
| Utilities/Download.cs | Routes downloads through HttpClientFactory while keeping existing signatures/timeout knob. |
| Utilities/Extensions.cs | Adds source-generated logging methods for HTTP retry and circuit breaker events. |
| Utilities/FileEx.cs | Updates public API to use safe collection types and applies async-disposal ConfigureAwait(false) patterns. |
| Utilities/StringHistory.cs | Changes exposed list to ReadOnlyCollection<string> and internalizes the mutable list. |
| Utilities/StringCompression.cs | Updates async disposal to use ConfigureAwait(false) via configured async disposable. |
| Utilities/GlobalUsings.cs | Adds System.Collections.ObjectModel global using for new public surface types. |
| Utilities/.editorconfig | Removes prior library-scoped analyzer relaxations (keeping only CA1711 exemption). |
| UtilitiesTests/HttpClientOptionsTests.cs | Adds tests asserting default HttpClientOptions values. |
| UtilitiesTests/HttpClientFactoryTests.cs | Adds tests for singleton/shared client, independent clients, user-agent behavior, and handler creation. |
| UtilitiesTests/AssemblyInfoTests.cs | Adds tests for AssemblyInfo.For<T>() and identity/user-agent properties. |
| UtilitiesTests/StringCompressionTests.cs | Switches test randomness to RandomNumberGenerator to satisfy security analyzers. |
| UtilitiesTests/StringCompressionAsyncTests.cs | Switches async test randomness to RandomNumberGenerator to satisfy security analyzers. |
| UtilitiesTests/FileExAsyncTests.cs | Uses CancellationTokenSource.CancelAsync() in async cancellation test paths. |
| UtilitiesTests/ExtensionsTests.cs | Uses CancellationTokenSource.CancelAsync() in async cancellation test paths. |
| UtilitiesTests/ConsoleTests.cs | Hardens Console.Out redirection by restoring original output in finally. |
| UtilitiesTests/.editorconfig | Tightens test-specific analyzer suppression set to only required xUnit exceptions. |
| Sandbox/Program.cs | Restructures Sandbox into an explicit Main that runs sample classes and returns an exit code. |
| Sandbox/AssemblyIdentitySample.cs | Adds a sample that validates AOT-safe identity resolution with explicit runtime checks. |
| Sandbox/HttpClientSample.cs | Adds a sample that deterministically exercises the retry pipeline via a failing local request. |
| .vscode/tasks.json | Adds a “Sandbox AOT Publish” task for Native AOT smoke testing. |
| .vscode/launch.json | Adds a “Sandbox (non-AOT)” debug launch configuration. |
| README.md | Updates release notes section for v4.0 highlights/breaking changes. |
| HISTORY.md | Adds v4.0 release entry detailing new APIs, AOT strategy, and breaking API changes. |
| cspell.json | Adds “Polly” to the allowed dictionary list. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a reusable, resilient HTTP client factory and an AOT-safe assembly identity helper, and cuts the library to v4.0.
HttpClientFactory- built onMicrosoft.Extensions.Http.Resilience(Polly v8) with retry, circuit breaker, and connection pooling. Exposes a shared singleton client, caller-owned clients, and the resilience handler (asDelegatingHandler, keeping Polly types off the public API). Tunable viaHttpClientOptions(best-practice defaults, override only what you need).AssemblyInfo- AOT-safe identity helper.For<T>()(typeof(T).Assembly) substitutes forAssembly.GetExecutingAssembly(), which is unreliable under Native AOT (dotnet/runtime#94200). Supplies the consuming app name/version and a default User-Agent.Downloadnow builds its client through the factory;TimeoutSecondsand all method signatures are unchanged (downloads now flow through the resilience pipeline).AOT strategy - proven, not assumed
PublishAotopt-in, suppressing only the advisoryIL3058(the Polly graph is not annotatedIsAotCompatible; real trim/dynamic-code issues would surface as IL2xxx/IL3050).Maincalling standalone, commentable sample classes and serves as a Native AOT smoke test. Published and run as Native AOT, it resolves identity identically to the managed run (AppName=Sandbox,UserAgent=Sandbox/<version>) and executes the full Polly retry pipeline - the definitive proof that identity resolution and Polly work under AOT.Sandbox AOT Publishtask and aSandbox (non-AOT)debug launch config.Analyzer cleanups (folded in)
List<T>public members ->Collection<T>/ReadOnlyCollection<T>(CA1002, a breaking API change).await usingdisposal now usesConfigureAwait(false)(CA2007)..editorconfigtrimmed to only the required xUnit suppressions (CA1707, CA1515).Docs
Pollyadded to cspell.Verification
dotnet build- 0 warnings / 0 errors underTreatWarningsAsErrors.dotnet test- 145 passed (12 new).dotnet csharpier checkanddotnet format style --verify-no-changesclean.🤖 Generated with Claude Code