Fixed compilation error where Infrastructure layer was referencing API layer (ColaFlow.API.Hubs). This violated the dependency inversion principle and Clean Architecture layering rules. Changes: - Moved McpNotificationHub from ColaFlow.API/Hubs to ColaFlow.Modules.Mcp.Infrastructure/Hubs - Updated McpNotificationHub to inherit directly from Hub instead of BaseHub - Copied necessary helper methods (GetCurrentUserId, GetCurrentTenantId, GetTenantGroupName) to avoid cross-layer dependency - Updated McpNotificationService to use new namespace (ColaFlow.Modules.Mcp.Infrastructure.Hubs) - Updated Program.cs to import new Hub namespace - Updated McpNotificationServiceTests to use new namespace - Kept BaseHub in API layer for ProjectHub and NotificationHub Architecture Impact: - Infrastructure layer no longer depends on API layer - Proper dependency flow: API -> Infrastructure -> Application -> Domain - McpNotificationHub is now properly encapsulated within the MCP module 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
136 lines
5.6 KiB
C#
136 lines
5.6 KiB
C#
using ColaFlow.Modules.Mcp.Application.DTOs.Notifications;
|
|
using ColaFlow.Modules.Mcp.Application.Services;
|
|
using ColaFlow.Modules.Mcp.Infrastructure.Hubs;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace ColaFlow.Modules.Mcp.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// Implementation of IMcpNotificationService using SignalR
|
|
/// </summary>
|
|
public class McpNotificationService : IMcpNotificationService
|
|
{
|
|
private readonly IHubContext<McpNotificationHub> _hubContext;
|
|
private readonly ILogger<McpNotificationService> _logger;
|
|
|
|
public McpNotificationService(
|
|
IHubContext<McpNotificationHub> hubContext,
|
|
ILogger<McpNotificationService> logger)
|
|
{
|
|
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
|
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
|
}
|
|
|
|
public async Task NotifyPendingChangeCreatedAsync(
|
|
PendingChangeCreatedNotification notification,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var groupName = GetPendingChangeGroupName(notification.PendingChangeId);
|
|
var tenantGroupName = GetTenantGroupName(notification.TenantId);
|
|
|
|
_logger.LogInformation(
|
|
"Sending PendingChangeCreated notification - PendingChangeId={PendingChangeId}, EntityType={EntityType}, Operation={Operation}",
|
|
notification.PendingChangeId, notification.EntityType, notification.Operation);
|
|
|
|
// Send to both: specific pending change subscribers AND all tenant members
|
|
await _hubContext.Clients
|
|
.Groups(groupName, tenantGroupName)
|
|
.SendAsync("PendingChangeCreated", notification, cancellationToken);
|
|
|
|
_logger.LogDebug(
|
|
"PendingChangeCreated notification sent - Groups=[{GroupName}, {TenantGroupName}]",
|
|
groupName, tenantGroupName);
|
|
}
|
|
|
|
public async Task NotifyPendingChangeApprovedAsync(
|
|
PendingChangeApprovedNotification notification,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var groupName = GetPendingChangeGroupName(notification.PendingChangeId);
|
|
var tenantGroupName = GetTenantGroupName(notification.TenantId);
|
|
|
|
_logger.LogInformation(
|
|
"Sending PendingChangeApproved notification - PendingChangeId={PendingChangeId}, EntityType={EntityType}, ApprovedBy={ApprovedBy}",
|
|
notification.PendingChangeId, notification.EntityType, notification.ApprovedBy);
|
|
|
|
await _hubContext.Clients
|
|
.Groups(groupName, tenantGroupName)
|
|
.SendAsync("PendingChangeApproved", notification, cancellationToken);
|
|
|
|
_logger.LogDebug(
|
|
"PendingChangeApproved notification sent - Groups=[{GroupName}, {TenantGroupName}]",
|
|
groupName, tenantGroupName);
|
|
}
|
|
|
|
public async Task NotifyPendingChangeRejectedAsync(
|
|
PendingChangeRejectedNotification notification,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var groupName = GetPendingChangeGroupName(notification.PendingChangeId);
|
|
var tenantGroupName = GetTenantGroupName(notification.TenantId);
|
|
|
|
_logger.LogInformation(
|
|
"Sending PendingChangeRejected notification - PendingChangeId={PendingChangeId}, Reason={Reason}, RejectedBy={RejectedBy}",
|
|
notification.PendingChangeId, notification.Reason, notification.RejectedBy);
|
|
|
|
await _hubContext.Clients
|
|
.Groups(groupName, tenantGroupName)
|
|
.SendAsync("PendingChangeRejected", notification, cancellationToken);
|
|
|
|
_logger.LogDebug(
|
|
"PendingChangeRejected notification sent - Groups=[{GroupName}, {TenantGroupName}]",
|
|
groupName, tenantGroupName);
|
|
}
|
|
|
|
public async Task NotifyPendingChangeAppliedAsync(
|
|
PendingChangeAppliedNotification notification,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var groupName = GetPendingChangeGroupName(notification.PendingChangeId);
|
|
var tenantGroupName = GetTenantGroupName(notification.TenantId);
|
|
|
|
_logger.LogInformation(
|
|
"Sending PendingChangeApplied notification - PendingChangeId={PendingChangeId}, Result={Result}",
|
|
notification.PendingChangeId, notification.Result);
|
|
|
|
await _hubContext.Clients
|
|
.Groups(groupName, tenantGroupName)
|
|
.SendAsync("PendingChangeApplied", notification, cancellationToken);
|
|
|
|
_logger.LogDebug(
|
|
"PendingChangeApplied notification sent - Groups=[{GroupName}, {TenantGroupName}]",
|
|
groupName, tenantGroupName);
|
|
}
|
|
|
|
public async Task NotifyPendingChangeExpiredAsync(
|
|
PendingChangeExpiredNotification notification,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var groupName = GetPendingChangeGroupName(notification.PendingChangeId);
|
|
var tenantGroupName = GetTenantGroupName(notification.TenantId);
|
|
|
|
_logger.LogInformation(
|
|
"Sending PendingChangeExpired notification - PendingChangeId={PendingChangeId}, ExpiredAt={ExpiredAt}",
|
|
notification.PendingChangeId, notification.ExpiredAt);
|
|
|
|
await _hubContext.Clients
|
|
.Groups(groupName, tenantGroupName)
|
|
.SendAsync("PendingChangeExpired", notification, cancellationToken);
|
|
|
|
_logger.LogDebug(
|
|
"PendingChangeExpired notification sent - Groups=[{GroupName}, {TenantGroupName}]",
|
|
groupName, tenantGroupName);
|
|
}
|
|
|
|
private static string GetPendingChangeGroupName(Guid pendingChangeId)
|
|
{
|
|
return $"pending-change-{pendingChangeId}";
|
|
}
|
|
|
|
private static string GetTenantGroupName(Guid tenantId)
|
|
{
|
|
return $"tenant-{tenantId}";
|
|
}
|
|
}
|