fix(lmxproxy): protect probe subscription from ReadAsync teardown, add instance configs
ReadAsync internally subscribes/unsubscribes the same ScanTime tag used by the persistent probe, which was tearing down the probe subscription and triggering false reconnects every ~5s. Guard UnsubscribeInternal and stored subscription state so the probe tag is never removed by other callers. Also removes DetailedHealthCheckService (redundant with the persistent probe), adds per-instance config files (appsettings.v2.json, appsettings.v2b.json) loaded via LMXPROXY_INSTANCE env var so deploys no longer overwrite port settings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,6 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Serilog;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Domain;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Health;
|
||||
using HealthCheckService = ZB.MOM.WW.LmxProxy.Host.Health.HealthCheckService;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Metrics;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Subscriptions;
|
||||
@@ -27,20 +26,17 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
|
||||
private readonly SubscriptionManager _subscriptionManager;
|
||||
private readonly PerformanceMetrics _performanceMetrics;
|
||||
private readonly HealthCheckService _healthCheckService;
|
||||
private readonly DetailedHealthCheckService? _detailedHealthCheckService;
|
||||
|
||||
public StatusReportService(
|
||||
IScadaClient scadaClient,
|
||||
SubscriptionManager subscriptionManager,
|
||||
PerformanceMetrics performanceMetrics,
|
||||
HealthCheckService healthCheckService,
|
||||
DetailedHealthCheckService? detailedHealthCheckService = null)
|
||||
HealthCheckService healthCheckService)
|
||||
{
|
||||
_scadaClient = scadaClient;
|
||||
_subscriptionManager = subscriptionManager;
|
||||
_performanceMetrics = performanceMetrics;
|
||||
_healthCheckService = healthCheckService;
|
||||
_detailedHealthCheckService = detailedHealthCheckService;
|
||||
}
|
||||
|
||||
public async Task<string> GenerateHtmlReportAsync()
|
||||
@@ -144,24 +140,6 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
|
||||
}
|
||||
}
|
||||
|
||||
// Detailed health check (optional)
|
||||
if (_detailedHealthCheckService != null)
|
||||
{
|
||||
var detailedResult = await _detailedHealthCheckService.CheckHealthAsync(new HealthCheckContext());
|
||||
statusData.DetailedHealth = new HealthInfo
|
||||
{
|
||||
Status = detailedResult.Status.ToString(),
|
||||
Description = detailedResult.Description ?? ""
|
||||
};
|
||||
if (detailedResult.Data != null)
|
||||
{
|
||||
foreach (var kvp in detailedResult.Data)
|
||||
{
|
||||
statusData.DetailedHealth.Data[kvp.Key] = kvp.Value?.ToString() ?? "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return statusData;
|
||||
}
|
||||
|
||||
@@ -264,18 +242,6 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
|
||||
sb.AppendLine(" </table>");
|
||||
sb.AppendLine(" </div>");
|
||||
|
||||
// Detailed health (if available)
|
||||
if (statusData.DetailedHealth != null)
|
||||
{
|
||||
var detailedClass = GetHealthCardClass(statusData.DetailedHealth.Status);
|
||||
var detailedCss = GetHealthStatusCss(statusData.DetailedHealth.Status);
|
||||
sb.AppendLine($" <div class=\"card {detailedClass}\">");
|
||||
sb.AppendLine(" <h3>Detailed Health Check</h3>");
|
||||
sb.AppendLine($" <p class=\"{detailedCss}\">{statusData.DetailedHealth.Status}</p>");
|
||||
sb.AppendLine($" <p>{statusData.DetailedHealth.Description}</p>");
|
||||
sb.AppendLine(" </div>");
|
||||
}
|
||||
|
||||
sb.AppendLine($" <div class=\"footer\">Last updated: {statusData.Timestamp:yyyy-MM-dd HH:mm:ss} UTC | Service: {statusData.ServiceName} v{statusData.Version}</div>");
|
||||
sb.AppendLine("</body>");
|
||||
sb.AppendLine("</html>");
|
||||
|
||||
Reference in New Issue
Block a user