68 lines
2.4 KiB
C#
68 lines
2.4 KiB
C#
using Fleet.Core;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Monitor.Protocol;
|
|
|
|
namespace Monitor.Backend.Application;
|
|
|
|
/// <summary>重启后热层为空:从原始块回填最近 1 小时(低优先级、逐块让出)。完成之前查询规划器不会选用热层。</summary>
|
|
public sealed partial class HotLayerBackfill : BackgroundService
|
|
{
|
|
private readonly HotLayer _hot;
|
|
private readonly IRawStore _raw;
|
|
private readonly TimeProvider _time;
|
|
private readonly ILogger<HotLayerBackfill> _logger;
|
|
|
|
public HotLayerBackfill(HotLayer hot, IRawStore raw, TimeProvider time, ILogger<HotLayerBackfill> logger)
|
|
{
|
|
_hot = hot;
|
|
_raw = raw;
|
|
_time = time;
|
|
_logger = logger;
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
try
|
|
{
|
|
await RunAsync(stoppingToken);
|
|
}
|
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
|
{
|
|
// 正常停止
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 回填失败不应该让热层永远不可用:标记就绪,缺的部分会通过降级到 10s 层之外的查询体现
|
|
LogFailed(ex);
|
|
_hot.MarkReady();
|
|
}
|
|
}
|
|
|
|
/// <summary>回填(也供测试直接调用)。</summary>
|
|
public async Task RunAsync(CancellationToken ct)
|
|
{
|
|
long now = _time.GetUtcNow().ToUnixTimeMilliseconds();
|
|
long from = now - (long)HotLayer.Retention.TotalMilliseconds - 600_000;
|
|
foreach ((NodeId agent, string series) in await _raw.ListSeriesAsync(from, now, ct))
|
|
{
|
|
IReadOnlyList<RawChunkMeta> metas = await _raw.FindAsync(new RawQuery(agent, series, FromMs: from, ToMs: now, Limit: 2000), ct);
|
|
foreach (RawChunkMeta meta in metas.Where(m => m.TestId is null))
|
|
{
|
|
byte[]? bytes = await _raw.ReadAsync(meta, ct);
|
|
if (bytes is not null && RawChunkCodec.Decode(bytes).TryGet(out RawChunk? chunk, out _))
|
|
{
|
|
_hot.Merge(agent, series, chunk);
|
|
}
|
|
|
|
await Task.Yield();
|
|
}
|
|
}
|
|
|
|
_hot.MarkReady();
|
|
}
|
|
|
|
[LoggerMessage(Level = LogLevel.Error, Message = "hot layer backfill failed")]
|
|
private partial void LogFailed(Exception exception);
|
|
}
|