first commit

This commit is contained in:
yanpeng200212
2026-10-08 10:43:59 +08:00
commit 8430ba0452
288 changed files with 29595 additions and 0 deletions
@@ -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);
}