Refactor classes to use constructor injection for dependencies

- Updated IrcBroadcaster to use constructor injection for IrcGatewayService.
- Refactored JwtTokenService to initialize configuration values in the constructor.
- Modified AuthController to use constructor injection for EchoHubDbContext and JwtTokenService.
- Refactored ChannelsController to utilize constructor injection for dependencies.
- Updated FilesController to use constructor injection for FileStorageService.
- Refactored ServerController to initialize EchoHubDbContext and IConfiguration via constructor.
- Modified UsersController to use constructor injection for EchoHubDbContext and ImageToAsciiService.
- Updated EchoHubDbContext to use constructor for DbContextOptions.
- Refactored ChatHub to use constructor injection for IChatService and ILogger.
- Modified ChatService to utilize constructor injection for dependencies.
- Refactored ServerDirectoryService to use constructor injection for IConfiguration, PresenceTracker, and ILogger.
This commit is contained in:
HueByte
2026-02-19 14:04:19 +01:00
parent 0422066851
commit 13297fd017
11 changed files with 248 additions and 156 deletions
@@ -2,19 +2,30 @@ using Microsoft.AspNetCore.SignalR.Client;
namespace EchoHub.Server.Services;
public sealed class ServerDirectoryService(
IConfiguration configuration,
PresenceTracker presenceTracker,
ILogger<ServerDirectoryService> logger) : BackgroundService
public sealed class ServerDirectoryService : BackgroundService
{
private const string DirectoryHubUrl = "https://echohub.voidcube.cloud/hubs/servers";
private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(30);
private static readonly TimeSpan ReconnectBaseDelay = TimeSpan.FromSeconds(2);
private static readonly TimeSpan ReconnectMaxDelay = TimeSpan.FromSeconds(30);
private readonly IConfiguration _configuration;
private readonly PresenceTracker _presenceTracker;
private readonly ILogger<ServerDirectoryService> _logger;
private HubConnection? _connection;
private int _lastReportedUserCount = -1;
public ServerDirectoryService(
IConfiguration configuration,
PresenceTracker presenceTracker,
ILogger<ServerDirectoryService> logger)
{
_configuration = configuration;
_presenceTracker = presenceTracker;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Console.Error.WriteLine("[DIAG] ServerDirectoryService.ExecuteAsync entered.");
@@ -22,27 +33,27 @@ public sealed class ServerDirectoryService(
await Task.Yield();
Console.Error.WriteLine("[DIAG] ServerDirectoryService.ExecuteAsync resumed after Task.Yield().");
var isPublic = configuration.GetValue<bool>("Server:PublicServer");
var isPublic = _configuration.GetValue<bool>("Server:PublicServer");
Console.Error.WriteLine($"[DIAG] ServerDirectoryService: PublicServer={isPublic}");
if (!isPublic)
{
logger.LogInformation("PublicServer is disabled — not registering with directory");
_logger.LogInformation("PublicServer is disabled — not registering with directory");
return;
}
var host = configuration["Server:PublicHost"];
var host = _configuration["Server:PublicHost"];
Console.Error.WriteLine($"[DIAG] ServerDirectoryService: PublicHost={host}");
if (string.IsNullOrWhiteSpace(host))
{
logger.LogWarning("PublicServer is enabled but Server:PublicHost is not set — skipping directory registration");
_logger.LogWarning("PublicServer is enabled but Server:PublicHost is not set — skipping directory registration");
return;
}
var serverName = configuration["Server:Name"] ?? "EchoHub Server";
var description = configuration["Server:Description"];
var serverName = _configuration["Server:Name"] ?? "EchoHub Server";
var description = _configuration["Server:Description"];
logger.LogInformation("PublicServer is enabled — connecting to EchoHubSpace directory as {Name} ({Host})", serverName, host);
_logger.LogInformation("PublicServer is enabled — connecting to EchoHubSpace directory as {Name} ({Host})", serverName, host);
// Outer loop: rebuilds the connection if automatic reconnect permanently fails
while (!stoppingToken.IsCancellationRequested)
@@ -57,7 +68,7 @@ public sealed class ServerDirectoryService(
connection.Reconnected += async _ =>
{
logger.LogInformation("Reconnected to directory — re-registering server");
_logger.LogInformation("Reconnected to directory — re-registering server");
_lastReportedUserCount = -1;
await RegisterAsync(serverName, description, host);
};
@@ -65,9 +76,9 @@ public sealed class ServerDirectoryService(
connection.Closed += ex =>
{
if (ex is not null)
logger.LogWarning(ex, "Directory connection permanently closed — will rebuild");
_logger.LogWarning(ex, "Directory connection permanently closed — will rebuild");
else
logger.LogWarning("Directory connection permanently closed — will rebuild");
_logger.LogWarning("Directory connection permanently closed — will rebuild");
connectionPermanentlyClosed.TrySetResult();
return Task.CompletedTask;
@@ -82,7 +93,7 @@ public sealed class ServerDirectoryService(
}
Console.Error.WriteLine("[DIAG] ServerDirectoryService: Connected successfully!");
logger.LogInformation("Successfully connected to EchoHubSpace API at {Url}", DirectoryHubUrl);
_logger.LogInformation("Successfully connected to EchoHubSpace API at {Url}", DirectoryHubUrl);
await RegisterAsync(serverName, description, host);
// Poll user count until the connection is permanently closed or cancellation
@@ -92,7 +103,7 @@ public sealed class ServerDirectoryService(
return;
// Connection was permanently closed — wait briefly then rebuild
logger.LogInformation("Rebuilding directory connection...");
_logger.LogInformation("Rebuilding directory connection...");
await Task.Delay(ReconnectBaseDelay, stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
@@ -129,7 +140,7 @@ public sealed class ServerDirectoryService(
{
attempt++;
var delay = GetBackoffDelay(attempt);
logger.LogWarning(ex, "Failed to connect to directory — retrying in {Delay}s", delay.TotalSeconds);
_logger.LogWarning(ex, "Failed to connect to directory — retrying in {Delay}s", delay.TotalSeconds);
await Task.Delay(delay, ct);
}
}
@@ -154,7 +165,7 @@ public sealed class ServerDirectoryService(
if (connection.State != HubConnectionState.Connected)
continue;
var currentCount = presenceTracker.GetOnlineUserCount();
var currentCount = _presenceTracker.GetOnlineUserCount();
if (currentCount == _lastReportedUserCount)
continue;
@@ -162,11 +173,11 @@ public sealed class ServerDirectoryService(
{
await connection.InvokeAsync("UpdateUserCount", currentCount, ct);
_lastReportedUserCount = currentCount;
logger.LogDebug("Updated directory user count to {Count}", currentCount);
_logger.LogDebug("Updated directory user count to {Count}", currentCount);
}
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to update user count on directory");
_logger.LogWarning(ex, "Failed to update user count on directory");
}
}
}
@@ -184,15 +195,15 @@ public sealed class ServerDirectoryService(
try
{
var userCount = presenceTracker.GetOnlineUserCount();
var userCount = _presenceTracker.GetOnlineUserCount();
var dto = new RegisterServerDto(name, description, host, userCount);
await _connection.InvokeAsync("RegisterServer", dto);
_lastReportedUserCount = userCount;
logger.LogInformation("Registered with directory as {Name} at {Host}", name, host);
_logger.LogInformation("Registered with directory as {Name} at {Host}", name, host);
}
catch (Exception ex)
{
logger.LogWarning(ex, "Failed to register with directory");
_logger.LogWarning(ex, "Failed to register with directory");
}
}