59 lines
2.2 KiB
C#
59 lines
2.2 KiB
C#
using Quartz;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Warehouse.IServices;
|
|
using VolPro.Entity.DomainModels;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace VolPro.Warehouse.Services;
|
|
|
|
/// <summary>
|
|
/// 心跳超时检测任务。扫描心跳超时 30 秒的网关节点,标记为离线,
|
|
/// 并级联标记该节点下所有设备为离线。
|
|
/// Cron 建议: 每 15 秒 ("0/15 * * * * ?")
|
|
/// </summary>
|
|
public class HeartbeatMonitorJob : IJob
|
|
{
|
|
public async Task Execute(IJobExecutionContext context)
|
|
{
|
|
var sp = (IServiceProvider)context.JobDetail.JobDataMap["ServiceProvider"];
|
|
var gwSvc = sp.GetService<Igateway_nodesService>();
|
|
var devSvc = sp.GetService<Ibase_deviceService>();
|
|
if (gwSvc == null) return;
|
|
|
|
var timeout = DateTime.Now.AddSeconds(-30);
|
|
|
|
// 扫描心跳超时的网关(当前在线但心跳超时)
|
|
var offlineNodes = await gwSvc.FindAsIQueryable(
|
|
x => x.IsOnline == "在线" && x.LastHeartbeat < timeout)
|
|
.ToListAsync();
|
|
|
|
foreach (var node in offlineNodes)
|
|
{
|
|
// 标记网关离线
|
|
node.IsOnline = "离线";
|
|
await gwSvc.FindAsIQueryable(x => x.NodeId == node.NodeId)
|
|
.FirstAsync(); // 确保实体被跟踪
|
|
// 直接通过 DbContext 更新
|
|
var dbProp = gwSvc.GetType().BaseType?.GetProperty("DbContext");
|
|
if (dbProp != null) continue; // fallback: 通过 FindAsIQueryable 重新获取更新
|
|
|
|
Console.WriteLine($"[HeartbeatMonitorJob] 网关 {node.NodeCode} 心跳超时,标记离线");
|
|
|
|
// 级联标记该网关下所有设备离线
|
|
if (devSvc != null)
|
|
{
|
|
var devices = await devSvc.FindAsIQueryable(
|
|
x => x.NodeId == node.NodeId && x.IsOnline == "在线")
|
|
.ToListAsync();
|
|
foreach (var dev in devices)
|
|
{
|
|
dev.IsOnline = "离线";
|
|
}
|
|
Console.WriteLine($"[HeartbeatMonitorJob] 级联 {devices.Count} 台设备离线");
|
|
}
|
|
}
|
|
}
|
|
}
|