using ECPBLL.Communication.Interfaces; using ECPDAL.Communication.DTOs; using Microsoft.AspNetCore.SignalR; namespace ECPSL.Communication.Hubs; /// /// Concrete SignalR push implementation of ECPBLL.Communication.Interfaces.ICommunicationPushService. /// Lives in ECPSL.Communication (where the Hub type must live per CLAUDE.md's SignalR folder rule) /// and is registered against the BLL-owned interface in CommunicationModule.Register — this is /// what lets CommentThreadBLL/CommentReactionBLL push via IHubContext without ECPBLL.Communication /// ever referencing ECPSL.Communication (which would create a circular project reference, since SL /// already depends on BLL). See ICommunicationPushService's doc-comment for the full rationale. /// public class CommunicationPushService( IHubContext _hubContext ) : ICommunicationPushService { private static string ObjectGroup(int objectTypeId, int objectId) => $"communication:{objectTypeId}:{objectId}"; private static string UserGroup(int userId) => $"communication:user:{userId}"; public async Task PushCommentAsync(int objectTypeId, int objectId, CommentThreadDTO comment, CancellationToken ct) => await _hubContext.Clients.Group(ObjectGroup(objectTypeId, objectId)) .ReceiveComment(comment).WaitAsync(ct).ConfigureAwait(false); public async Task PushReplyAsync(int objectTypeId, int objectId, CommentThreadDTO reply, CancellationToken ct) => await _hubContext.Clients.Group(ObjectGroup(objectTypeId, objectId)) .ReceiveReply(reply).WaitAsync(ct).ConfigureAwait(false); public async Task PushReactionAsync(int objectTypeId, int objectId, CommentReactionDTO reaction, CancellationToken ct) => await _hubContext.Clients.Group(ObjectGroup(objectTypeId, objectId)) .ReceiveReaction(reaction).WaitAsync(ct).ConfigureAwait(false); public async Task PushStatusChangeAsync(int objectTypeId, int objectId, int commentThreadId, byte newStatus, CancellationToken ct) => await _hubContext.Clients.Group(ObjectGroup(objectTypeId, objectId)) .ReceiveStatusChange(commentThreadId, newStatus).WaitAsync(ct).ConfigureAwait(false); public async Task PushMentionAsync(int mentionedUserId, CommentMentionDTO mention, CancellationToken ct) => await _hubContext.Clients.Group(UserGroup(mentionedUserId)) .ReceiveMention(mention).WaitAsync(ct).ConfigureAwait(false); public async Task PushErrorAsync(int userId, string errorMessage, CancellationToken ct) => await _hubContext.Clients.Group(UserGroup(userId)) .ReceiveError("ERROR", errorMessage).WaitAsync(ct).ConfigureAwait(false); }