From 3b79c0eb6d0d17d76d9b86d3ef0395446c2d7152 Mon Sep 17 00:00:00 2001 From: HueByte Date: Thu, 19 Feb 2026 13:53:05 +0000 Subject: [PATCH] deploy: 159a28e89030da27232764de491035da51e29e01 --- .../EchoHub.Server.Irc.IrcGatewayService.html | 8 +- ...ub.Server.Services.SignalRBroadcaster.html | 8 +- changelog/index.html | 1 + changelog/toc.html | 3 + changelog/toc.json | 2 +- changelog/v0.2.2.html | 129 ++++++++++++++++++ index.json | 11 +- manifest.json | 10 ++ xrefmap.yml | 36 ++--- 9 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 changelog/v0.2.2.html diff --git a/api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html b/api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html index 03b7276..189070e 100644 --- a/api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html +++ b/api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html @@ -158,8 +158,8 @@ Class IrcGatewayService -

- IrcGatewayService(IOptions<IrcOptions>, IChatService, ILogger<IrcGatewayService>) +

+ IrcGatewayService(IOptions<IrcOptions>, IServiceProvider, ILogger<IrcGatewayService>)

@@ -167,14 +167,14 @@ Class IrcGatewayService
-
public IrcGatewayService(IOptions<IrcOptions> options, IChatService chatService, ILogger<IrcGatewayService> logger)
+
public IrcGatewayService(IOptions<IrcOptions> options, IServiceProvider services, ILogger<IrcGatewayService> logger)

Parameters

options IOptions<IrcOptions>
-
chatService IChatService
+
services IServiceProvider
logger ILogger<IrcGatewayService>
diff --git a/api/server/EchoHub.Server.Services.SignalRBroadcaster.html b/api/server/EchoHub.Server.Services.SignalRBroadcaster.html index d20f571..5258dc2 100644 --- a/api/server/EchoHub.Server.Services.SignalRBroadcaster.html +++ b/api/server/EchoHub.Server.Services.SignalRBroadcaster.html @@ -160,8 +160,8 @@ Class SignalRBroadcaster -

- SignalRBroadcaster(IHubContext<ChatHub, IEchoHubClient>, PresenceTracker) +

+ SignalRBroadcaster(IServiceProvider, PresenceTracker)

@@ -169,12 +169,12 @@ Class SignalRBroadcaster
-
public SignalRBroadcaster(IHubContext<ChatHub, IEchoHubClient> hubContext, PresenceTracker presenceTracker)
+
public SignalRBroadcaster(IServiceProvider serviceProvider, PresenceTracker presenceTracker)

Parameters

-
hubContext IHubContext<ChatHub, IEchoHubClient>
+
serviceProvider IServiceProvider
presenceTracker PresenceTracker
diff --git a/changelog/index.html b/changelog/index.html index 566750d..45589c8 100644 --- a/changelog/index.html +++ b/changelog/index.html @@ -90,6 +90,7 @@

Release history for EchoHub.

Releases

    +
  • v0.2.2 - Startup & Shutdown Fixes
  • v0.2.1 - Shutdown & CI Fixes
  • v0.2.0 - IRC Gateway
  • v0.1.1 - Directory Connection Self-Healing
  • diff --git a/changelog/toc.html b/changelog/toc.html index 9586b0a..28802e6 100644 --- a/changelog/toc.html +++ b/changelog/toc.html @@ -15,6 +15,9 @@
  • Overview
  • +
  • + v0.2.2 +
  • v0.2.1
  • diff --git a/changelog/toc.json b/changelog/toc.json index 9be0318..ee03155 100644 --- a/changelog/toc.json +++ b/changelog/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.1","href":"v0.2.1.html","topicHref":"v0.2.1.html"},{"name":"v0.2.0","href":"v0.2.0.html","topicHref":"v0.2.0.html"},{"name":"v0.1.1","href":"v0.1.1.html","topicHref":"v0.1.1.html"},{"name":"v0.1.0","href":"v0.1.0.html","topicHref":"v0.1.0.html"}]} +{"items":[{"name":"Overview","href":"index.html","topicHref":"index.html"},{"name":"v0.2.2","href":"v0.2.2.html","topicHref":"v0.2.2.html"},{"name":"v0.2.1","href":"v0.2.1.html","topicHref":"v0.2.1.html"},{"name":"v0.2.0","href":"v0.2.0.html","topicHref":"v0.2.0.html"},{"name":"v0.1.1","href":"v0.1.1.html","topicHref":"v0.1.1.html"},{"name":"v0.1.0","href":"v0.1.0.html","topicHref":"v0.1.0.html"}]} diff --git a/changelog/v0.2.2.html b/changelog/v0.2.2.html new file mode 100644 index 0000000..df57c4b --- /dev/null +++ b/changelog/v0.2.2.html @@ -0,0 +1,129 @@ + + + + + v0.2.2 - Startup & Shutdown Fixes | EchoHub Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    +
    +
    +
    Table of Contents
    + +
    +
    + +
    +
    +
    + +
    +
    + + + +
    + +
    +

    v0.2.2 - Startup & Shutdown Fixes

    + +

    Fixes

    +
      +
    • Fixed server hanging on startup when IRC gateway is enabled — circular DI dependency between IrcGatewayServiceIChatServiceIChatBroadcasterIrcBroadcaster caused the DI container to deadlock
    • +
    • Fixed SignalRBroadcaster eagerly resolving IHubContext<ChatHub> during DI construction, which could deadlock on some platforms — now lazy-resolves via IServiceProvider on first use
    • +
    • Simplified IRC service registration to use standard AddSingleton<IChatBroadcaster, IrcBroadcaster> instead of manual factory, breaking the circular resolution chain
    • +
    • Fixed server hanging on Ctrl+C — replaced await using with explicit dispose bounded to 3 seconds, so a stuck HubConnection can no longer block shutdown
    • +
    • Reduced host shutdown timeout from 30s (default) to 5s
    • +
    • Caught OperationCanceledException in the directory service reconnect loop so cancellation exits immediately instead of propagating through dispose
    • +
    +

    Refactoring

    +
      +
    • Replaced primary constructors with standard constructor injection across all server classes for consistency
    • +
    + +
    + + + + + +
    + +
    + +
    +
    + +
    + + + + diff --git a/index.json b/index.json index fa8c5c1..ab456ca 100644 --- a/index.json +++ b/index.json @@ -387,7 +387,7 @@ "api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html": { "href": "api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html", "title": "Class IrcGatewayService | EchoHub Documentation", - "summary": "Class IrcGatewayService Namespace EchoHub.Server.Irc Assembly EchoHub.Server.Irc.dll public sealed class IrcGatewayService : BackgroundService, IDisposable Inheritance object BackgroundService IrcGatewayService Implements IDisposable Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors IrcGatewayService(IOptions, IChatService, ILogger) public IrcGatewayService(IOptions options, IChatService chatService, ILogger logger) Parameters options IOptions chatService IChatService logger ILogger Properties Connections public IReadOnlyDictionary Connections { get; } Property Value IReadOnlyDictionary Options public IrcOptions Options { get; } Property Value IrcOptions Methods ExecuteAsync(CancellationToken) protected override Task ExecuteAsync(CancellationToken stoppingToken) Parameters stoppingToken CancellationToken Returns Task GetConnectionsInChannel(string) public IEnumerable GetConnectionsInChannel(string channelName) Parameters channelName string Returns IEnumerable StopAsync(CancellationToken) public override Task StopAsync(CancellationToken cancellationToken) Parameters cancellationToken CancellationToken Returns Task" + "summary": "Class IrcGatewayService Namespace EchoHub.Server.Irc Assembly EchoHub.Server.Irc.dll public sealed class IrcGatewayService : BackgroundService, IDisposable Inheritance object BackgroundService IrcGatewayService Implements IDisposable Inherited Members object.GetType() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors IrcGatewayService(IOptions, IServiceProvider, ILogger) public IrcGatewayService(IOptions options, IServiceProvider services, ILogger logger) Parameters options IOptions services IServiceProvider logger ILogger Properties Connections public IReadOnlyDictionary Connections { get; } Property Value IReadOnlyDictionary Options public IrcOptions Options { get; } Property Value IrcOptions Methods ExecuteAsync(CancellationToken) protected override Task ExecuteAsync(CancellationToken stoppingToken) Parameters stoppingToken CancellationToken Returns Task GetConnectionsInChannel(string) public IEnumerable GetConnectionsInChannel(string channelName) Parameters channelName string Returns IEnumerable StopAsync(CancellationToken) public override Task StopAsync(CancellationToken cancellationToken) Parameters cancellationToken CancellationToken Returns Task" }, "api/server-irc/EchoHub.Server.Irc.IrcMessage.html": { "href": "api/server-irc/EchoHub.Server.Irc.IrcMessage.html", @@ -522,7 +522,7 @@ "api/server/EchoHub.Server.Services.SignalRBroadcaster.html": { "href": "api/server/EchoHub.Server.Services.SignalRBroadcaster.html", "title": "Class SignalRBroadcaster | EchoHub Documentation", - "summary": "Class SignalRBroadcaster Namespace EchoHub.Server.Services Assembly EchoHub.Server.dll public class SignalRBroadcaster : IChatBroadcaster Inheritance object SignalRBroadcaster Implements IChatBroadcaster Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors SignalRBroadcaster(IHubContext, PresenceTracker) public SignalRBroadcaster(IHubContext hubContext, PresenceTracker presenceTracker) Parameters hubContext IHubContext presenceTracker PresenceTracker Methods SendChannelUpdatedAsync(ChannelDto, string?) public Task SendChannelUpdatedAsync(ChannelDto channel, string? channelName = null) Parameters channel ChannelDto channelName string Returns Task SendErrorAsync(string, string) public Task SendErrorAsync(string connectionId, string message) Parameters connectionId string message string Returns Task SendMessageToChannelAsync(string, MessageDto) public Task SendMessageToChannelAsync(string channelName, MessageDto message) Parameters channelName string message MessageDto Returns Task SendUserJoinedAsync(string, string, string?) public Task SendUserJoinedAsync(string channelName, string username, string? excludeConnectionId = null) Parameters channelName string username string excludeConnectionId string Returns Task SendUserLeftAsync(string, string) public Task SendUserLeftAsync(string channelName, string username) Parameters channelName string username string Returns Task SendUserStatusChangedAsync(List, UserPresenceDto) public Task SendUserStatusChangedAsync(List channelNames, UserPresenceDto presence) Parameters channelNames List presence UserPresenceDto Returns Task" + "summary": "Class SignalRBroadcaster Namespace EchoHub.Server.Services Assembly EchoHub.Server.dll public class SignalRBroadcaster : IChatBroadcaster Inheritance object SignalRBroadcaster Implements IChatBroadcaster Inherited Members object.GetType() object.MemberwiseClone() object.ToString() object.Equals(object) object.Equals(object, object) object.ReferenceEquals(object, object) object.GetHashCode() Constructors SignalRBroadcaster(IServiceProvider, PresenceTracker) public SignalRBroadcaster(IServiceProvider serviceProvider, PresenceTracker presenceTracker) Parameters serviceProvider IServiceProvider presenceTracker PresenceTracker Methods SendChannelUpdatedAsync(ChannelDto, string?) public Task SendChannelUpdatedAsync(ChannelDto channel, string? channelName = null) Parameters channel ChannelDto channelName string Returns Task SendErrorAsync(string, string) public Task SendErrorAsync(string connectionId, string message) Parameters connectionId string message string Returns Task SendMessageToChannelAsync(string, MessageDto) public Task SendMessageToChannelAsync(string channelName, MessageDto message) Parameters channelName string message MessageDto Returns Task SendUserJoinedAsync(string, string, string?) public Task SendUserJoinedAsync(string channelName, string username, string? excludeConnectionId = null) Parameters channelName string username string excludeConnectionId string Returns Task SendUserLeftAsync(string, string) public Task SendUserLeftAsync(string channelName, string username) Parameters channelName string username string Returns Task SendUserStatusChangedAsync(List, UserPresenceDto) public Task SendUserStatusChangedAsync(List channelNames, UserPresenceDto presence) Parameters channelNames List presence UserPresenceDto Returns Task" }, "api/server/EchoHub.Server.Services.html": { "href": "api/server/EchoHub.Server.Services.html", @@ -557,7 +557,7 @@ "changelog/index.html": { "href": "changelog/index.html", "title": "Changelog | EchoHub Documentation", - "summary": "Changelog Release history for EchoHub. Releases v0.2.1 - Shutdown & CI Fixes v0.2.0 - IRC Gateway v0.1.1 - Directory Connection Self-Healing v0.1.0 - Initial Release" + "summary": "Changelog Release history for EchoHub. Releases v0.2.2 - Startup & Shutdown Fixes v0.2.1 - Shutdown & CI Fixes v0.2.0 - IRC Gateway v0.1.1 - Directory Connection Self-Healing v0.1.0 - Initial Release" }, "changelog/v0.1.0.html": { "href": "changelog/v0.1.0.html", @@ -579,6 +579,11 @@ "title": "v0.2.1 - Shutdown & CI Fixes | EchoHub Documentation", "summary": "v0.2.1 - Shutdown & CI Fixes Fixes Fixed server hanging on Ctrl+C when the directory server is unreachable — StopAsync now cancels background services before disposing connections Fixed IRC gateway shutdown blocking indefinitely on unresponsive clients — send operations are now bounded to 2 seconds Fixed CI release workflow not having full git history for building release notes (fetch-depth: 0) Fixed workflow_dispatch trigger breaking change detection when github.event.before is empty Improvements GitHub releases now include a commit list and version diff link instead of generic auto-generated notes GitHub releases link to the full changelog on the docs site" }, + "changelog/v0.2.2.html": { + "href": "changelog/v0.2.2.html", + "title": "v0.2.2 - Startup & Shutdown Fixes | EchoHub Documentation", + "summary": "v0.2.2 - Startup & Shutdown Fixes Fixes Fixed server hanging on startup when IRC gateway is enabled — circular DI dependency between IrcGatewayService → IChatService → IChatBroadcaster → IrcBroadcaster caused the DI container to deadlock Fixed SignalRBroadcaster eagerly resolving IHubContext during DI construction, which could deadlock on some platforms — now lazy-resolves via IServiceProvider on first use Simplified IRC service registration to use standard AddSingleton instead of manual factory, breaking the circular resolution chain Fixed server hanging on Ctrl+C — replaced await using with explicit dispose bounded to 3 seconds, so a stuck HubConnection can no longer block shutdown Reduced host shutdown timeout from 30s (default) to 5s Caught OperationCanceledException in the directory service reconnect loop so cancellation exits immediately instead of propagating through dispose Refactoring Replaced primary constructors with standard constructor injection across all server classes for consistency" + }, "index.html": { "href": "index.html", "title": "EchoHub Documentation | EchoHub Documentation", diff --git a/manifest.json b/manifest.json index a0fab97..903efcf 100644 --- a/manifest.json +++ b/manifest.json @@ -1668,6 +1668,16 @@ }, "version": "" }, + { + "type": "Conceptual", + "source_relative_path": "changelog/v0.2.2.md", + "output": { + ".html": { + "relative_path": "changelog/v0.2.2.html" + } + }, + "version": "" + }, { "type": "Resource", "source_relative_path": "images/hue_icon.svg", diff --git a/xrefmap.yml b/xrefmap.yml index 2c0fc55..dd22858 100644 --- a/xrefmap.yml +++ b/xrefmap.yml @@ -9514,15 +9514,15 @@ references: commentId: T:EchoHub.Server.Irc.IrcGatewayService fullName: EchoHub.Server.Irc.IrcGatewayService nameWithType: IrcGatewayService -- uid: EchoHub.Server.Irc.IrcGatewayService.#ctor(Microsoft.Extensions.Options.IOptions{EchoHub.Server.Irc.IrcOptions},EchoHub.Core.Contracts.IChatService,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Irc.IrcGatewayService}) - name: IrcGatewayService(IOptions, IChatService, ILogger) - href: api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html#EchoHub_Server_Irc_IrcGatewayService__ctor_Microsoft_Extensions_Options_IOptions_EchoHub_Server_Irc_IrcOptions__EchoHub_Core_Contracts_IChatService_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Irc_IrcGatewayService__ - commentId: M:EchoHub.Server.Irc.IrcGatewayService.#ctor(Microsoft.Extensions.Options.IOptions{EchoHub.Server.Irc.IrcOptions},EchoHub.Core.Contracts.IChatService,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Irc.IrcGatewayService}) - name.vb: New(IOptions(Of IrcOptions), IChatService, ILogger(Of IrcGatewayService)) - fullName: EchoHub.Server.Irc.IrcGatewayService.IrcGatewayService(Microsoft.Extensions.Options.IOptions, EchoHub.Core.Contracts.IChatService, Microsoft.Extensions.Logging.ILogger) - fullName.vb: EchoHub.Server.Irc.IrcGatewayService.New(Microsoft.Extensions.Options.IOptions(Of EchoHub.Server.Irc.IrcOptions), EchoHub.Core.Contracts.IChatService, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Irc.IrcGatewayService)) - nameWithType: IrcGatewayService.IrcGatewayService(IOptions, IChatService, ILogger) - nameWithType.vb: IrcGatewayService.New(IOptions(Of IrcOptions), IChatService, ILogger(Of IrcGatewayService)) +- uid: EchoHub.Server.Irc.IrcGatewayService.#ctor(Microsoft.Extensions.Options.IOptions{EchoHub.Server.Irc.IrcOptions},System.IServiceProvider,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Irc.IrcGatewayService}) + name: IrcGatewayService(IOptions, IServiceProvider, ILogger) + href: api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html#EchoHub_Server_Irc_IrcGatewayService__ctor_Microsoft_Extensions_Options_IOptions_EchoHub_Server_Irc_IrcOptions__System_IServiceProvider_Microsoft_Extensions_Logging_ILogger_EchoHub_Server_Irc_IrcGatewayService__ + commentId: M:EchoHub.Server.Irc.IrcGatewayService.#ctor(Microsoft.Extensions.Options.IOptions{EchoHub.Server.Irc.IrcOptions},System.IServiceProvider,Microsoft.Extensions.Logging.ILogger{EchoHub.Server.Irc.IrcGatewayService}) + name.vb: New(IOptions(Of IrcOptions), IServiceProvider, ILogger(Of IrcGatewayService)) + fullName: EchoHub.Server.Irc.IrcGatewayService.IrcGatewayService(Microsoft.Extensions.Options.IOptions, System.IServiceProvider, Microsoft.Extensions.Logging.ILogger) + fullName.vb: EchoHub.Server.Irc.IrcGatewayService.New(Microsoft.Extensions.Options.IOptions(Of EchoHub.Server.Irc.IrcOptions), System.IServiceProvider, Microsoft.Extensions.Logging.ILogger(Of EchoHub.Server.Irc.IrcGatewayService)) + nameWithType: IrcGatewayService.IrcGatewayService(IOptions, IServiceProvider, ILogger) + nameWithType.vb: IrcGatewayService.New(IOptions(Of IrcOptions), IServiceProvider, ILogger(Of IrcGatewayService)) - uid: EchoHub.Server.Irc.IrcGatewayService.#ctor* name: IrcGatewayService href: api/server-irc/EchoHub.Server.Irc.IrcGatewayService.html#EchoHub_Server_Irc_IrcGatewayService__ctor_ @@ -10726,15 +10726,15 @@ references: commentId: T:EchoHub.Server.Services.SignalRBroadcaster fullName: EchoHub.Server.Services.SignalRBroadcaster nameWithType: SignalRBroadcaster -- uid: EchoHub.Server.Services.SignalRBroadcaster.#ctor(Microsoft.AspNetCore.SignalR.IHubContext{EchoHub.Server.Hubs.ChatHub,EchoHub.Core.Contracts.IEchoHubClient},EchoHub.Server.Services.PresenceTracker) - name: SignalRBroadcaster(IHubContext, PresenceTracker) - href: api/server/EchoHub.Server.Services.SignalRBroadcaster.html#EchoHub_Server_Services_SignalRBroadcaster__ctor_Microsoft_AspNetCore_SignalR_IHubContext_EchoHub_Server_Hubs_ChatHub_EchoHub_Core_Contracts_IEchoHubClient__EchoHub_Server_Services_PresenceTracker_ - commentId: M:EchoHub.Server.Services.SignalRBroadcaster.#ctor(Microsoft.AspNetCore.SignalR.IHubContext{EchoHub.Server.Hubs.ChatHub,EchoHub.Core.Contracts.IEchoHubClient},EchoHub.Server.Services.PresenceTracker) - name.vb: New(IHubContext(Of ChatHub, IEchoHubClient), PresenceTracker) - fullName: EchoHub.Server.Services.SignalRBroadcaster.SignalRBroadcaster(Microsoft.AspNetCore.SignalR.IHubContext, EchoHub.Server.Services.PresenceTracker) - fullName.vb: EchoHub.Server.Services.SignalRBroadcaster.New(Microsoft.AspNetCore.SignalR.IHubContext(Of EchoHub.Server.Hubs.ChatHub, EchoHub.Core.Contracts.IEchoHubClient), EchoHub.Server.Services.PresenceTracker) - nameWithType: SignalRBroadcaster.SignalRBroadcaster(IHubContext, PresenceTracker) - nameWithType.vb: SignalRBroadcaster.New(IHubContext(Of ChatHub, IEchoHubClient), PresenceTracker) +- uid: EchoHub.Server.Services.SignalRBroadcaster.#ctor(System.IServiceProvider,EchoHub.Server.Services.PresenceTracker) + name: SignalRBroadcaster(IServiceProvider, PresenceTracker) + href: api/server/EchoHub.Server.Services.SignalRBroadcaster.html#EchoHub_Server_Services_SignalRBroadcaster__ctor_System_IServiceProvider_EchoHub_Server_Services_PresenceTracker_ + commentId: M:EchoHub.Server.Services.SignalRBroadcaster.#ctor(System.IServiceProvider,EchoHub.Server.Services.PresenceTracker) + name.vb: New(IServiceProvider, PresenceTracker) + fullName: EchoHub.Server.Services.SignalRBroadcaster.SignalRBroadcaster(System.IServiceProvider, EchoHub.Server.Services.PresenceTracker) + fullName.vb: EchoHub.Server.Services.SignalRBroadcaster.New(System.IServiceProvider, EchoHub.Server.Services.PresenceTracker) + nameWithType: SignalRBroadcaster.SignalRBroadcaster(IServiceProvider, PresenceTracker) + nameWithType.vb: SignalRBroadcaster.New(IServiceProvider, PresenceTracker) - uid: EchoHub.Server.Services.SignalRBroadcaster.#ctor* name: SignalRBroadcaster href: api/server/EchoHub.Server.Services.SignalRBroadcaster.html#EchoHub_Server_Services_SignalRBroadcaster__ctor_