Skip to content

Retire known-endpoints scatter-gather and audit KnownEndpoints storage#5619

Draft
johnsimons wants to merge 1 commit into
masterfrom
john/last_seen
Draft

Retire known-endpoints scatter-gather and audit KnownEndpoints storage#5619
johnsimons wants to merge 1 commit into
masterfrom
john/last_seen

Conversation

@johnsimons

Copy link
Copy Markdown
Member

Why

While preparing the new EF persisters we traced what the audit instance's KnownEndpoint documents are actually for, and why the primary and audit instances each have their own KnownEndpoint with different fields (Monitored vs LastSeen).

1. Audit LastSeen is written but never read. AuditPersister keeps it updated to the max ProcessedAt, but the audit query strips it before returning, so no API, index, or query ever consumes it. It's a leftover from the pre-RavenDB5 retention cleaner (193c3cf, 2020) which deleted KnownEndpoints where LastSeen < cutoff. Since RavenDB 5, retention is handled by the @expires document metadata stamped on every store (RavenAuditIngestionUnitOfWork) — LastSeen plays no part.

2. The primary already learns about every endpoint via messaging, not the scatter-gather. The audit instance pushes RegisterNewEndpoint messages on first sight of an endpoint (DetectNewEndpointsFromAuditImportsEnricher); the primary persists it durably via CreateIfNotExists, which never clobbers a user's Monitored choice on re-announcement. The /endpoints/known scatter-gather only contributed edge cases: pre-4.5 endpoints (no HostId, never pushed), in-flight registrations, and endpoints deleted from the primary but still present in audit data.

3. The audit KnownEndpoints storage had exactly one writer and one reader. Writer: ingestion (RecordKnownEndpoint). Reader: the audit /endpoints/known route serving the scatter-gather. The RegisterNewEndpoint push doesn't touch the store (its dedup cache is in-memory only).

4. No shipping client needs the remote data. ServicePulse never calls /endpoints/known (the root document's known_endpoints_url is parsed into a store and never read; all endpoint UI flows use GET /endpoints, PATCH/DELETE /endpoints/{id}, heartbeats/stats, endpointssettings — all primary-local). ServiceInsight (supported until 2027-02-10) does call it via DefaultServiceControl.GetEndpoints(), but only consumes identity fields (endpoint_details + host_display_name) that the primary serves locally — never Monitored or LastSeen.

Removing this now means the audit EF persister needs no KnownEndpoints table at all.

What

Primary instance

  • GET /endpoints/known serves from the in-memory endpoint registry (same response shape and query-stats headers); GetKnownEndpointsApi deleted.
  • Bugfix: PATCH /endpoints/{id} now returns 404 for endpoints the primary doesn't know, instead of throwing KeyNotFoundException (500) — the endpoints[id]?. in EndpointInstanceMonitoring never null-checks because the dictionary indexer throws first. Scatter-gathered ids from audit-only endpoints could previously trigger this.

Audit instance

  • Ingestion no longer records KnownEndpoint documents; RecordKnownEndpoint, QueryKnownEndpoints, and the KnownEndpoint model are removed from the persistence seam and the RavenDB/InMemory implementations.
  • GET /endpoints/known remains as a backwards-compatibility stub returning an empty list with zero-count stats headers, so older primaries that still scatter-gather merge an empty result rather than a 404. Deletable in a future major, after ServiceInsight's deprecation (2027-02-10).

Compatibility

  • No route removals; response shapes unchanged. ServiceInsight's Endpoint Explorer keeps working against the primary route (its fallback to endpoints_url is not shape-compatible, so the route and the root document's known_endpoints_url must stay until ServiceInsight is deprecated).
  • Existing audit KnownEndpoint documents age out on their own via @expires — no migration.
  • Behavior change: endpoints visible only in audit data (pre-4.5 endpoints, in-flight registrations, primary-deleted endpoints) no longer appear in /endpoints/known. Toggling those endpoints already failed with a 500 before this change.
  • No interaction with the elastic-scale heartbeats work: TrackInstances, mute/unmute, and HeartbeatEndpointSettingsSyncHostedService all operate on the primary store and GET /endpoints.

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.
@johnsimons johnsimons self-assigned this Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant