-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Ppaul/failover ledger endpoint #51947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
2e30dd0
515190d
2fa1b35
af7213a
cb79689
bf8d04e
19870c2
409c510
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Text.Json; | ||
| using System.Diagnostics; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using Azure.Core; | ||
|
|
@@ -16,6 +17,9 @@ internal class ConfidentialLedgerFailoverService | |
| private readonly HttpPipeline _pipeline; | ||
| private readonly ClientDiagnostics _clientDiagnostics; | ||
|
|
||
| internal const string IdentityServiceBaseUrl = "https://identity.confidential-ledger.core.azure.com"; | ||
| internal const string LedgerDomainSuffix = "confidential-ledger.azure.com"; | ||
|
|
||
| private static ResponseClassifier _responseClassifier200; | ||
| private static ResponseClassifier ResponseClassifier200 => _responseClassifier200 ??= new StatusCodeClassifier(stackalloc ushort[] { 200 }); | ||
|
|
||
|
|
@@ -57,145 +61,115 @@ private async Task<List<Uri>> GetFailoverEndpointsAsync( | |
| Uri primaryEndpoint, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| var failoverEndpoints = new List<Uri>(); | ||
|
|
||
| try | ||
| { | ||
| string ledgerId = primaryEndpoint.Host.Substring(0, primaryEndpoint.Host.IndexOf('.')); | ||
|
|
||
| Uri failoverUrl = new Uri($"https://identity.confidential-ledger.core.azure.com/failover/{ledgerId}"); | ||
| Uri failoverUrl = new Uri($"{IdentityServiceBaseUrl}/failover/{ledgerId}"); | ||
|
|
||
| using HttpMessage message = CreateFailoverRequest(failoverUrl); | ||
| Response response = await _pipeline.ProcessMessageAsync(message, new RequestContext()).ConfigureAwait(false); | ||
|
|
||
| if (response.Status == 200) | ||
| { | ||
| using JsonDocument jsonDoc = JsonDocument.Parse(response.Content); | ||
| jsonDoc.RootElement.TryGetProperty("ledgerId", out _); // fire & forget | ||
| if (jsonDoc.RootElement.TryGetProperty("failoverLedgers", out JsonElement failoverArray)) | ||
| { | ||
| foreach (JsonElement failoverLedger in failoverArray.EnumerateArray()) | ||
| { | ||
| string failoverLedgerId = null; | ||
| try | ||
| { | ||
| switch (failoverLedger.ValueKind) | ||
| { | ||
| case JsonValueKind.String: | ||
| failoverLedgerId = failoverLedger.GetString(); | ||
| break; | ||
| case JsonValueKind.Object: | ||
| if (failoverLedger.TryGetProperty("name", out JsonElement nameProp) && nameProp.ValueKind == JsonValueKind.String) | ||
| { | ||
| failoverLedgerId = nameProp.GetString(); | ||
| } | ||
| else | ||
| { | ||
| foreach (JsonProperty prop in failoverLedger.EnumerateObject()) | ||
| { | ||
| if (prop.Value.ValueKind == JsonValueKind.String && string.Equals(prop.Name, "id", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| failoverLedgerId = prop.Value.GetString(); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| catch (Exception) | ||
| { | ||
| // ignore element issues | ||
| } | ||
|
|
||
| if (!string.IsNullOrEmpty(failoverLedgerId)) | ||
| { | ||
| Uri endpoint = new UriBuilder(primaryEndpoint) { Host = $"{failoverLedgerId}.confidential-ledger.azure.com" }.Uri; | ||
| failoverEndpoints.Add(endpoint); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return ParseFailoverEndpoints(primaryEndpoint, response); | ||
| } | ||
| catch (Exception) | ||
| { | ||
PallabPaul marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // suppress metadata retrieval exception | ||
| } | ||
|
|
||
| return failoverEndpoints; | ||
| return new List<Uri>(); | ||
| } | ||
|
|
||
| private List<Uri> GetFailoverEndpoints( | ||
| Uri primaryEndpoint, | ||
| CancellationToken cancellationToken = default) | ||
| { | ||
| var failoverEndpoints = new List<Uri>(); | ||
|
|
||
| try | ||
| { | ||
| // retrieving sync metadata | ||
| string ledgerId = primaryEndpoint.Host.Substring(0, primaryEndpoint.Host.IndexOf('.')); | ||
|
|
||
| Uri failoverUrl = new Uri($"https://identity.confidential-ledger.core.azure.com/failover/{ledgerId}"); | ||
| Uri failoverUrl = new Uri($"{IdentityServiceBaseUrl}/failover/{ledgerId}"); | ||
|
|
||
| using HttpMessage message = CreateFailoverRequest(failoverUrl); | ||
| Response response = _pipeline.ProcessMessage(message, new RequestContext()); | ||
| return ParseFailoverEndpoints(primaryEndpoint, response); | ||
| } | ||
| catch (Exception) | ||
| { | ||
| // suppress metadata retrieval exception | ||
| } | ||
| return new List<Uri>(); | ||
| } | ||
|
|
||
| if (response.Status == 200) | ||
| private static List<Uri> ParseFailoverEndpoints(Uri primaryEndpoint, Response response) | ||
| { | ||
| var endpoints = new List<Uri>(); | ||
| if (response?.Status != 200) | ||
| { | ||
| return endpoints; | ||
| } | ||
| try | ||
| { | ||
| using JsonDocument jsonDoc = JsonDocument.Parse(response.Content); | ||
| jsonDoc.RootElement.TryGetProperty("ledgerId", out _); // optional | ||
| if (jsonDoc.RootElement.TryGetProperty("failoverLedgers", out JsonElement failoverArray)) | ||
| { | ||
| using JsonDocument jsonDoc = JsonDocument.Parse(response.Content); | ||
| jsonDoc.RootElement.TryGetProperty("ledgerId", out _); | ||
| if (jsonDoc.RootElement.TryGetProperty("failoverLedgers", out JsonElement failoverArray)) | ||
| foreach (JsonElement failoverLedger in failoverArray.EnumerateArray()) | ||
| { | ||
| foreach (JsonElement failoverLedger in failoverArray.EnumerateArray()) | ||
| string failoverLedgerId = null; | ||
| try | ||
| { | ||
| string failoverLedgerId = null; | ||
| try | ||
| switch (failoverLedger.ValueKind) | ||
| { | ||
| switch (failoverLedger.ValueKind) | ||
| { | ||
| case JsonValueKind.String: | ||
| failoverLedgerId = failoverLedger.GetString(); | ||
| break; | ||
| case JsonValueKind.Object: | ||
| if (failoverLedger.TryGetProperty("name", out JsonElement nameProp) && nameProp.ValueKind == JsonValueKind.String) | ||
| { | ||
| failoverLedgerId = nameProp.GetString(); | ||
| } | ||
| else | ||
| case JsonValueKind.String: | ||
| failoverLedgerId = failoverLedger.GetString(); | ||
| break; | ||
| case JsonValueKind.Object: | ||
| if (failoverLedger.TryGetProperty("name", out JsonElement nameProp) && nameProp.ValueKind == JsonValueKind.String) | ||
| { | ||
| failoverLedgerId = nameProp.GetString(); | ||
| } | ||
| else | ||
| { | ||
| foreach (JsonProperty prop in failoverLedger.EnumerateObject()) | ||
| { | ||
| foreach (JsonProperty prop in failoverLedger.EnumerateObject()) | ||
| if (prop.Value.ValueKind == JsonValueKind.String && string.Equals(prop.Name, "id", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| if (prop.Value.ValueKind == JsonValueKind.String && string.Equals(prop.Name, "id", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| failoverLedgerId = prop.Value.GetString(); | ||
| break; | ||
| } | ||
| failoverLedgerId = prop.Value.GetString(); | ||
| break; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| catch (Exception) | ||
| { | ||
| // ignore element issues | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| catch (JsonException jex) | ||
| { | ||
| #if DEBUG | ||
| Debug.WriteLine($"[ConfidentialLedgerFailoverService] JSON parse issue for failoverLedger element: {jex.Message}"); | ||
| #endif | ||
| _ = jex; // suppress unused warning in non-DEBUG builds | ||
| } | ||
| catch (InvalidOperationException ioex) | ||
| { | ||
| #if DEBUG | ||
| Debug.WriteLine($"[ConfidentialLedgerFailoverService] Invalid operation while parsing failoverLedger element: {ioex.Message}"); | ||
| #endif | ||
| _ = ioex; // suppress unused warning in non-DEBUG builds | ||
| } | ||
|
|
||
| if (!string.IsNullOrEmpty(failoverLedgerId)) | ||
| { | ||
| Uri endpoint = new UriBuilder(primaryEndpoint) { Host = $"{failoverLedgerId}.confidential-ledger.azure.com" }.Uri; | ||
| failoverEndpoints.Add(endpoint); | ||
| } | ||
| if (!string.IsNullOrEmpty(failoverLedgerId)) | ||
| { | ||
| Uri endpoint = new UriBuilder(primaryEndpoint) { Host = $"{failoverLedgerId}.{LedgerDomainSuffix}" }.Uri; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is passing the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. primary endpoint host already contains the suffix, which might be staging or any new env we add later like ppe. Therefore if would make sense to replace the first part of the existing host instead of constructing the new one with the current prod suffix. |
||
| endpoints.Add(endpoint); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| catch (Exception) | ||
| { | ||
| // suppress metadata retrieval exception | ||
| // ignore entire parse failure | ||
| } | ||
|
|
||
| return failoverEndpoints; | ||
| return endpoints; | ||
| } | ||
|
|
||
| private HttpMessage CreateFailoverRequest(Uri failoverUrl) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To get the actual value you'd need to follow the same logic as in
GetIdentityServerTlsCert, i.e.ledgerOptions?.CertificateEndpoint ?? new Uri(Default_Certificate_Endpoint)It can be overriden in
ledgerOptions, and please reuse the default endpoint value fromConfidentialLedgerClientbut that would need to changeprivate const stringtopublic const stringI bet