Compare commits
2 Commits
0ed51baf20
...
4b410fdd9f
| Author | SHA1 | Date |
|---|---|---|
|
|
4b410fdd9f | |
|
|
91cb7a72db |
|
|
@ -24,7 +24,7 @@ namespace Hopetry.Services
|
|||
{
|
||||
var key = $"{Prefix}{info.MachineId}";
|
||||
var json = JsonConvert.SerializeObject(info);
|
||||
await _db.StringSetAsync(key, json, TimeSpan.FromDays(30));
|
||||
await _db.StringSetAsync(key, json, TimeSpan.FromMinutes(5));
|
||||
}
|
||||
|
||||
// 获取单个客户端信息
|
||||
|
|
@ -59,6 +59,51 @@ namespace Hopetry.Services
|
|||
return await _db.KeyDeleteAsync($"{Prefix}{machineId}");
|
||||
}
|
||||
|
||||
// 新增心跳键前缀
|
||||
private const string HeartbeatPrefix = "heartbeat:";
|
||||
|
||||
// 更新客户端心跳(核心新增方法)
|
||||
public async Task UpdateClientHeartbeatAsync(string machineId)
|
||||
{
|
||||
// 同时更新两个键的过期时间:
|
||||
// 1. 客户端信息键(保持长期有效)
|
||||
// 2. 心跳状态键(短期存活检测)
|
||||
var tasks = new List<Task>
|
||||
{
|
||||
// 刷新客户端信息过期时间(30天)
|
||||
_db.KeyExpireAsync($"{Prefix}{machineId}", TimeSpan.FromMinutes(5)),
|
||||
|
||||
// 设置/更新心跳状态(带5分钟过期)
|
||||
_db.StringSetAsync(
|
||||
$"{HeartbeatPrefix}{machineId}",
|
||||
DateTime.UtcNow.ToString("o"),
|
||||
expiry: TimeSpan.FromMinutes(5)
|
||||
)
|
||||
};
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
// 获取所有活跃客户端ID(基于心跳键)
|
||||
public async Task<List<string>> GetActiveClientIdsAsync()
|
||||
{
|
||||
var endpoints = _redis.GetEndPoints();
|
||||
var server = _redis.GetServer(endpoints.First());
|
||||
|
||||
// 注意:生产环境应改用SCAN
|
||||
var heartbeatKeys = server.Keys(pattern: $"{HeartbeatPrefix}*");
|
||||
|
||||
return heartbeatKeys
|
||||
.Select(k => k.ToString().Substring(HeartbeatPrefix.Length))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
// 检查客户端是否活跃
|
||||
public async Task<bool> IsClientActiveAsync(string machineId)
|
||||
{
|
||||
return await _db.KeyExistsAsync($"{HeartbeatPrefix}{machineId}");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_redis?.Dispose();
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ using Minio.Exceptions;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Security.AccessControl;
|
||||
using Microsoft.VisualBasic;
|
||||
using log4net.Util;
|
||||
|
||||
namespace HeBianGu.App.Disk
|
||||
{
|
||||
|
|
@ -119,6 +118,7 @@ namespace HeBianGu.App.Disk
|
|||
private IConfiguration config;
|
||||
private SemaphoreSlim _semaphore = new SemaphoreSlim(5);
|
||||
private Timer _progressTimer;
|
||||
private Timer _heartbeatTimer ;
|
||||
private bool _isTimerRunning = false;
|
||||
private object _timerLock = new object();
|
||||
private bool _isUploading = false; // 新增:标记是否有上传任务正在运行
|
||||
|
|
@ -129,6 +129,7 @@ namespace HeBianGu.App.Disk
|
|||
private int regionCount = 0;
|
||||
private ExplorerMinIOBehavior _explorerBehavior;
|
||||
private MinIOSearchBehavior _minioBehavior;
|
||||
private Hopetry.Provider.SystemInfo systemInfo;
|
||||
// 配置Redis连接
|
||||
private RedisService redis = new RedisService("175.27.168.120:6050,password=HopetryRedis1406,connectRetry=3");
|
||||
|
||||
|
|
@ -150,11 +151,14 @@ namespace HeBianGu.App.Disk
|
|||
DeleteFolderCommand = new AsyncRelayCommand(async () => await DeleteSelectedItemsAsync());
|
||||
DownloadCommand = new AsyncRelayCommand(async () => await DoDownloadCommand());
|
||||
SelectDirCommand = new CustomCommand(async () => await DoSelectDirCommand());
|
||||
systemInfo = SystemInfoCollector.Collect();
|
||||
//SelectItemsCommand = new AsyncRelayCommand(async () => await RelayCommand<SystemInfoModel>(SelectItem)SelectItem());
|
||||
// 初始化Timer
|
||||
_progressTimer = new Timer(1000);
|
||||
_progressTimer.Elapsed += UpdateProgress;
|
||||
_sendViewModel.UpLoadItems.CollectionChanged += (s, e) => { _sendViewModel.UpdateUploadingItems(); };
|
||||
_heartbeatTimer = new Timer(30_000);
|
||||
_heartbeatTimer.Elapsed += async (s, e) => await SendHeartbeatAsync();
|
||||
_sendViewModel.UpLoadItems.CollectionChanged += (s, e) => { _sendViewModel.UpdateUploadingItems(); };
|
||||
//加载上传完成列表
|
||||
GetCompletedFiles();
|
||||
}
|
||||
|
|
@ -210,6 +214,22 @@ namespace HeBianGu.App.Disk
|
|||
Application.Current.Dispatcher.Invoke(() => { _sendViewModel.Progress = progress; });
|
||||
}
|
||||
|
||||
//上传redis心跳检测
|
||||
private async Task SendHeartbeatAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 上报心跳并更新客户端信息
|
||||
//await redis.StoreClientInfoAsync(systemInfo);
|
||||
await redis.UpdateClientHeartbeatAsync(systemInfo.MachineId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 处理网络异常等
|
||||
Debug.WriteLine($"心跳上报失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void StartProgressTimer()
|
||||
{
|
||||
lock (_timerLock)
|
||||
|
|
@ -217,6 +237,7 @@ namespace HeBianGu.App.Disk
|
|||
if (!_isTimerRunning)
|
||||
{
|
||||
_progressTimer.Start();
|
||||
_heartbeatTimer.Start();
|
||||
_isTimerRunning = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -229,6 +250,7 @@ namespace HeBianGu.App.Disk
|
|||
if (_isTimerRunning)
|
||||
{
|
||||
_progressTimer.Stop();
|
||||
_heartbeatTimer.Stop();
|
||||
_isTimerRunning = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -401,7 +423,7 @@ namespace HeBianGu.App.Disk
|
|||
_isUploading = true;
|
||||
StartProgressTimer();
|
||||
// 收集系统信息
|
||||
var systemInfo = SystemInfoCollector.Collect();
|
||||
//var systemInfo = SystemInfoCollector.Collect();
|
||||
try
|
||||
{
|
||||
// 存储到Redis
|
||||
|
|
@ -877,8 +899,8 @@ namespace HeBianGu.App.Disk
|
|||
{
|
||||
await DeleteMinIOItems(selectedItems);
|
||||
|
||||
_explorerBehavior.RefreshMinIOPath(CurrentMinIOPath);
|
||||
MessageBox.Show($"已成功删除 {selectedItems.Count} 个项目");
|
||||
_explorerBehavior.RefreshMinIOPath(CurrentMinIOPath);
|
||||
SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue