dotnet / dotnet/extensions

Service discovery does not refresh

Open
#7,013 2 comments 0 reactions 0 assignees View on GitHub
needs-area-label untriaged
Dominant language
C#
Stars
3.2k
Forks
894
Avg merge
1d 12h
Merged PRs (30d)
23

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

I've implemented an `IServiceEndpointProvider` that doesn't use `IChangeToken`. I would expect that `PopulateAsync` is called periodically, based on `ServiceDiscoveryOptions.RefreshPeriod`, which is documented as:

> Gets or sets the period between polling attempts for providers which do not support refresh notifications via `IChangeToken.ActiveChangeCallbacks`.

However, no refresh ever happens. The reason is because `ServiceEndpointWatcher` [never schedules the refresh timer when _any of the providers_ (so not mine) added a change token](https://github.com/dotnet/extensions/blob/0eb69ee79db77bd15df91678b36f69c73fba23a8/src/Libraries/Microsoft.Extensions.ServiceDiscovery/ServiceEndpointWatcher.cs#L158-L171):

```c#
// Check if we need to poll for updates or if we can register for change notification callbacks.
if (endpoints.ChangeToken.ActiveChangeCallbacks)
{
// Initiate a background refresh when the change token fires.
_changeTokenRegistration = endpoints.ChangeToken.RegisterChangeCallback(
static state => _ = ((ServiceEndpointWatcher)state!).RefreshAsync(force: false), this);

// Dispose the existing timer, if any, since we are reliant on change tokens for updates.
_pollingTimer?.Dispose();
_pollingTimer = null;
}
else
{
SchedulePollingTimer();
}
```

Because the configuration provider is added from `builder.Services.AddServiceDiscovery()` which is invoked from the ServiceDefaults project, there will always be a change token after `ServiceEndpointWatcher` has enumerated all providers.

Does this work as designed and is the documentation wrong, or is this a bug?

### Expected Behavior

Documented behavior to match with the implementation.

### Steps To Reproduce

- Create a new Aspire Starter project without output caching
- Implement `IServiceEndpointProviderFactory` / `IServiceEndpointProvider`
- Write a log line from `IServiceEndpointProvider.PopulateAsync`
- Add the factory to the service collection at startup, and configure `RefreshPeriod` to 1 second
- Hit the weather endpoint in the browser a few times and check the logs

### Exceptions (if any)

-

### .NET Version info

.NET 8

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.