From 21dfcb57d6f626ad2b2268f4786ad2e3e61637fc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 00:01:56 +0000 Subject: [PATCH 1/3] Initial plan From d19da6f19e0178524880ee4756d2c4c8953d3ace Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 00:08:24 +0000 Subject: [PATCH 2/3] fix: rename `currentRole` to `current-role` in health check response for consistency Co-authored-by: Aniruddh25 <3513779+Aniruddh25@users.noreply.github.com> --- .../HealthCheck/ComprehensiveHealthReportResponseWriter.cs | 2 +- src/Service/HealthCheck/Model/ComprehensiveHealthCheckReport.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/HealthCheck/ComprehensiveHealthReportResponseWriter.cs b/src/Service/HealthCheck/ComprehensiveHealthReportResponseWriter.cs index 5027c5e059..26846e6b9c 100644 --- a/src/Service/HealthCheck/ComprehensiveHealthReportResponseWriter.cs +++ b/src/Service/HealthCheck/ComprehensiveHealthReportResponseWriter.cs @@ -109,7 +109,7 @@ public async Task WriteResponseAsync(HttpContext context) // Ensure cachedResponse is not null before calling WriteAsync if (report != null) { - // Set currentRole per-request (not cached) so each caller sees their own role + // Set current-role per-request (not cached) so each caller sees their own role await context.Response.WriteAsync(SerializeReport(report with { CurrentRole = _healthCheckHelper.GetCurrentRole(roleHeader, roleToken) })); } else diff --git a/src/Service/HealthCheck/Model/ComprehensiveHealthCheckReport.cs b/src/Service/HealthCheck/Model/ComprehensiveHealthCheckReport.cs index 26a260af47..a63c2debf2 100644 --- a/src/Service/HealthCheck/Model/ComprehensiveHealthCheckReport.cs +++ b/src/Service/HealthCheck/Model/ComprehensiveHealthCheckReport.cs @@ -46,7 +46,7 @@ public record ComprehensiveHealthCheckReport /// /// The current role of the user making the request (e.g., "anonymous", "authenticated"). /// - [JsonPropertyName("currentRole")] + [JsonPropertyName("current-role")] public string? CurrentRole { get; set; } /// From d0d1d0c9ae935535bc98912ced2ad155bb8a4111 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 08:19:08 +0000 Subject: [PATCH 3/3] fix: add retry logic to HotReloadConfigConnectionString and HotReloadConfigDatabaseType tests Co-authored-by: souvikghosh04 <210500244+souvikghosh04@users.noreply.github.com> --- .../HotReload/ConfigurationHotReloadTests.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs index 18c19cbd7a..05a858a654 100644 --- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs +++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs @@ -780,12 +780,28 @@ await WaitForConditionAsync( succeedConfigLog = _writer.ToString(); } - HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); + // Retry REST request because metadata re-initialization happens asynchronously + // after the "Validated hot-reloaded configuration file" message. The metadata provider + // factory clears and re-initializes providers on the hot-reload thread, so requests + // arriving before that completes will fail. + HttpResponseMessage restResult = null; + bool restSucceeded = false; + for (int attempt = 1; attempt <= 10; attempt++) + { + restResult = await _testClient.GetAsync("/rest/Book"); + if (restResult.StatusCode == HttpStatusCode.OK) + { + restSucceeded = true; + break; + } + + await Task.Delay(1000); + } // Assert Assert.IsTrue(failedConfigLog.Contains(HOT_RELOAD_FAILURE_MESSAGE)); Assert.IsTrue(succeedConfigLog.Contains(HOT_RELOAD_SUCCESS_MESSAGE)); - Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode); + Assert.IsTrue(restSucceeded, $"REST request did not return OK after hot-reload. Last status: {restResult?.StatusCode}"); } /// @@ -838,12 +854,28 @@ await WaitForConditionAsync( succeedConfigLog = _writer.ToString(); } - HttpResponseMessage restResult = await _testClient.GetAsync("/rest/Book"); + // Retry REST request because metadata re-initialization happens asynchronously + // after the "Validated hot-reloaded configuration file" message. The metadata provider + // factory clears and re-initializes providers on the hot-reload thread, so requests + // arriving before that completes will fail. + HttpResponseMessage restResult = null; + bool restSucceeded = false; + for (int attempt = 1; attempt <= 10; attempt++) + { + restResult = await _testClient.GetAsync("/rest/Book"); + if (restResult.StatusCode == HttpStatusCode.OK) + { + restSucceeded = true; + break; + } + + await Task.Delay(1000); + } // Assert Assert.IsTrue(failedConfigLog.Contains(HOT_RELOAD_FAILURE_MESSAGE)); Assert.IsTrue(succeedConfigLog.Contains(HOT_RELOAD_SUCCESS_MESSAGE)); - Assert.AreEqual(HttpStatusCode.OK, restResult.StatusCode); + Assert.IsTrue(restSucceeded, $"REST request did not return OK after hot-reload. Last status: {restResult?.StatusCode}"); } ///