using Microsoft.Extensions.Primitives; using Yarp.ReverseProxy.Configuration; using YarpGateway.Config; namespace YarpGateway.DynamicProxy; public class DynamicProxyConfigProvider : IProxyConfigProvider { private volatile IProxyConfig _config; private readonly DatabaseRouteConfigProvider _routeProvider; private readonly DatabaseClusterConfigProvider _clusterProvider; private readonly object _lock = new(); public DynamicProxyConfigProvider( DatabaseRouteConfigProvider routeProvider, DatabaseClusterConfigProvider clusterProvider) { _routeProvider = routeProvider; _clusterProvider = clusterProvider; UpdateConfig(); } public IProxyConfig GetConfig() { return _config; } public void UpdateConfig() { lock (_lock) { var routes = _routeProvider.GetRoutes(); var clusters = _clusterProvider.GetClusters(); _config = new InMemoryProxyConfig( routes, clusters, Array.Empty>() ); } } public async Task ReloadAsync() { await _routeProvider.ReloadAsync(); await _clusterProvider.ReloadAsync(); UpdateConfig(); } private class InMemoryProxyConfig : IProxyConfig { private static readonly CancellationChangeToken _nullChangeToken = new(new CancellationToken()); public InMemoryProxyConfig( IReadOnlyList routes, IReadOnlyList clusters, IReadOnlyList> transforms) { Routes = routes; Clusters = clusters; Transforms = transforms; } public IReadOnlyList Routes { get; } public IReadOnlyList Clusters { get; } public IReadOnlyList> Transforms { get; } public IChangeToken ChangeToken => _nullChangeToken; } }