diff --git a/backend/src/MoShiro.Backend.Application/Query/QueryService.cs b/backend/src/MoShiro.Backend.Application/Query/QueryService.cs index c97921f..8bb0b7b 100644 --- a/backend/src/MoShiro.Backend.Application/Query/QueryService.cs +++ b/backend/src/MoShiro.Backend.Application/Query/QueryService.cs @@ -23,9 +23,11 @@ public sealed class QueryService private readonly ITestStore _tests; private readonly BackendOptions _options; private readonly TimeProvider _time; + private readonly AgentRuntime _runtime; - public QueryService(RangeResolver resolver, SourcePlanner planner, RowLoader loader, HotLayer hot, IEventStore events, ITestStore tests, BackendOptions options, TimeProvider time) + public QueryService(RangeResolver resolver, SourcePlanner planner, RowLoader loader, HotLayer hot, IEventStore events, ITestStore tests, BackendOptions options, TimeProvider time, AgentRuntime runtime) { + _runtime = runtime; _resolver = resolver; _planner = planner; _loader = loader; @@ -56,11 +58,16 @@ public sealed class QueryService // ───────────────────────── 单条线路的时序 ───────────────────────── + /// 这条线路现在是不是连着(Agent 报告了这个 Probe 的会话):连着的线路窗口以当前时间为终点,不去查“最后一个样本”——Backend 刚重启、热层和持久层还没追上时,后者会落后好几个小时,页面就显示成旧数据。 + private bool IsConnected(LineKey line) => + _runtime.TryGet(line.Agent, out AgentRuntimeState? state) && state.Probes.Any(p => p.Id == line.Probe.Value && p.IpVersion == line.IpVersion); + public async ValueTask> SeriesAsync(LineKey line, RangeRequest request, MetricSelection selection, CancellationToken ct) { // anchor=latest:离线或刚恢复的线路,窗口以它最后一个样本为终点(落在最近 5 秒之内就当作在线,仍以当前时间为终点) if (string.Equals(request.Anchor, "latest", StringComparison.OrdinalIgnoreCase) && request.To is null && request.From is null && request.Range is not null - && RangeResolver.TryParseSpan(request.Range, out long span)) + && RangeResolver.TryParseSpan(request.Range, out long span) + && !IsConnected(line)) { long now = _time.GetUtcNow().ToUnixTimeMilliseconds(); if (await _loader.LatestSampleMsAsync(line.Agent, line.Series, now, ct) is { } latest && latest < now - 5000)