Skip to content

Ppaul/sdk pruning failover retries#60200

Open
PallabPaul wants to merge 12 commits into
Azure:mainfrom
PallabPaul:ppaul/sdk-pruning-failover-retries
Open

Ppaul/sdk pruning failover retries#60200
PallabPaul wants to merge 12 commits into
Azure:mainfrom
PallabPaul:ppaul/sdk-pruning-failover-retries

Conversation

@PallabPaul

Copy link
Copy Markdown
Member

Contributing to the Azure SDK

Please see our CONTRIBUTING.md if you are not familiar with contributing to this repository or have questions.

For specific information about pull request etiquette and best practices, see this section.

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.

Pull request overview

This PR extends the Confidential Ledger client’s resiliency behavior by adding failover ledger routing, optional “archived/pruned collection” fallback for GetCurrentLedgerEntry, improved polling tolerance in PostLedgerEntryOperation, and new tests validating these behaviors. It also bumps the package version and updates the changelog for the new features.

Changes:

  • Added a failover discovery/execution service and integrated it into GetLedgerEntry* / GetCurrentLedgerEntry*.
  • Added optional archived-collection fallback and “Loading” polling behavior driven by client retry settings.
  • Updated PostLedgerEntryOperation polling to tolerate transient 406 and bounded consecutive 404s; added new resiliency tests and updated version/changelog.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
sdk/confidentialledger/Azure.Security.ConfidentialLedger/tests/ConfidentialLedgerPruningTests.cs Adds unit tests covering archived fallback, loading polling, and 406/404 tolerance.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/PostLedgerEntryOperation.cs Adds logic to treat 406 as pending and tolerate a bounded number of consecutive 404s while polling.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/Generated/ConfidentialLedgerClient.cs Adds failover routing and “Loading” polling to protocol methods, plus helper request overloads.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/ConfidentialLedgerFailoverService.cs Introduces failover endpoint discovery and execution logic.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/ConfidentialLedgerClientOptions.cs Adds EnableArchivedCollectionFallback option.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/ConfidentialLedgerClient.cs Wires in failover service, archived fallback, and “Loading” detection/formatting helpers.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/src/Azure.Security.ConfidentialLedger.csproj Bumps package version to 1.5.0-beta.1.
sdk/confidentialledger/Azure.Security.ConfidentialLedger/CHANGELOG.md Documents new features and bug fixes for 1.5.0-beta.1.

Comment on lines +277 to +287
Response failoverCurrent = await _failoverService.ExecuteOnFailoversAsync(
_ledgerEndpoint,
async (endpoint) =>
{
using HttpMessage message = CreateGetCurrentLedgerEntryRequest(endpoint, collectionId, context);
return await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false);
},
nameof(GetCurrentLedgerEntryAsync),
collectionId,
context?.CancellationToken ?? default).ConfigureAwait(false);
return FormatLedgerEntry(failoverCurrent);
Comment on lines +297 to +305
if (!IsLoadingResponse(response) || attempt >= _maxLoadingRetries)
{
return response;
}

if (_loadingPollDelay > TimeSpan.Zero)
{
await Task.Delay(_loadingPollDelay, cancellationToken).ConfigureAwait(false);
}
Comment on lines +362 to +373
Response failoverCurrent = _failoverService.ExecuteOnFailovers(
_ledgerEndpoint,
(endpoint) =>
{
using HttpMessage message = CreateGetCurrentLedgerEntryRequest(endpoint, collectionId, context);
return _pipeline.ProcessMessage(message, context);
},
nameof(GetCurrentLedgerEntry),
collectionId,
context?.CancellationToken ?? default);
return FormatLedgerEntry(failoverCurrent);
}
Comment on lines +382 to +391
if (!IsLoadingResponse(response) || attempt >= _maxLoadingRetries)
{
return response;
}

if (_loadingPollDelay > TimeSpan.Zero)
{
cancellationToken.WaitHandle.WaitOne(_loadingPollDelay);
cancellationToken.ThrowIfCancellationRequested();
}
Comment on lines +16 to +32
private readonly HttpPipeline _pipeline;
private readonly ClientDiagnostics _clientDiagnostics;

// The identity service used to discover failover ledgers. Honors a custom
// ConfidentialLedgerClientOptions.CertificateEndpoint when one is configured, falling back to
// the default identity service endpoint otherwise.
private readonly Uri _identityServiceEndpoint;

private static ResponseClassifier _responseClassifier200;
private static ResponseClassifier ResponseClassifier200 => _responseClassifier200 ??= new StatusCodeClassifier(stackalloc ushort[] { 200 });

public ConfidentialLedgerFailoverService(HttpPipeline pipeline, ClientDiagnostics clientDiagnostics, Uri identityServiceEndpoint = null)
{
_pipeline = pipeline ?? throw new ArgumentNullException(nameof(pipeline));
_clientDiagnostics = clientDiagnostics ?? throw new ArgumentNullException(nameof(clientDiagnostics));
_identityServiceEndpoint = identityServiceEndpoint ?? new Uri(ConfidentialLedgerClient.Default_Certificate_Endpoint);
}
Comment on lines +41 to +45
if (string.IsNullOrEmpty(collectionIdGate))
{
return operationAsync(primaryEndpoint); // collection gating: no failover
}
return ExecuteOnFailoversAsync(primaryEndpoint, operationAsync, operationName, cancellationToken);
Comment on lines +55 to +59
if (string.IsNullOrEmpty(collectionIdGate))
{
return operationSync(primaryEndpoint);
}
return ExecuteOnFailovers(primaryEndpoint, operationSync, operationName, cancellationToken);
Comment on lines +72 to +74
using HttpMessage message = CreateFailoverRequest(failoverUrl);
Response response = await _pipeline.ProcessMessageAsync(message, new RequestContext()).ConfigureAwait(false);
return ParseFailoverEndpoints(primaryEndpoint, response);
Comment on lines +94 to +96
using HttpMessage message = CreateFailoverRequest(failoverUrl);
Response response = _pipeline.ProcessMessage(message, new RequestContext());
return ParseFailoverEndpoints(primaryEndpoint, response);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants