Files
2026-10-08 10:43:59 +08:00

46 lines
1.9 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using F9WebAiTest.Api.Hubs;
using F9WebAiTest.Application.Dtos.Notice;
using F9WebAiTest.Application.Services.Notice;
using Microsoft.AspNetCore.SignalR;
namespace F9WebAiTest.Api.Services;
/// <summary>
/// 消息实时推送器实现:基于 SignalR 的 IHubContext 直接推送。
/// 无后台队列、无轮询——消息创建时同步完成投递与推送。
///
/// 在线判定:OnlineUserRegistry(Hub 连接/断开时登记的内存表)。
/// 之所以需要显式判定而不能依赖推送异常:SignalR 对"无连接的 Clients.User 调用"是静默成功的,
/// 不判定的话离线用户会被误记为推送成功。
///
/// 用户标识:由 NotificationUserIdProvider 统一取 JWT 的 "id" 声明,
/// 因此 Clients.User(userId) 可精准命中该用户的所有在线连接(支持多端同时在线)。
/// </summary>
public class NotificationPusher : INotificationPusher
{
private readonly IHubContext<NotificationHub> _hubContext;
public NotificationPusher(IHubContext<NotificationHub> hubContext)
{
_hubContext = hubContext;
}
/// <inheritdoc />
public bool IsOnline(long userId) => OnlineUserRegistry.IsOnline(userId);
/// <inheritdoc />
public async Task<bool> PushNewMessageAsync(long userId, NotificationMessageDto message, CancellationToken ct = default)
{
// 离线用户:不推送(消息已持久化,上线后拉取兜底),返回 false 由调用方标记 IsOffline
if (!OnlineUserRegistry.IsOnline(userId)) return false;
await _hubContext.Clients.User(userId.ToString()).SendAsync("ReceiveNotification", message, ct);
return true;
}
/// <inheritdoc />
public Task PushUnreadCountAsync(long userId, int unreadCount, int todoCount, CancellationToken ct = default)
=> _hubContext.Clients.User(userId.ToString())
.SendAsync("UnreadCountChanged", new { unreadCount, todoCount }, ct);
}