Skip to content

Migrate Elsa.Api.Client to Microsoft.Extensions.Http.Resilience - #7907

Open
sfmskywalker with Copilot wants to merge 3 commits into
mainfrom
copilot/migrate-from-polly-extensions-http
Open

Migrate Elsa.Api.Client to Microsoft.Extensions.Http.Resilience#7907
sfmskywalker with Copilot wants to merge 3 commits into
mainfrom
copilot/migrate-from-polly-extensions-http

Conversation

Copilot AI commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Purpose

Replace Elsa.Api.Client's deprecated Polly.Extensions.Http integration so downstream consumers no longer inherit an unresolvable deprecated-package warning. The client now uses the current Microsoft.Extensions.Http.Resilience pipeline for its default HTTP retry behavior.


Scope

Select one primary concern:

  • Bug fix (behavior change)
  • Refactor (no behavior change)
  • Documentation update
  • Formatting / code cleanup
  • Dependency / build update
  • New feature

If this PR includes multiple unrelated concerns, please split it before requesting review.


Description

Problem

Elsa.Api.Client referenced Polly.Extensions.Http 3.0.0, which NuGet marks as deprecated. Any project consuming the client inherited that warning transitively with no downstream fix available.

Solution

  • Client resilience migration

    • Replaced the default AddTransientHttpErrorPolicy(...) registration with a Microsoft.Extensions.Http.Resilience retry handler.
    • Kept the default retry shape aligned with the existing behavior: 3 retries, exponential backoff, retry-only pipeline.
  • Dependency cleanup

    • Removed Polly.Extensions.Http from Elsa.Api.Client.
    • Removed Microsoft.Extensions.Http.Polly from Elsa.Api.Client.
    • Removed the unused central package pins for both deprecated/obsolete integration packages.
  • Focused coverage

    • Added a component test that registers an API client with a resilience retry handler and verifies retries are actually applied through the configured HTTP pipeline.

Example of the new default registration shape:

builder.AddResilienceHandler("elsa-api-client-retry", pipeline => pipeline.AddRetry(new HttpRetryStrategyOptions
{
    MaxRetryAttempts = 3,
    Delay = TimeSpan.FromSeconds(2),
    BackoffType = DelayBackoffType.Exponential,
    UseJitter = false,
    ShouldRetryAfterHeader = false
}));

Verification

Steps:

  1. Inspect /src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj and confirm Polly.Extensions.Http / Microsoft.Extensions.Http.Polly are removed and Microsoft.Extensions.Http.Resilience is referenced.
  2. Inspect /src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs and confirm the default retry configuration uses AddResilienceHandler(...).AddRetry(...).
  3. Run dotnet list src/clients/Elsa.Api.Client/Elsa.Api.Client.csproj package --deprecated.

Expected outcome:
Elsa.Api.Client no longer reports deprecated packages, and its default HTTP client registration uses the resilience pipeline API instead of the legacy Polly HTTP integration.


Screenshots / Recordings (if applicable)


Commit Convention

We recommend using conventional commit prefixes:

  • fix: – Bug fixes (behavior change)
  • feat: – New features
  • refactor: – Code changes without behavior change
  • docs: – Documentation updates
  • chore: – Maintenance, tooling, or dependency updates
  • test: – Test additions or modifications

Clear commit messages make reviews easier and history more meaningful.


Checklist

  • The PR is focused on a single concern
  • Commit messages follow the recommended convention
  • Tests added or updated (if applicable)
  • Documentation updated (if applicable)
  • No unrelated cleanup included
  • All tests pass

Copilot AI review requested due to automatic review settings August 3, 2026 19:20

Copilot AI 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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 19:27

Copilot AI 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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

RequestCount++;

if (RequestCount <= failuresBeforeSuccess)
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError));
Comment on lines +131 to +134
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(response, Encoding.UTF8, "application/json")
});
Copilot AI changed the title [WIP] Migrate from Polly.Extensions.Http to Microsoft.Extensions.Http.Resilience Migrate Elsa.Api.Client to Microsoft.Extensions.Http.Resilience Aug 3, 2026
Copilot AI requested a review from sfmskywalker August 3, 2026 19:32
@sfmskywalker
sfmskywalker marked this pull request as ready for review August 16, 2026 23:00
@sfmskywalker

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

@sfmskywalker

Copy link
Copy Markdown
Member

@greptileai

Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>
@greptile-apps

greptile-apps Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change moves the Elsa API client to the Microsoft resilience handler and adds retry coverage. A throttled task-completion request is now sent four times instead of once because HTTP 429 is included in the default retry behavior. Restrict the retry predicate before merging so callers receive rate-limit responses without repeated mutations.

Confidence Score: 4/5

Not safe to merge until the retry handler stops automatically repeating rate-limited mutating requests.

An in-process client run reproduced repeated POST dispatches for HTTP 429 and confirmed that the prior implementation dispatched the same request once.

Files Needing Attention: src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a P1 finding proof for the posted finding and attached reproducibility artifacts.
  • T-Rex produced a second P1 finding proof for another review comment.
  • T-Rex executed a general contract validation harness to compare retry behavior across revisions, confirming four POST requests on the changed revision and a single POST on the old policy, with a NullReferenceException noted after the final response.

View all artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix All With AI
### Issue 1
src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs:43-50
**HTTP 429 retries repeat task mutations**

`HttpRetryStrategyOptions` uses its default retry predicate because `ShouldHandle` is not configured. That predicate retries HTTP 429 responses, so a throttled non-idempotent API call is issued four times: the original request plus the three configured retries. The previous `AddTransientHttpErrorPolicy` behavior sent the identical 429 response once. Restrict the retry predicate to the intended transient failures so rate limiting is returned to the caller instead of repeating POST and DELETE operations.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Migrate Elsa.Api.Client resilience handl..." | Re-trigger Greptile

Comment on lines +43 to +50
public Action<IHttpClientBuilder>? ConfigureRetryPolicy { get; set; } = builder => builder.AddResilienceHandler("elsa-api-client-retry", pipeline => pipeline.AddRetry(new HttpRetryStrategyOptions
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromSeconds(2),
BackoffType = DelayBackoffType.Exponential,
UseJitter = false,
ShouldRetryAfterHeader = false
}));

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.

P1 HTTP 429 retries repeat task mutations

HttpRetryStrategyOptions uses its default retry predicate because ShouldHandle is not configured. That predicate retries HTTP 429 responses, so a throttled non-idempotent API call is issued four times: the original request plus the three configured retries. The previous AddTransientHttpErrorPolicy behavior sent the identical 429 response once. Restrict the retry predicate to the intended transient failures so rate limiting is returned to the caller instead of repeating POST and DELETE operations.

Artifacts

trex-artifacts/http-429-repro.cs

  • Runtime harness source that sends a non-idempotent task-completion POST to an in-process handler returning HTTP 429 and counts the requests.

trex-artifacts/http-429-01-before.log

  • Executed git-parent policy run showing HTTP 429 produced one POST request, so the old policy did not retry it.

trex-artifacts/http-429-02-after.log

  • Executed changed-policy run showing HTTP 429 produced four POST requests, confirming three configured retries.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/clients/Elsa.Api.Client/Options/ElsaClientBuilderOptions.cs
Line: 43-50

Comment:
**HTTP 429 retries repeat task mutations**

`HttpRetryStrategyOptions` uses its default retry predicate because `ShouldHandle` is not configured. That predicate retries HTTP 429 responses, so a throttled non-idempotent API call is issued four times: the original request plus the three configured retries. The previous `AddTransientHttpErrorPolicy` behavior sent the identical 429 response once. Restrict the retry predicate to the intended transient failures so rate limiting is returned to the caller instead of repeating POST and DELETE operations.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@greptile-apps

greptile-apps Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

Copilot AI commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Resolved in 168e3c7.

@gitguardian

gitguardian Bot commented Aug 16, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
35183230 Triggered Generic High Entropy Secret 168e3c7 src/apps/Elsa.ModularServer.Web/appsettings.json View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

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.

Migrate from deprecated Polly.Extensions.Http to Microsoft.Extensions.Http.Resilience

3 participants