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;
///
/// Implementation of IMcpNotificationService using SignalR
///
public class McpNotificationService : IMcpNotificationService
{
private readonly IHubContext _hubContext;
private readonly ILogger _logger;
public McpNotificationService(
IHubContext hubContext,
ILogger 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}";
}
}