♻️ Updated discovery resolver

This commit is contained in:
2025-12-13 19:28:24 +08:00
parent 3a7140f0a6
commit 7ecb64742f
15 changed files with 157 additions and 72 deletions

View File

@@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("develop");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "develop"; });

View File

@@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("drive");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "drive"; });

View File

@@ -5,7 +5,7 @@ using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("gateway");
builder.ConfigureAppKestrel(builder.Configuration, maxRequestBodySize: long.MaxValue, enableGrpc: false);

View File

@@ -9,7 +9,7 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "insight"; });
builder.AddServiceDefaults();
builder.AddServiceDefaults("insight");
builder.ConfigureAppKestrel(builder.Configuration);

View File

@@ -27,7 +27,6 @@ public class ThoughtProvider
private readonly PostService.PostServiceClient _postClient;
private readonly AccountService.AccountServiceClient _accountClient;
private readonly IConfiguration _configuration;
private readonly ServiceRegistrar _registrar;
private readonly Dictionary<string, Kernel> _kernels = new();
private readonly Dictionary<string, string> _serviceProviders = new();
@@ -38,11 +37,9 @@ public class ThoughtProvider
public ThoughtProvider(
IConfiguration configuration,
PostService.PostServiceClient postServiceClient,
AccountService.AccountServiceClient accountServiceClient,
ServiceRegistrar registrar
AccountService.AccountServiceClient accountServiceClient
)
{
_registrar = registrar;
_postClient = postServiceClient;
_accountClient = accountServiceClient;
_configuration = configuration;
@@ -105,8 +102,8 @@ public class ThoughtProvider
// Add gRPC clients for Thought Plugins
builder.Services.AddServiceDiscoveryCore();
builder.Services.AddServiceDiscovery();
builder.Services.AddAccountService(_registrar);
builder.Services.AddSphereService(_registrar);
builder.Services.AddAccountService();
builder.Services.AddSphereService();
builder.Plugins.AddFromObject(new SnAccountKernelPlugin(_accountClient));
builder.Plugins.AddFromObject(new SnPostKernelPlugin(_postClient));

View File

@@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("pass");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "pass"; });

View File

@@ -14,7 +14,9 @@
"dotnetRunMessages": true,
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Development",
"HTTP_PORTS": "5010",
"GRPC_PORT": "6010"
}
}
}

View File

@@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("ring");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "ring"; });

View File

@@ -3,6 +3,7 @@ using DysonNetwork.Shared.Cache;
using DysonNetwork.Shared.Registry;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
@@ -27,7 +28,8 @@ public static class Extensions
private const string HealthEndpointPath = "/health";
private const string AlivenessEndpointPath = "/alive";
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder, string serviceName)
where TBuilder : IHostApplicationBuilder
{
// Allow unencrypted grpc
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
@@ -37,6 +39,7 @@ public static class Extensions
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.AddServiceDiscoveryCore();
builder.Services.ConfigureHttpClientDefaults(http =>
{
@@ -54,18 +57,24 @@ public static class Extensions
// });
var etcdClient = new EtcdClient(builder.Configuration.GetConnectionString("Registrar"));
var registrar = new ServiceRegistrar(etcdClient);
builder.Services.AddSingleton<IClock>(SystemClock.Instance);
builder.Services.AddSingleton(etcdClient);
builder.Services.AddSingleton(registrar);
builder.Services.AddSingleton<ServiceRegistrar>();
builder.Services.AddHostedService<ServiceRegistrarHostedService>();
builder.Services.AddSingleton<IServiceEndpointProviderFactory, RegistrarServiceEndpointFactory>();
builder.Services.AddRingService(registrar);
builder.Services.AddAuthService(registrar);
builder.Services.AddAccountService(registrar);
builder.Services.AddSphereService(registrar);
builder.Services.AddDriveService(registrar);
builder.Services.AddDevelopService(registrar);
if (serviceName != "ring")
builder.Services.AddRingService();
if (serviceName != "pass")
builder.Services.AddAuthService();
if (serviceName != "pass")
builder.Services.AddAccountService();
if (serviceName != "sphere")
builder.Services.AddSphereService();
if (serviceName != "drive")
builder.Services.AddDriveService();
if (serviceName != "develop")
builder.Services.AddDevelopService();
builder.AddNatsClient("Queue");
builder.AddRedisClient("Cache", configureOptions: opts => { opts.AbortOnConnectFail = false; });

View File

@@ -0,0 +1,38 @@
using System.Diagnostics.CodeAnalysis;
using dotnet_etcd;
using Microsoft.Extensions.ServiceDiscovery;
namespace DysonNetwork.Shared.Registry;
/// <summary>
/// A factory for creating <see cref="RegistrarServiceEndpointProvider"/> instances.
/// </summary>
public class RegistrarServiceEndpointFactory(EtcdClient etcdClient) : IServiceEndpointProviderFactory
{
/// <summary>
/// Tries to create a provider for the given query.
/// </summary>
/// <remarks>
/// This factory creates a provider for any service name. It supports a convention
/// where the service name can include the service part, e.g., "my-service.http" or "my-service.grpc".
/// If the service part is not specified, it defaults to "http".
/// </remarks>
public bool TryCreateProvider(ServiceEndpointQuery query, [NotNullWhen(true)] out IServiceEndpointProvider? provider)
{
var serviceName = query.ServiceName;
var servicePart = "grpc"; // Default to "grpc"
var lastDot = serviceName.LastIndexOf('.');
if (lastDot > 0 && lastDot < serviceName.Length - 1)
{
var part = serviceName[(lastDot + 1)..];
// You might want to have a list of known parts.
// For now, we assume any suffix after a dot is a service part.
servicePart = part;
serviceName = serviceName[..lastDot];
}
provider = new RegistrarServiceEndpointProvider(serviceName, servicePart, etcdClient);
return true;
}
}

View File

@@ -0,0 +1,41 @@
using System.Net;
using dotnet_etcd;
using Microsoft.Extensions.ServiceDiscovery;
namespace DysonNetwork.Shared.Registry;
/// <summary>
/// A service endpoint provider that resolves endpoints from an etcd registry.
/// </summary>
public class RegistrarServiceEndpointProvider(string serviceName, string servicePart, EtcdClient etcdClient)
: IServiceEndpointProvider
{
public ValueTask DisposeAsync()
{
GC.SuppressFinalize(this);
return ValueTask.CompletedTask;
}
/// <summary>
/// Populates the endpoints for the service.
/// </summary>
public async ValueTask PopulateAsync(IServiceEndpointBuilder endpoints, CancellationToken cancellationToken)
{
var prefix = $"/services/{serviceName}/{servicePart}/";
// Fetch service instances from etcd.
var response = await etcdClient.GetRangeAsync(prefix, cancellationToken: cancellationToken);
var instances = response.Kvs.Select(kv => kv.Value.ToStringUtf8());
foreach (var instance in instances)
{
// Instances are in "host:port" format.
var parts = instance.Split(':', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (parts.Length != 2 || !int.TryParse(parts[1], out var port)) continue;
var host = parts[0];
// Create a DnsEndPoint. The framework will use the original request's scheme (e.g., http, https).
endpoints.Endpoints.Add(ServiceEndpoint.Create(new DnsEndPoint(host, port)));
}
}
}

View File

@@ -7,11 +7,10 @@ namespace DysonNetwork.Shared.Registry;
public static class ServiceInjectionHelper
{
public static IServiceCollection AddRingService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddRingService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("ring", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<RingService.RingServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<RingService.RingServiceClient>(o => o.Address = new Uri("https://ring"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -19,17 +18,16 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddAuthService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddAuthService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("pass", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<AuthService.AuthServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<AuthService.AuthServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<PermissionService.PermissionServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<PermissionService.PermissionServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -37,11 +35,10 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddAccountService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddAccountService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("pass", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<AccountService.AccountServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<AccountService.AccountServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -49,42 +46,42 @@ public static class ServiceInjectionHelper
services
.AddGrpcClient<BotAccountReceiverService.BotAccountReceiverServiceClient>(o =>
o.Address = new Uri(instance)
o.Address = new Uri("https://pass")
)
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<ActionLogService.ActionLogServiceClient>(o => o.Address = new Uri(instance))
services.AddGrpcClient<ActionLogService.ActionLogServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<PaymentService.PaymentServiceClient>(o => o.Address = new Uri(instance))
services.AddGrpcClient<PaymentService.PaymentServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<WalletService.WalletServiceClient>(o => o.Address = new Uri(instance))
services.AddGrpcClient<WalletService.WalletServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<RealmService.RealmServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<RealmService.RealmServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddSingleton<RemoteRealmService>();
services
.AddGrpcClient<SocialCreditService.SocialCreditServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<SocialCreditService.SocialCreditServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<ExperienceService.ExperienceServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<ExperienceService.ExperienceServiceClient>(o => o.Address = new Uri("https://pass"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -92,16 +89,15 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddDriveService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddDriveService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("drive", "grpc").GetAwaiter().GetResult();
services.AddGrpcClient<FileService.FileServiceClient>(o => o.Address = new Uri(instance))
services.AddGrpcClient<FileService.FileServiceClient>(o => o.Address = new Uri("https://drive"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services.AddGrpcClient<FileReferenceService.FileReferenceServiceClient>(o =>
o.Address = new Uri("https://_grpc.drive"))
o.Address = new Uri("https://drive"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -109,17 +105,16 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddSphereService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddSphereService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("drive", "grpc").GetAwaiter().GetResult();
services
.AddGrpcClient<PostService.PostServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<PostService.PostServiceClient>(o => o.Address = new Uri("https://sphere"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
services
.AddGrpcClient<PublisherService.PublisherServiceClient>(o => o.Address = new Uri(instance))
.AddGrpcClient<PublisherService.PublisherServiceClient>(o => o.Address = new Uri("https://sphere"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);
@@ -127,11 +122,10 @@ public static class ServiceInjectionHelper
return services;
}
public static IServiceCollection AddDevelopService(this IServiceCollection services, ServiceRegistrar registrar)
public static IServiceCollection AddDevelopService(this IServiceCollection services)
{
var instance = registrar.GetServiceInstanceAsync("develop", "grpc").GetAwaiter().GetResult();
services.AddGrpcClient<CustomAppService.CustomAppServiceClient>(o =>
o.Address = new Uri(instance))
o.Address = new Uri("https://develop"))
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{ ServerCertificateCustomValidationCallback = (_, _, _, _) => true }
);

View File

@@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("sphere");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "sphere"; });

View File

@@ -8,7 +8,7 @@ using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddServiceDefaults("zone");
builder.Services.Configure<ServiceRegistrationOptions>(opts => { opts.Name = "zone"; });

View File

@@ -1,6 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAccessToken_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fb370f448e9f5fca62da785172d83a214319335e27ac4d51840349c6dce15d68_003FAccessToken_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AActionResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4f76d3d319d4497595e4095b28237676214908_003Ff8_003Fd5e7c1c7_003FActionResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAddressBinder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb392c538ecbd43fc8939688b86c17f3b27e108_003F4a_003Fc1e9fe39_003FAddressBinder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAesGcm_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3d932a3ff98244208ca84309a75a7734243600_003F2c_003F1063867b_003FAesGcm_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAny_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F331aca3f6f414013b09964063341351379060_003F67_003F87f868e3_003FAny_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AApnSender_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6aadc2cf048f477d8636fb2def7b73648200_003Fc5_003F2a1973a9_003FApnSender_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
@@ -23,6 +24,8 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AClaim_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa7fdc52b6e574ae7b9822133be91162a15800_003Ff7_003Feebffd8d_003FClaim_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AClusterConfig_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F3f_003F87f581ed_003FClusterConfig_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConcurrentDictionary_00602_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F1f443143201742669eeb211a435e32ae4c600_003F24_003F59c4e69f_003FConcurrentDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConfigurationServiceEndpointProviderFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fdb9ae21e10f787e1761eedbdba715debe7dd21d81a8e2280a0e54b16c5ac3a8f_003FConfigurationServiceEndpointProviderFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConfigurationServiceEndpointProvider_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9baba048e9b6902819ba22b06bf05ef99fb19e64a6a2801f57fd988b21a5f84_003FConfigurationServiceEndpointProvider_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConnectionMultiplexer_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F2ed0e2f073b1d77b98dadb822da09ee8a9dfb91bf29bf2bbaecb8750d7e74cc9_003FConnectionMultiplexer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AContainerResourceBuilderExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F19256b6d2a8a458692f07fe8d98d79e9161628_003Fd7_003F266d041b_003FContainerResourceBuilderExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AContractlessStandardResolver_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F0fb7a5f343ed4578a15c716986a3f17950c00_003F78_003F264ef090_003FContractlessStandardResolver_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
@@ -182,6 +185,7 @@
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATusDiskStore_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8bb08a178b5b43c5bac20a5a54159a5b2a800_003Fe1_003Fefd9af34_003FTusDiskStore_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATusDiskStore_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8bb08a178b5b43c5bac20a5a54159a5b2a800_003F1c_003F21999acd_003FTusDiskStore_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATypeNameHelper_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcbe513b2487e4beeb8618510c05a705ad460_003Fb3_003F557e4fad_003FTypeNameHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AUriExt_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fa13e1e644e9feecdc9b4ca95c3d6ce0b78c9f9ad7dbb464b4d99b66838564b_003FUriExt_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AUri_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5d2c480da9be415dab9be535bb6d08713cc00_003Fd0_003Fffc36a51_003FUri_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AValidationContext_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8bb08a178b5b43c5bac20a5a54159a5b2a800_003F6b_003F741ceebe_003FValidationContext_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWebApplicationBuilder_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F60a5479edf534f47a4511002a4d278881cb08_003F03_003Fef441701_003FWebApplicationBuilder_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>