Add Redis support for SignalR backplane and caching
- Introduced Redis configuration in appsettings.json to enable SignalR backplane functionality. - Updated Program.cs to conditionally configure SignalR with Redis if a connection string is provided. - Added Redis connection service registration in ApiBootstrap for distributed scenarios. - Included necessary package references for StackExchange.Redis and Microsoft.Extensions.Caching.StackExchangeRedis in project files. - Implemented password masking for Redis connection strings to enhance security.
This commit is contained in:
@@ -510,9 +510,56 @@ public static class ApiBootstrap
|
||||
services.AddTransient<ICacheService, CacheService>();
|
||||
services.AddSingleton<ITaskCache, TaskCache>();
|
||||
|
||||
// Redis (for SignalR backplane and other distributed scenarios)
|
||||
services.AddRedis(configuration);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddRedis(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
// Check if Redis is configured
|
||||
// Priority: ConnectionStrings:Redis (can be set via ConnectionStrings__Redis env var) > REDIS_URL env var
|
||||
var redisConnectionString = configuration.GetConnectionString("Redis")
|
||||
?? configuration["REDIS_URL"];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(redisConnectionString))
|
||||
{
|
||||
Console.WriteLine($"✅ Redis configured: {MaskRedisPassword(redisConnectionString)}");
|
||||
|
||||
// Register generic Redis connection service for various use cases
|
||||
// (SignalR backplane, distributed caching, pub/sub, etc.)
|
||||
services.AddSingleton<IRedisConnectionService, RedisConnectionService>();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("ℹ️ Redis not configured - running in single-instance mode");
|
||||
|
||||
// Register a no-op Redis service that returns null connections
|
||||
services.AddSingleton<IRedisConnectionService>(sp =>
|
||||
new RedisConnectionService(configuration, sp.GetRequiredService<ILogger<RedisConnectionService>>()));
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
private static string MaskRedisPassword(string connectionString)
|
||||
{
|
||||
if (connectionString.Contains("password=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var parts = connectionString.Split(',');
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
{
|
||||
if (parts[i].Trim().StartsWith("password=", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
parts[i] = "password=***";
|
||||
}
|
||||
}
|
||||
return string.Join(",", parts);
|
||||
}
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
private static IServiceCollection AddWorkers(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
if (configuration.GetValue<bool>("WorkerNotifyBundleBacktest", false))
|
||||
|
||||
Reference in New Issue
Block a user