mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-01-26 06:39:45 -05:00
reorganized project
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
using System.Net;
|
||||
using Cleanuparr.Infrastructure.Services;
|
||||
using Infrastructure.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Polly;
|
||||
using Polly.Extensions.Http;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Dynamic configuration handler - this configures HttpClients on-demand based on stored configurations
|
||||
/// </summary>
|
||||
public class DynamicHttpClientConfiguration : IConfigureNamedOptions<HttpClientFactoryOptions>
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public DynamicHttpClientConfiguration(IServiceProvider serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public void Configure(string name, HttpClientFactoryOptions options)
|
||||
{
|
||||
var configStore = _serviceProvider.GetRequiredService<IHttpClientConfigStore>();
|
||||
|
||||
if (!configStore.TryGetConfiguration(name, out HttpClientConfig? config))
|
||||
return;
|
||||
|
||||
// Configure the HttpClient
|
||||
options.HttpClientActions.Add(httpClient =>
|
||||
{
|
||||
httpClient.Timeout = TimeSpan.FromSeconds(config.Timeout);
|
||||
});
|
||||
|
||||
// Configure the HttpMessageHandler based on type
|
||||
options.HttpMessageHandlerBuilderActions.Add(builder =>
|
||||
{
|
||||
ConfigureHandler(builder, config);
|
||||
|
||||
// Add retry policy if configured
|
||||
if (config.RetryConfig != null)
|
||||
{
|
||||
AddRetryPolicy(builder, config.RetryConfig);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ConfigureHandler(HttpMessageHandlerBuilder builder, HttpClientConfig config)
|
||||
{
|
||||
var certValidationService = _serviceProvider.GetRequiredService<CertificateValidationService>();
|
||||
|
||||
switch (config.Type)
|
||||
{
|
||||
case HttpClientType.WithRetry:
|
||||
builder.PrimaryHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = (sender, certificate, chain, policy) =>
|
||||
certValidationService.ShouldByPassValidationError(config.CertificateValidationType, sender, certificate, chain, policy)
|
||||
};
|
||||
break;
|
||||
|
||||
case HttpClientType.Deluge:
|
||||
builder.PrimaryHandler = new HttpClientHandler
|
||||
{
|
||||
AllowAutoRedirect = config.AllowAutoRedirect,
|
||||
UseCookies = true,
|
||||
CookieContainer = new CookieContainer(),
|
||||
AutomaticDecompression = config.AutomaticDecompression,
|
||||
ServerCertificateCustomValidationCallback = (sender, certificate, chain, policy) =>
|
||||
certValidationService.ShouldByPassValidationError(config.CertificateValidationType, sender, certificate, chain, policy),
|
||||
};
|
||||
break;
|
||||
|
||||
case HttpClientType.Default:
|
||||
default:
|
||||
// Use default handler with certificate validation
|
||||
var defaultHandler = new HttpClientHandler
|
||||
{
|
||||
ServerCertificateCustomValidationCallback = (sender, certificate, chain, policy) =>
|
||||
certValidationService.ShouldByPassValidationError(config.CertificateValidationType, sender, certificate, chain, policy)
|
||||
};
|
||||
builder.PrimaryHandler = defaultHandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void AddRetryPolicy(HttpMessageHandlerBuilder builder, RetryConfig retryConfig)
|
||||
{
|
||||
var retryPolicy = HttpPolicyExtensions
|
||||
.HandleTransientHttpError();
|
||||
|
||||
if (retryConfig.ExcludeUnauthorized)
|
||||
{
|
||||
retryPolicy = retryPolicy.OrResult(response =>
|
||||
!response.IsSuccessStatusCode && response.StatusCode != HttpStatusCode.Unauthorized);
|
||||
}
|
||||
else
|
||||
{
|
||||
retryPolicy = retryPolicy.OrResult(response => !response.IsSuccessStatusCode);
|
||||
}
|
||||
|
||||
var policy = retryPolicy.WaitAndRetryAsync(
|
||||
retryConfig.MaxRetries,
|
||||
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
|
||||
);
|
||||
|
||||
builder.AdditionalHandlers.Add(new PolicyHttpMessageHandler(policy));
|
||||
}
|
||||
|
||||
public void Configure(HttpClientFactoryOptions options)
|
||||
{
|
||||
// This is called for unnamed clients - we don't need to do anything here
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
using System.Net;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Persistence.Models.Configuration.General;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the dynamic HttpClient factory
|
||||
/// </summary>
|
||||
public class DynamicHttpClientFactory : IDynamicHttpClientFactory
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IHttpClientConfigStore _configStore;
|
||||
private readonly IHttpClientOptionsInvalidator _optionsInvalidator;
|
||||
private readonly ILogger<DynamicHttpClientFactory> _logger;
|
||||
|
||||
public DynamicHttpClientFactory(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IHttpClientConfigStore configStore,
|
||||
IHttpClientOptionsInvalidator optionsInvalidator,
|
||||
ILogger<DynamicHttpClientFactory> logger)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configStore = configStore;
|
||||
_optionsInvalidator = optionsInvalidator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public HttpClient CreateClient(string clientName, HttpClientConfig config)
|
||||
{
|
||||
_configStore.AddConfiguration(clientName, config);
|
||||
return _httpClientFactory.CreateClient(clientName);
|
||||
}
|
||||
|
||||
public HttpClient CreateClient(string clientName)
|
||||
{
|
||||
if (!_configStore.TryGetConfiguration(clientName, out _))
|
||||
{
|
||||
throw new InvalidOperationException($"No configuration found for client '{clientName}'. Register configuration first.");
|
||||
}
|
||||
|
||||
return _httpClientFactory.CreateClient(clientName);
|
||||
}
|
||||
|
||||
public void RegisterConfiguration(string clientName, HttpClientConfig config)
|
||||
{
|
||||
_configStore.AddConfiguration(clientName, config);
|
||||
}
|
||||
|
||||
public void RegisterRetryClient(string clientName, int timeout, RetryConfig retryConfig, CertificateValidationType certificateType)
|
||||
{
|
||||
var config = new HttpClientConfig
|
||||
{
|
||||
Name = clientName,
|
||||
Timeout = timeout,
|
||||
Type = HttpClientType.WithRetry,
|
||||
RetryConfig = retryConfig,
|
||||
CertificateValidationType = certificateType
|
||||
};
|
||||
|
||||
RegisterConfiguration(clientName, config);
|
||||
}
|
||||
|
||||
public void RegisterDelugeClient(string clientName, int timeout, RetryConfig retryConfig, CertificateValidationType certificateType)
|
||||
{
|
||||
var config = new HttpClientConfig
|
||||
{
|
||||
Name = clientName,
|
||||
Timeout = timeout,
|
||||
Type = HttpClientType.Deluge,
|
||||
RetryConfig = retryConfig,
|
||||
AllowAutoRedirect = true,
|
||||
CertificateValidationType = certificateType,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
};
|
||||
|
||||
RegisterConfiguration(clientName, config);
|
||||
}
|
||||
|
||||
public void RegisterDownloadClient(string clientName, int timeout, HttpClientType clientType, RetryConfig retryConfig, CertificateValidationType certificateType)
|
||||
{
|
||||
var config = new HttpClientConfig
|
||||
{
|
||||
Name = clientName,
|
||||
Timeout = timeout,
|
||||
Type = clientType,
|
||||
RetryConfig = retryConfig,
|
||||
CertificateValidationType = certificateType
|
||||
};
|
||||
|
||||
// Configure Deluge-specific settings if needed
|
||||
if (clientType == HttpClientType.Deluge)
|
||||
{
|
||||
config.AllowAutoRedirect = true;
|
||||
config.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
}
|
||||
|
||||
RegisterConfiguration(clientName, config);
|
||||
}
|
||||
|
||||
public void UnregisterConfiguration(string clientName)
|
||||
{
|
||||
_configStore.RemoveConfiguration(clientName);
|
||||
|
||||
// Also invalidate the cached options for this client
|
||||
_optionsInvalidator.InvalidateClient(clientName);
|
||||
|
||||
_logger.LogDebug("Unregistered and invalidated HTTP client configuration: {ClientName}", clientName);
|
||||
}
|
||||
|
||||
public void UpdateAllClientsFromGeneralConfig(GeneralConfig generalConfig)
|
||||
{
|
||||
var allConfigurations = _configStore.GetAllConfigurations().ToList();
|
||||
|
||||
if (!allConfigurations.Any())
|
||||
{
|
||||
_logger.LogDebug("No HTTP client configurations to update");
|
||||
return;
|
||||
}
|
||||
|
||||
var updatedConfigurations = allConfigurations.Select(kvp =>
|
||||
{
|
||||
var config = kvp.Value;
|
||||
|
||||
// Update timeout and certificate validation for all clients
|
||||
config.Timeout = generalConfig.HttpTimeout;
|
||||
config.CertificateValidationType = generalConfig.HttpCertificateValidation;
|
||||
|
||||
// Update retry configuration if it exists
|
||||
if (config.RetryConfig != null)
|
||||
{
|
||||
config.RetryConfig.MaxRetries = generalConfig.HttpMaxRetries;
|
||||
}
|
||||
|
||||
return new KeyValuePair<string, HttpClientConfig>(kvp.Key, config);
|
||||
}).ToList();
|
||||
|
||||
// Apply all updates to our configuration store
|
||||
_configStore.UpdateConfigurations(updatedConfigurations);
|
||||
|
||||
// CRITICAL: Invalidate IHttpClientFactory's cached configurations
|
||||
// This forces the factory to call our Configure() method again with updated settings
|
||||
var clientNames = updatedConfigurations.Select(kvp => kvp.Key).ToList();
|
||||
_optionsInvalidator.InvalidateClients(clientNames);
|
||||
|
||||
_logger.LogInformation("Updated and invalidated {Count} HTTP client configurations with new general settings: " +
|
||||
"Timeout={Timeout}s, MaxRetries={MaxRetries}, CertificateValidation={CertValidation}",
|
||||
updatedConfigurations.Count,
|
||||
generalConfig.HttpTimeout,
|
||||
generalConfig.HttpMaxRetries,
|
||||
generalConfig.HttpCertificateValidation);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetRegisteredClientNames()
|
||||
{
|
||||
return _configStore.GetAllConfigurations().Select(kvp => kvp.Key);
|
||||
}
|
||||
|
||||
public void InvalidateAllCachedConfigurations()
|
||||
{
|
||||
_optionsInvalidator.InvalidateAllClients();
|
||||
_logger.LogInformation("Force invalidated all HTTP client option caches");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Service collection extensions for the dynamic HTTP client system
|
||||
/// </summary>
|
||||
public static class DynamicHttpClientServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the dynamic HTTP client system to the service collection
|
||||
/// This replaces the traditional AddHttpClients method
|
||||
/// </summary>
|
||||
public static IServiceCollection AddDynamicHttpClients(this IServiceCollection services)
|
||||
{
|
||||
// Register the dynamic system components
|
||||
services.AddSingleton<IHttpClientConfigStore, HttpClientConfigStore>();
|
||||
services.AddSingleton<IConfigureOptions<HttpClientFactoryOptions>, DynamicHttpClientConfiguration>();
|
||||
services.AddSingleton<IDynamicHttpClientFactory, DynamicHttpClientFactory>();
|
||||
|
||||
// Register the cache invalidation service
|
||||
services.AddSingleton<IHttpClientOptionsInvalidator, HttpClientOptionsInvalidator>();
|
||||
|
||||
// Add base HttpClient factory
|
||||
services.AddHttpClient();
|
||||
|
||||
// Pre-register standard configurations using a hosted service
|
||||
services.AddHostedService<HttpClientConfigurationService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Net;
|
||||
using Cleanuparr.Domain.Enums;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for a dynamic HTTP client
|
||||
/// </summary>
|
||||
public class HttpClientConfig
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int Timeout { get; set; }
|
||||
public HttpClientType Type { get; set; }
|
||||
public RetryConfig? RetryConfig { get; set; }
|
||||
|
||||
// Deluge-specific settings
|
||||
public bool AllowAutoRedirect { get; set; } = true;
|
||||
public DecompressionMethods AutomaticDecompression { get; set; } = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
|
||||
public CertificateValidationType CertificateValidationType { get; set; } = CertificateValidationType.Enabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retry configuration for HTTP clients
|
||||
/// </summary>
|
||||
public class RetryConfig
|
||||
{
|
||||
public int MaxRetries { get; set; }
|
||||
public bool ExcludeUnauthorized { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Types of HTTP clients that can be configured
|
||||
/// </summary>
|
||||
public enum HttpClientType
|
||||
{
|
||||
Default,
|
||||
WithRetry,
|
||||
Deluge
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// In-memory implementation of the HTTP client configuration store
|
||||
/// </summary>
|
||||
public class HttpClientConfigStore : IHttpClientConfigStore
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, HttpClientConfig> _configurations = new();
|
||||
private readonly ConcurrentDictionary<string, RetryConfig> _retryConfigurations = new();
|
||||
|
||||
public bool TryGetConfiguration(string clientName, out HttpClientConfig config)
|
||||
{
|
||||
return _configurations.TryGetValue(clientName, out config!);
|
||||
}
|
||||
|
||||
public void AddConfiguration(string clientName, HttpClientConfig config)
|
||||
{
|
||||
_configurations.AddOrUpdate(clientName, config, (_, _) => config);
|
||||
}
|
||||
|
||||
public void RemoveConfiguration(string clientName)
|
||||
{
|
||||
_configurations.TryRemove(clientName, out _);
|
||||
_retryConfigurations.TryRemove(clientName, out _);
|
||||
}
|
||||
|
||||
public void AddRetryConfiguration(string clientName, RetryConfig retryConfig)
|
||||
{
|
||||
_retryConfigurations.AddOrUpdate(clientName, retryConfig, (key, oldValue) => retryConfig);
|
||||
}
|
||||
|
||||
public bool TryGetRetryConfiguration(string clientName, out RetryConfig retryConfig)
|
||||
{
|
||||
return _retryConfigurations.TryGetValue(clientName, out retryConfig!);
|
||||
}
|
||||
|
||||
public IEnumerable<KeyValuePair<string, HttpClientConfig>> GetAllConfigurations()
|
||||
{
|
||||
return _configurations.ToList(); // Return a snapshot to avoid collection modification issues
|
||||
}
|
||||
|
||||
public void UpdateConfigurations(IEnumerable<KeyValuePair<string, HttpClientConfig>> configurations)
|
||||
{
|
||||
foreach (var kvp in configurations)
|
||||
{
|
||||
_configurations.AddOrUpdate(kvp.Key, kvp.Value, (_, _) => kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using Cleanuparr.Persistence;
|
||||
using Cleanuparr.Shared.Helpers;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using DelugeService = Cleanuparr.Infrastructure.Features.DownloadClient.Deluge.DelugeService;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Background service to pre-register standard HttpClient configurations
|
||||
/// </summary>
|
||||
public class HttpClientConfigurationService : IHostedService
|
||||
{
|
||||
private readonly IDynamicHttpClientFactory _clientFactory;
|
||||
private readonly DataContext _dataContext;
|
||||
private readonly ILogger<HttpClientConfigurationService> _logger;
|
||||
|
||||
public HttpClientConfigurationService(
|
||||
IDynamicHttpClientFactory clientFactory,
|
||||
DataContext dataContext,
|
||||
ILogger<HttpClientConfigurationService> logger)
|
||||
{
|
||||
_clientFactory = clientFactory;
|
||||
_dataContext = dataContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = await _dataContext.GeneralConfigs
|
||||
.AsNoTracking()
|
||||
.FirstAsync(cancellationToken);
|
||||
|
||||
// Register the retry client (equivalent to Constants.HttpClientWithRetryName)
|
||||
_clientFactory.RegisterRetryClient(
|
||||
Constants.HttpClientWithRetryName,
|
||||
config.HttpTimeout,
|
||||
new RetryConfig
|
||||
{
|
||||
MaxRetries = config.HttpMaxRetries,
|
||||
ExcludeUnauthorized = true
|
||||
},
|
||||
config.HttpCertificateValidation
|
||||
);
|
||||
|
||||
// Register the Deluge client
|
||||
_clientFactory.RegisterDelugeClient(
|
||||
nameof(DelugeService),
|
||||
config.HttpTimeout,
|
||||
new RetryConfig
|
||||
{
|
||||
MaxRetries = config.HttpMaxRetries,
|
||||
ExcludeUnauthorized = true
|
||||
},
|
||||
config.HttpCertificateValidation
|
||||
);
|
||||
|
||||
_logger.LogInformation("Pre-registered standard HTTP client configurations");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to pre-register HTTP client configurations");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of HTTP client options invalidator using cache manipulation
|
||||
/// </summary>
|
||||
public class HttpClientOptionsInvalidator : IHttpClientOptionsInvalidator
|
||||
{
|
||||
private readonly IOptionsMonitorCache<HttpClientFactoryOptions> _optionsCache;
|
||||
private readonly ILogger<HttpClientOptionsInvalidator> _logger;
|
||||
|
||||
public HttpClientOptionsInvalidator(
|
||||
IOptionsMonitorCache<HttpClientFactoryOptions> optionsCache,
|
||||
ILogger<HttpClientOptionsInvalidator> logger)
|
||||
{
|
||||
_optionsCache = optionsCache;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void InvalidateClient(string clientName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove the cached configuration for this specific client
|
||||
_optionsCache.TryRemove(clientName);
|
||||
|
||||
_logger.LogDebug("Invalidated HTTP client options cache for client: {ClientName}", clientName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to invalidate HTTP client options cache for client: {ClientName}", clientName);
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateAllClients()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Clear the entire options cache
|
||||
_optionsCache.Clear();
|
||||
|
||||
_logger.LogDebug("Invalidated all HTTP client options cache entries");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to invalidate all HTTP client options cache entries");
|
||||
}
|
||||
}
|
||||
|
||||
public void InvalidateClients(IEnumerable<string> clientNames)
|
||||
{
|
||||
var clientNamesList = clientNames.ToList();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var clientName in clientNamesList)
|
||||
{
|
||||
_optionsCache.TryRemove(clientName);
|
||||
}
|
||||
|
||||
_logger.LogDebug("Invalidated HTTP client options cache for {Count} clients: {ClientNames}",
|
||||
clientNamesList.Count, string.Join(", ", clientNamesList));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to invalidate HTTP client options cache for multiple clients");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Cleanuparr.Domain.Enums;
|
||||
using Cleanuparr.Persistence.Models.Configuration.General;
|
||||
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Factory service to manage dynamic HttpClient creation
|
||||
/// </summary>
|
||||
public interface IDynamicHttpClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an HttpClient with the specified configuration and registers it for future use
|
||||
/// </summary>
|
||||
HttpClient CreateClient(string clientName, HttpClientConfig config);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an HttpClient using a previously registered configuration
|
||||
/// </summary>
|
||||
HttpClient CreateClient(string clientName);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a configuration for later use
|
||||
/// </summary>
|
||||
void RegisterConfiguration(string clientName, HttpClientConfig config);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a retry-enabled HttpClient configuration
|
||||
/// </summary>
|
||||
void RegisterRetryClient(string clientName, int timeout, RetryConfig retryConfig, CertificateValidationType certificateType);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a Deluge-specific HttpClient configuration
|
||||
/// </summary>
|
||||
void RegisterDelugeClient(string clientName, int timeout, RetryConfig retryConfig, CertificateValidationType certificateType);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a configuration for a download client
|
||||
/// </summary>
|
||||
void RegisterDownloadClient(string clientName, int timeout, HttpClientType clientType, RetryConfig retryConfig, CertificateValidationType certificateType);
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a configuration
|
||||
/// </summary>
|
||||
void UnregisterConfiguration(string clientName);
|
||||
|
||||
/// <summary>
|
||||
/// Updates all registered HTTP client configurations with new general config settings
|
||||
/// </summary>
|
||||
void UpdateAllClientsFromGeneralConfig(GeneralConfig generalConfig);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all currently registered client names
|
||||
/// </summary>
|
||||
IEnumerable<string> GetRegisteredClientNames();
|
||||
|
||||
/// <summary>
|
||||
/// Forces cache invalidation for all registered clients (for debugging/testing)
|
||||
/// </summary>
|
||||
void InvalidateAllCachedConfigurations();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Store interface for managing HttpClient configurations dynamically
|
||||
/// </summary>
|
||||
public interface IHttpClientConfigStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to get a configuration for the specified client name
|
||||
/// </summary>
|
||||
bool TryGetConfiguration(string clientName, out HttpClientConfig config);
|
||||
|
||||
/// <summary>
|
||||
/// Adds or updates a configuration for the specified client name
|
||||
/// </summary>
|
||||
void AddConfiguration(string clientName, HttpClientConfig config);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a configuration for the specified client name
|
||||
/// </summary>
|
||||
void RemoveConfiguration(string clientName);
|
||||
|
||||
/// <summary>
|
||||
/// Adds or updates a retry configuration for the specified client name
|
||||
/// </summary>
|
||||
void AddRetryConfiguration(string clientName, RetryConfig retryConfig);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all currently registered configurations
|
||||
/// </summary>
|
||||
IEnumerable<KeyValuePair<string, HttpClientConfig>> GetAllConfigurations();
|
||||
|
||||
/// <summary>
|
||||
/// Updates multiple configurations atomically
|
||||
/// </summary>
|
||||
void UpdateConfigurations(IEnumerable<KeyValuePair<string, HttpClientConfig>> configurations);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Cleanuparr.Infrastructure.Http.DynamicHttpClientSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Service for invalidating cached HTTP client configurations
|
||||
/// </summary>
|
||||
public interface IHttpClientOptionsInvalidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Invalidates the cached configuration for a specific client name
|
||||
/// </summary>
|
||||
/// <param name="clientName">The name of the client to invalidate</param>
|
||||
void InvalidateClient(string clientName);
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates all cached HTTP client configurations
|
||||
/// </summary>
|
||||
void InvalidateAllClients();
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates multiple client configurations
|
||||
/// </summary>
|
||||
/// <param name="clientNames">The names of the clients to invalidate</param>
|
||||
void InvalidateClients(IEnumerable<string> clientNames);
|
||||
}
|
||||
Reference in New Issue
Block a user