From 31b2012c8bfb8c11f6d8b5096c7e07d835ad9287 Mon Sep 17 00:00:00 2001 From: John Simons Date: Sat, 18 Jul 2026 20:30:59 +1000 Subject: [PATCH] Retire known-endpoints scatter-gather and audit KnownEndpoints storage Retire known-endpoints scatter-gather and audit KnownEndpoints storage The audit instance's KnownEndpoint documents (and their LastSeen field) were written on every ingested batch but only ever read back by the /endpoints/known scatter-gather, which no shipping client depends on: ServicePulse never calls the route, and ServiceInsight only consumes identity fields that the primary can serve locally. Endpoint discovery already flows to the primary via RegisterNewEndpoint queue messages, so the remote query added nothing but edge cases (pre-4.5 endpoints without a HostId, in-flight registrations, primary-deleted endpoints still present in audit data). - Primary GET /endpoints/known now serves from the in-memory endpoint registry; GetKnownEndpointsApi is deleted - PATCH /endpoints/{id} returns 404 for unknown endpoints instead of crashing with KeyNotFoundException (500) - Audit ingestion no longer records KnownEndpoint documents; the model, RecordKnownEndpoint, and QueryKnownEndpoints are removed from the persistence seam and both implementations - The audit /endpoints/known route remains as a backwards-compatibility stub returning an empty result so older primaries that still scatter-gather get a valid response instead of a 404 Existing audit KnownEndpoint documents expire on their own via the RavenDB @expires metadata; no migration is needed. --- .../InMemoryAuditDataStore.cs | 24 ------- .../InMemoryAuditIngestionUnitOfWork.cs | 7 -- .../RavenAuditDataStore.cs | 24 ------- .../RavenAuditIngestionUnitOfWork.cs | 4 -- .../EmbeddedLifecycleTests.cs | 3 +- .../RetentionTests.cs | 42 ----------- .../KnownEndpointsTests.cs | 72 ------------------- .../IAuditDataStore.cs | 1 - .../Monitoring/KnownEndpoint.cs | 25 ------- .../UnitOfWork/IAuditIngestionUnitOfWork.cs | 2 - .../APIApprovals.HttpApiRoutes.approved.txt | 2 +- .../Auditing/AuditPersister.cs | 39 ---------- .../Infrastructure/WebApi/RootController.cs | 2 +- .../KnownEndpointsController.cs | 17 +++-- .../Web/EndpointsMonitoringController.cs | 17 ++--- .../Monitoring/Web/GetKnownEndpointsApi.cs | 45 ------------ 16 files changed, 21 insertions(+), 305 deletions(-) delete mode 100644 src/ServiceControl.Audit.Persistence.Tests/KnownEndpointsTests.cs delete mode 100644 src/ServiceControl.Audit.Persistence/Monitoring/KnownEndpoint.cs delete mode 100644 src/ServiceControl/Monitoring/Web/GetKnownEndpointsApi.cs diff --git a/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditDataStore.cs b/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditDataStore.cs index 3632772f1f..f06b0681b7 100644 --- a/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditDataStore.cs +++ b/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditDataStore.cs @@ -9,15 +9,11 @@ using ServiceControl.Audit.Auditing.BodyStorage; using ServiceControl.Audit.Auditing.MessagesView; using ServiceControl.Audit.Infrastructure; - using ServiceControl.Audit.Monitoring; - using ServiceControl.Audit.Persistence.Infrastructure; - using ServiceControl.Audit.Persistence.Monitoring; using ServiceControl.SagaAudit; class InMemoryAuditDataStore : IAuditDataStore { IBodyStorage bodyStorage; - public List knownEndpoints; public List failedAuditImports; public InMemoryAuditDataStore(IBodyStorage bodyStorage) @@ -26,7 +22,6 @@ public InMemoryAuditDataStore(IBodyStorage bodyStorage) sagaHistories = []; messageViews = []; processedMessages = []; - knownEndpoints = []; failedAuditImports = []; } @@ -176,25 +171,6 @@ Task GetMessageBodyFromMetadata(string messageId) return Task.FromResult(MessageBodyView.FromString(body, contentType, bodySize, string.Empty)); } - public async Task>> QueryKnownEndpoints(CancellationToken cancellationToken) - { - var knownEndpointsView = knownEndpoints - .Select(x => new KnownEndpointsView - { - Id = DeterministicGuid.MakeId(x.Name, x.HostId.ToString()), - EndpointDetails = new EndpointDetails - { - Host = x.Host, - HostId = x.HostId, - Name = x.Name - }, - HostDisplayName = x.Host - }) - .ToList(); - - return await Task.FromResult(new QueryResult>(knownEndpointsView, new QueryStatsInfo(string.Empty, knownEndpointsView.Count))); - } - public Task>> QueryAuditCounts(string endpointName, CancellationToken cancellationToken) { var results = messageViews diff --git a/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditIngestionUnitOfWork.cs b/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditIngestionUnitOfWork.cs index 961e39801a..fa4e167227 100644 --- a/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditIngestionUnitOfWork.cs +++ b/src/ServiceControl.Audit.Persistence.InMemory/InMemoryAuditIngestionUnitOfWork.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Auditing.BodyStorage; using ServiceControl.Audit.Auditing; - using ServiceControl.Audit.Persistence.Monitoring; using ServiceControl.Audit.Persistence.UnitOfWork; using ServiceControl.SagaAudit; @@ -16,12 +15,6 @@ class InMemoryAuditIngestionUnitOfWork( { public ValueTask DisposeAsync() => ValueTask.CompletedTask; - public Task RecordKnownEndpoint(KnownEndpoint knownEndpoint, CancellationToken cancellationToken) - { - dataStore.knownEndpoints.Add(knownEndpoint); - return Task.CompletedTask; - } - public async Task RecordProcessedMessage(ProcessedMessage processedMessage, ReadOnlyMemory body, CancellationToken cancellationToken) { if (!body.IsEmpty) diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs b/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs index 8a465fb029..97f90af67c 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/RavenAuditDataStore.cs @@ -8,12 +8,9 @@ using Auditing.MessagesView; using Extensions; using Indexes; - using Monitoring; using Raven.Client.Documents; using ServiceControl.Audit.Auditing; using ServiceControl.Audit.Infrastructure; - using ServiceControl.Audit.Monitoring; - using ServiceControl.Audit.Persistence.Infrastructure; using ServiceControl.SagaAudit; using Transformers; @@ -125,27 +122,6 @@ public async Task GetMessageBody(string messageId, Cancellation ); } - public async Task>> QueryKnownEndpoints(CancellationToken cancellationToken) - { - using var session = await sessionProvider.OpenSession(cancellationToken: cancellationToken); - var endpoints = await session.Advanced.LoadStartingWithAsync(KnownEndpoint.CollectionName, pageSize: 1024, token: cancellationToken); - - var knownEndpoints = endpoints - .Select(x => new KnownEndpointsView - { - Id = DeterministicGuid.MakeId(x.Name, x.HostId.ToString()), - EndpointDetails = new EndpointDetails - { - Host = x.Host, - HostId = x.HostId, - Name = x.Name - }, - HostDisplayName = x.Host - }) - .ToList(); - - return new QueryResult>(knownEndpoints, new QueryStatsInfo(string.Empty, knownEndpoints.Count)); - } public async Task>> QueryAuditCounts(string endpointName, CancellationToken cancellationToken) { diff --git a/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs b/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs index eb19562dbc..1fa64e3c34 100644 --- a/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs +++ b/src/ServiceControl.Audit.Persistence.RavenDB/UnitOfWork/RavenAuditIngestionUnitOfWork.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Auditing; using Auditing.BodyStorage; - using Monitoring; using NServiceBus; using Persistence.UnitOfWork; using Raven.Client; @@ -50,9 +49,6 @@ MetadataAsDictionary GetExpirationMetadata() => public Task RecordSagaSnapshot(SagaSnapshot sagaSnapshot, CancellationToken cancellationToken) => bulkInsert.StoreAsync(sagaSnapshot, GetExpirationMetadata()); - public Task RecordKnownEndpoint(KnownEndpoint knownEndpoint, CancellationToken cancellationToken) - => bulkInsert.StoreAsync(knownEndpoint, GetExpirationMetadata()); - public async ValueTask DisposeAsync() { await bulkInsert.DisposeAsync(); diff --git a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/EmbeddedLifecycleTests.cs b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/EmbeddedLifecycleTests.cs index 6e518d8ac1..e6fe27aa0f 100644 --- a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/EmbeddedLifecycleTests.cs +++ b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/EmbeddedLifecycleTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading.Tasks; using NUnit.Framework; + using ServiceControl.Audit.Infrastructure; using ServiceControl.Audit.Persistence.RavenDB; using TestHelper; @@ -35,7 +36,7 @@ public override async Task Setup() [Test] public async Task Verify_embedded_database() { - await DataStore.QueryKnownEndpoints(TestContext.CurrentContext.CancellationToken); + await DataStore.GetMessages(false, new PagingInfo(), new SortInfo("Id", "asc"), cancellationToken: TestContext.CurrentContext.CancellationToken); using (Assert.EnterMultipleScope()) { diff --git a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/RetentionTests.cs b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/RetentionTests.cs index fa75845e67..97512f2a85 100644 --- a/src/ServiceControl.Audit.Persistence.Tests.RavenDB/RetentionTests.cs +++ b/src/ServiceControl.Audit.Persistence.Tests.RavenDB/RetentionTests.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Auditing; - using Monitoring; using NServiceBus; using NUnit.Framework; using SagaAudit; @@ -44,36 +43,6 @@ public async Task AuditMessageRetention() } } - [Test] - public async Task KnownEndpointRetention() - { - var knownEndpoint = new KnownEndpoint() - { - Host = "Myself", - HostId = Guid.NewGuid(), - Id = "KnownEndpoints/1234123", - LastSeen = DateTime.UtcNow, - Name = "Wazowsky" - }; - - await IngestKnownEndpoints( - knownEndpoint - ); - - var queryResultBeforeExpiration = await DataStore.QueryKnownEndpoints(TestContext.CurrentContext.CancellationToken); - - await Task.Delay(4000); - - var queryResultAfterExpiration = await DataStore.QueryKnownEndpoints(TestContext.CurrentContext.CancellationToken); - - Assert.That(queryResultBeforeExpiration.Results, Has.Count.EqualTo(1)); - using (Assert.EnterMultipleScope()) - { - Assert.That(queryResultBeforeExpiration.Results[0].EndpointDetails.Name, Is.EqualTo("Wazowsky")); - Assert.That(queryResultAfterExpiration.Results.Count, Is.EqualTo(0)); - } - } - [Test] public async Task SagaSnapshotRetention() { @@ -147,17 +116,6 @@ async Task IngestProcessedMessagesAudits(params ProcessedMessage[] processedMess await configuration.CompleteDBOperation(); } - async Task IngestKnownEndpoints(params KnownEndpoint[] knownEndpoints) - { - var unitOfWork = await StartAuditUnitOfWork(knownEndpoints.Length); - foreach (var knownEndpoint in knownEndpoints) - { - await unitOfWork.RecordKnownEndpoint(knownEndpoint); - } - await unitOfWork.DisposeAsync(); - await configuration.CompleteDBOperation(); - } - async Task IngestSagaAudits(params SagaSnapshot[] snapshots) { var unitOfWork = await StartAuditUnitOfWork(snapshots.Length); diff --git a/src/ServiceControl.Audit.Persistence.Tests/KnownEndpointsTests.cs b/src/ServiceControl.Audit.Persistence.Tests/KnownEndpointsTests.cs deleted file mode 100644 index 2fd6840d97..0000000000 --- a/src/ServiceControl.Audit.Persistence.Tests/KnownEndpointsTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -namespace ServiceControl.Audit.Persistence.Tests -{ - using System; - using System.Linq; - using System.Threading.Tasks; - using Monitoring; - using NUnit.Framework; - - [TestFixture] - class KnownEndpointsTests : PersistenceTestFixture - { - [Test] - public async Task Basic_Roundtrip() - { - var ingestedEndpoint = new KnownEndpoint - { - Host = "HostName", - HostId = Guid.NewGuid(), - LastSeen = DateTime.UtcNow, - Name = "Endpoint" - }; - - await IngestKnownEndpoints(ingestedEndpoint); - - var endpoints = await DataStore.QueryKnownEndpoints(TestContext.CurrentContext.CancellationToken); - - Assert.That(endpoints.Results, Has.Count.EqualTo(1)); - var endpoint = endpoints.Results[0]; - using (Assert.EnterMultipleScope()) - { - Assert.That(endpoint.HostDisplayName, Is.EqualTo(ingestedEndpoint.Host)); - Assert.That(endpoint.EndpointDetails.Host, Is.EqualTo(ingestedEndpoint.Host)); - Assert.That(endpoint.EndpointDetails.HostId, Is.EqualTo(ingestedEndpoint.HostId)); - Assert.That(endpoint.EndpointDetails.Name, Is.EqualTo(ingestedEndpoint.Name)); - } - } - - [Test] - public async Task Can_query_many_known_endpoints() - { - var knownEndpoints = Enumerable.Range(1, 200) - .Select(x => new KnownEndpoint - { - Host = $"HostName{x}", - HostId = Guid.NewGuid(), - Name = $"Endpoint{x}" - }).ToArray(); - - await IngestKnownEndpoints(knownEndpoints); - - var queryResult = await DataStore.QueryKnownEndpoints(TestContext.CurrentContext.CancellationToken); - - using (Assert.EnterMultipleScope()) - { - Assert.That(queryResult.QueryStats.TotalCount, Is.EqualTo(200)); - Assert.That(queryResult.Results, Has.Count.EqualTo(200)); - } - } - - async Task IngestKnownEndpoints(params KnownEndpoint[] knownEndpoints) - { - var unitOfWork = await StartAuditUnitOfWork(knownEndpoints.Length); - foreach (var knownEndpoint in knownEndpoints) - { - await unitOfWork.RecordKnownEndpoint(knownEndpoint); - } - await unitOfWork.DisposeAsync(); - await configuration.CompleteDBOperation(); - } - - } -} \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence/IAuditDataStore.cs b/src/ServiceControl.Audit.Persistence/IAuditDataStore.cs index bc7258ffc3..5ed7a2fc6e 100644 --- a/src/ServiceControl.Audit.Persistence/IAuditDataStore.cs +++ b/src/ServiceControl.Audit.Persistence/IAuditDataStore.cs @@ -12,7 +12,6 @@ public interface IAuditDataStore { - Task>> QueryKnownEndpoints(CancellationToken cancellationToken); Task> QuerySagaHistoryById(Guid input, CancellationToken cancellationToken); Task>> GetMessages(bool includeSystemMessages, PagingInfo pagingInfo, SortInfo sortInfo, DateTimeRange timeSentRange = null, CancellationToken cancellationToken = default); Task>> QueryMessages(string searchParam, PagingInfo pagingInfo, SortInfo sortInfo, DateTimeRange timeSentRange = null, CancellationToken cancellationToken = default); diff --git a/src/ServiceControl.Audit.Persistence/Monitoring/KnownEndpoint.cs b/src/ServiceControl.Audit.Persistence/Monitoring/KnownEndpoint.cs deleted file mode 100644 index fc6762bf37..0000000000 --- a/src/ServiceControl.Audit.Persistence/Monitoring/KnownEndpoint.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace ServiceControl.Audit.Persistence.Monitoring -{ - using System; - using Infrastructure; - - public class KnownEndpoint - { - public string Id { get; set; } - - public string Name { get; set; } - - public Guid HostId { get; set; } - - public string Host { get; set; } - - public DateTime LastSeen { get; set; } - - public static string MakeDocumentId(string endpointName, Guid endpointHostId) - { - return $"{CollectionName}/{DeterministicGuid.MakeId(endpointName, endpointHostId.ToString())}"; - } - - public const string CollectionName = "KnownEndpoints"; - } -} \ No newline at end of file diff --git a/src/ServiceControl.Audit.Persistence/UnitOfWork/IAuditIngestionUnitOfWork.cs b/src/ServiceControl.Audit.Persistence/UnitOfWork/IAuditIngestionUnitOfWork.cs index 116f3ae013..01b18c6415 100644 --- a/src/ServiceControl.Audit.Persistence/UnitOfWork/IAuditIngestionUnitOfWork.cs +++ b/src/ServiceControl.Audit.Persistence/UnitOfWork/IAuditIngestionUnitOfWork.cs @@ -4,13 +4,11 @@ using System.Threading; using System.Threading.Tasks; using Auditing; - using Monitoring; using ServiceControl.SagaAudit; public interface IAuditIngestionUnitOfWork : IAsyncDisposable { Task RecordProcessedMessage(ProcessedMessage processedMessage, ReadOnlyMemory body = default, CancellationToken cancellationToken = default); Task RecordSagaSnapshot(SagaSnapshot sagaSnapshot, CancellationToken cancellationToken = default); - Task RecordKnownEndpoint(KnownEndpoint knownEndpoint, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.HttpApiRoutes.approved.txt b/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.HttpApiRoutes.approved.txt index bfcfbc190b..3e218d68a5 100644 --- a/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.HttpApiRoutes.approved.txt +++ b/src/ServiceControl.Audit.UnitTests/ApprovalFiles/APIApprovals.HttpApiRoutes.approved.txt @@ -6,7 +6,7 @@ GET /endpoints/{endpoint}/audit-count => ServiceControl.Audit.Auditing.MessagesV GET /endpoints/{endpoint}/messages => ServiceControl.Audit.Auditing.MessagesView.GetMessagesController:GetEndpointMessages(PagingInfo pagingInfo, SortInfo sortInfo, Boolean includeSystemMessages, String endpoint, CancellationToken cancellationToken) GET /endpoints/{endpoint}/messages/search => ServiceControl.Audit.Auditing.MessagesView.GetMessagesController:Search(PagingInfo pagingInfo, SortInfo sortInfo, String endpoint, String q, CancellationToken cancellationToken) GET /endpoints/{endpoint}/messages/search/{keyword} => ServiceControl.Audit.Auditing.MessagesView.GetMessagesController:SearchByKeyword(PagingInfo pagingInfo, SortInfo sortInfo, String endpoint, String keyword, CancellationToken cancellationToken) -GET /endpoints/known => ServiceControl.Audit.Monitoring.KnownEndpointsController:GetAll(PagingInfo pagingInfo, CancellationToken cancellationToken) +GET /endpoints/known => ServiceControl.Audit.Monitoring.KnownEndpointsController:GetAll(PagingInfo pagingInfo) GET /instance-info => ServiceControl.Audit.Infrastructure.WebApi.RootController:Config() GET /messages => ServiceControl.Audit.Auditing.MessagesView.GetMessagesController:GetAllMessages(PagingInfo pagingInfo, SortInfo sortInfo, Boolean includeSystemMessages, CancellationToken cancellationToken) GET /messages/{id}/body => ServiceControl.Audit.Auditing.MessagesView.GetMessagesController:Get(String id, CancellationToken cancellationToken) diff --git a/src/ServiceControl.Audit/Auditing/AuditPersister.cs b/src/ServiceControl.Audit/Auditing/AuditPersister.cs index 136688919e..e9421a27aa 100644 --- a/src/ServiceControl.Audit/Auditing/AuditPersister.cs +++ b/src/ServiceControl.Audit/Auditing/AuditPersister.cs @@ -12,7 +12,6 @@ using NServiceBus.Transport; using Persistence.UnitOfWork; using ServiceControl.Audit.Persistence.Infrastructure; - using ServiceControl.Audit.Persistence.Monitoring; using ServiceControl.EndpointPlugin.Messages.SagaState; using ServiceControl.Infrastructure; using ServiceControl.SagaAudit; @@ -39,8 +38,6 @@ public async Task> Persist(IReadOnlyList(); - foreach (var context in contexts) { // Any message context that failed during processing will have a faulted task and should be skipped @@ -51,16 +48,6 @@ public async Task> Persist(IReadOnlyList> Persist(IReadOnlyList> Persist(IReadOnlyList observedEndpoints, ProcessedMessage processedMessage) - { - var uniqueEndpointId = $"{observedEndpoint.Name}{observedEndpoint.HostId}"; - if (!observedEndpoints.TryGetValue(uniqueEndpointId, out var knownEndpoint)) - { - knownEndpoint = new KnownEndpoint - { - Host = observedEndpoint.Host, - HostId = observedEndpoint.HostId, - LastSeen = processedMessage.ProcessedAt, - Name = observedEndpoint.Name, - Id = KnownEndpoint.MakeDocumentId(observedEndpoint.Name, observedEndpoint.HostId), - }; - observedEndpoints.Add(uniqueEndpointId, knownEndpoint); - } - - knownEndpoint.LastSeen = processedMessage.ProcessedAt > knownEndpoint.LastSeen ? processedMessage.ProcessedAt : knownEndpoint.LastSeen; - } - async Task ProcessMessage(MessageContext context) { if (context.Headers.TryGetValue(Headers.EnclosedMessageTypes, out var messageType) diff --git a/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs b/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs index bdbf4fc727..6334d612a6 100644 --- a/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs +++ b/src/ServiceControl.Audit/Infrastructure/WebApi/RootController.cs @@ -74,7 +74,7 @@ public OkObjectResult Config() settings.AuditQueue, settings.ForwardAuditMessages }, - Peristence = new + Persistence = new { settings.PersistenceType }, diff --git a/src/ServiceControl.Audit/Monitoring/KnownEndpoints/KnownEndpointsController.cs b/src/ServiceControl.Audit/Monitoring/KnownEndpoints/KnownEndpointsController.cs index 3b7fd5871b..fa64b559a3 100644 --- a/src/ServiceControl.Audit/Monitoring/KnownEndpoints/KnownEndpointsController.cs +++ b/src/ServiceControl.Audit/Monitoring/KnownEndpoints/KnownEndpointsController.cs @@ -1,27 +1,26 @@ namespace ServiceControl.Audit.Monitoring { using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; + using Auditing.MessagesView; using Infrastructure; using Infrastructure.WebApi; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; - using Persistence; using ServiceControl.Infrastructure.Auth; [ApiController] [Route("api")] - public class KnownEndpointsController(IAuditDataStore dataStore) : ControllerBase + public class KnownEndpointsController : ControllerBase { + // Backwards-compatibility stub: the audit instance no longer stores known endpoints, but older + // primary instances scatter-gather this route and expect a valid result. [Authorize(Policy = Permissions.AuditEndpointView)] [Route("endpoints/known")] [HttpGet] - public async Task> GetAll([FromQuery] PagingInfo pagingInfo, CancellationToken cancellationToken) + public IList GetAll([FromQuery] PagingInfo pagingInfo) { - var result = await dataStore.QueryKnownEndpoints(cancellationToken); - Response.WithQueryStatsAndPagingInfo(result.QueryStats, pagingInfo); - return result.Results; + Response.WithQueryStatsAndPagingInfo(QueryStatsInfo.Zero, pagingInfo); + return []; } } -} \ No newline at end of file +} diff --git a/src/ServiceControl/Monitoring/Web/EndpointsMonitoringController.cs b/src/ServiceControl/Monitoring/Web/EndpointsMonitoringController.cs index 0926075b59..8adf7d13c7 100644 --- a/src/ServiceControl/Monitoring/Web/EndpointsMonitoringController.cs +++ b/src/ServiceControl/Monitoring/Web/EndpointsMonitoringController.cs @@ -3,11 +3,9 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; - using CompositeViews.Messages; using Infrastructure.Auth; using Infrastructure.WebApi; using Microsoft.AspNetCore.Authorization; - using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using Persistence; @@ -22,7 +20,6 @@ public class EndpointUpdateModel [Route("api")] public class EndpointsMonitoringController( IEndpointInstanceMonitoring monitoring, - GetKnownEndpointsApi knownEndpointsApi, IMonitoringDataStore dataStore) : ControllerBase { @@ -66,13 +63,12 @@ public async Task DeleteEndpoint(Guid endpointId) [Authorize(Policy = Permissions.ErrorEndpointsView)] [Route("endpoints/known")] [HttpGet] - public async Task> KnownEndpoints([FromQuery] PagingInfo pagingInfo) + public IList KnownEndpoints([FromQuery] PagingInfo pagingInfo) { - QueryResult> result = - await knownEndpointsApi.Execute(new ScatterGatherContext(pagingInfo), Request.GetEncodedPathAndQuery()); + var knownEndpoints = monitoring.GetKnownEndpoints(); - Response.WithQueryStatsAndPagingInfo(result.QueryStats, pagingInfo); - return result.Results; + Response.WithQueryStatsAndPagingInfo(new QueryStatsInfo(string.Empty, knownEndpoints.Count, isStale: false), pagingInfo); + return knownEndpoints; } [Authorize(Policy = Permissions.ErrorEndpointsManage)] @@ -80,6 +76,11 @@ public async Task> KnownEndpoints([FromQuery] PagingIn [HttpPatch] public async Task Monitoring(Guid endpointId, [FromBody] EndpointUpdateModel data) { + if (!monitoring.HasEndpoint(endpointId)) + { + return NotFound(); + } + if (data.MonitorHeartbeat) { await monitoring.EnableMonitoring(endpointId); diff --git a/src/ServiceControl/Monitoring/Web/GetKnownEndpointsApi.cs b/src/ServiceControl/Monitoring/Web/GetKnownEndpointsApi.cs deleted file mode 100644 index d86a4c4f48..0000000000 --- a/src/ServiceControl/Monitoring/Web/GetKnownEndpointsApi.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace ServiceControl.Monitoring -{ - using System.Collections.Generic; - using System.Linq; - using System.Net.Http; - using System.Threading.Tasks; - using CompositeViews.Messages; - using Microsoft.AspNetCore.Http; - using Microsoft.Extensions.Logging; - using Persistence; - using Persistence.Infrastructure; - using ServiceBus.Management.Infrastructure.Settings; - - public class GetKnownEndpointsApi( - IEndpointInstanceMonitoring store, - Settings settings, - IHttpClientFactory httpClientFactory, - IHttpContextAccessor httpContextAccessor, - ILogger logger) - : ScatterGatherApi>(store, settings, httpClientFactory, httpContextAccessor, logger) - { - protected override Task>> LocalQuery(ScatterGatherContext input) - { - var knownEndpoints = DataStore.GetKnownEndpoints(); - - return Task.FromResult( - new QueryResult>( - knownEndpoints, - new QueryStatsInfo(string.Empty, knownEndpoints.Count, isStale: false) - ) - ); - } - - protected override IList ProcessResults(ScatterGatherContext input, QueryResult>[] results) => results.Where(p => p.Results != null).SelectMany(x => x.Results).Distinct(KnownEndpointsViewComparer.Instance).ToList(); - - class KnownEndpointsViewComparer : IEqualityComparer - { - public bool Equals(KnownEndpointsView x, KnownEndpointsView y) => y != null && x != null && x.Id.Equals(y.Id); - - public int GetHashCode(KnownEndpointsView obj) => obj.Id.GetHashCode(); - - public static KnownEndpointsViewComparer Instance = new KnownEndpointsViewComparer(); - } - } -} \ No newline at end of file