78 lines
2.9 KiB
C#
78 lines
2.9 KiB
C#
using Quartz;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using Warehouse.IServices;
|
||
using VolPro.Entity.DomainModels;
|
||
using System;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Warehouse.IRepositories;
|
||
|
||
namespace VolPro.Warehouse.Services;
|
||
|
||
/// <summary>
|
||
/// 心跳超时检测任务。扫描心跳超时 30 秒的网关节点,标记为离线,
|
||
/// 并级联标记该节点下所有设备为离线。
|
||
/// Cron 建议: 每 15 秒 ("0/15 * * * * ?")
|
||
///
|
||
/// 设备与网关的关联通过 AdapterCode 前缀匹配(如设备 AdapterCode="MC4:31ku" 匹配网关 AdapterTypes="MC4:31ku")。
|
||
/// </summary>
|
||
public class HeartbeatMonitorJob : IJob
|
||
{
|
||
private readonly IServiceProvider _sp;
|
||
public HeartbeatMonitorJob(IServiceProvider sp) { _sp = sp; }
|
||
|
||
public async Task Execute(IJobExecutionContext? context)
|
||
{
|
||
var sp = _sp;
|
||
if (sp == null) return;
|
||
|
||
var gwSvc = sp.GetService<Igateway_nodesService>();
|
||
var gwRepo = sp.GetService<Igateway_nodesRepository>();
|
||
var devRepo = sp.GetService<Ibase_deviceRepository>();
|
||
if (gwSvc == null || gwRepo == null || devRepo == 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 = "离线";
|
||
try { gwRepo.Update(node); } catch { }
|
||
Console.WriteLine($"[HeartbeatMonitorJob] 网关 {node.NodeCode} 心跳超时,标记离线");
|
||
|
||
// 级联标记该网关下所有设备离线(批量 SQL)
|
||
try
|
||
{
|
||
var adapterPrefixes = (node.AdapterTypes ?? "")
|
||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||
.Select(t => t.Trim()).ToList();
|
||
|
||
if (adapterPrefixes.Any())
|
||
{
|
||
var allDevices = await devRepo.FindAsIQueryable(
|
||
d => d.IsOnline == "在线").ToListAsync();
|
||
var matched = allDevices
|
||
.Where(d => adapterPrefixes.Any(p => (d.AdapterCode ?? "").StartsWith(p)))
|
||
.ToList();
|
||
|
||
if (matched.Any())
|
||
{
|
||
foreach (var dev in matched) dev.IsOnline = "离线";
|
||
devRepo.UpdateRange(matched);
|
||
Console.WriteLine($"[HeartbeatMonitorJob] 级联 {matched.Count} 台设备离线");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.Error.WriteLine($"[HeartbeatMonitorJob] 级联离线失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|