fix(query): a connected line is always anchored at now, whatever the stores have caught up to [CI]
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful
ci/woodpecker/push/dev-image Pipeline failed

This commit is contained in:
justme committed 2026-10-19 10:48:38 +08:00
1 parent e1ec7c9b04
commit 5594d1cc86
1 file changed
+9 -2
@@ -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
// ───────────────────────── 单条线路的时序 ─────────────────────────
/// <summary>这条线路现在是不是连着(Agent 报告了这个 Probe 的会话):连着的线路窗口以当前时间为终点,不去查“最后一个样本”——Backend 刚重启、热层和持久层还没追上时,后者会落后好几个小时,页面就显示成旧数据。</summary>
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<Result<SeriesResult>> 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)