first commit
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user