Skip to content

The Darling viewer's sidebar dot and its Overview card disagree about a never-collected server #2473

Description

@erikdarlingdata

Found by review on #2470 (the Lite half, #2458). The duplication is the smaller half of it — the two surfaces already disagree on dev, which is the thing #2429's collapse was written to make impossible.

The disagreement

Both are stamped from the same ClassifyFreshness(LastCollectionTime, nowUtc) call, and they answer differently.

ServerSummaryItem.ApplyFreshness (ViewerDataService.Overview.cs:733):

var freshness = ClassifyFreshness(LastCollectionTime, nowUtc);
if (freshness == ServerFreshness.NeverCollected)
{
    IsOnline = null;
    HasCollectorErrors = false;
    AwaitingFirstCollection = true;
    return;
}

DarlingServer.ApplyFreshness (ViewerDataService.cs:130) — the sidebar row's:

var freshness = ServerSummaryItem.ClassifyFreshness(lastCollectionUtc, nowUtc);
IsOnline = freshness == ServerFreshness.NeverCollected ? null : freshness != ServerFreshness.Offline;
HasCollectorErrors = freshness == ServerFreshness.Stale;

There is no AwaitingFirstCollection on DarlingServer, and DotStatus (ViewerDataService.cs:116) has no arm for it:

public string DotStatus => IsOnline switch
{
    true => HasCollectorErrors ? "Warning" : "Online",
    false => "Offline",
    _ => "Unknown"
};

So for a registered-but-never-collected server, on the same screen:

sidebar row Overview card
word "Unknown" "Awaiting first collection"
colour no DataTrigger matches → ForegroundMutedBrush (grey) amber #FFD54F
tooltip none the card's, naming the state

MainWindow.xaml:531-537 has DataTriggers for Online / Offline / Warning only, so "Unknown" falls through to the muted default. The dot is silently the pre-#2429 answer.

This is the exact failure #2429 spent two review rounds on, and its own enum doc says why it should not be reachable:

with a single discriminant there is no combination left for the renderings to disagree about, because they no longer each decide.

ServerCardStatus.AwaitingFirstCollection exists specifically because "a red 'Offline' on a merely-queued server sent a 24-server field report chasing a phantom scheduler bug". The sidebar's answer is grey rather than red, so it is the milder version — but it is still the surface a reader points at first, and it is telling them something the card contradicts one panel over.

Why it was not done in #2470

#2470 collapsed Lite's copy onto ServerCardStatusRules.Classify (one Classify, one Word(), one Headline(), both surfaces rendering the result). The viewer cannot just take that:

What settling it looks like

  1. DarlingServer renders the viewer's ServerCardStatus instead of deriving its own ladder — which needs it to carry AwaitingFirstCollection (or, better, the classified ServerFreshness itself, since both ApplyFreshness implementations already start from it and immediately throw the discriminant away in favour of two booleans).
  2. MainWindow.xaml gains the fifth state, or the dot binds the enum rather than the string so an unhandled member cannot fall through to grey.
  3. The sidebar dot gets the tooltip its card already has, as Lite's did in Collapse the sidebar dot onto the status the Overview card renders (#2458) #2470.
  4. A pin in the shape both Say why Lite's card is amber, and which axis the word is about (#2437) #2451 and Collapse the sidebar dot onto the status the Overview card renders (#2458) #2470 landed: the words are written in one place, scanned syntax-agnostically. Collapse the sidebar dot onto the status the Overview card renders (#2458) #2470's experience is the argument for the syntax-agnostic form — Say why Lite's card is amber, and which axis the word is about (#2437) #2451's Assert.Equal(1, CountOccurrences(source, "IsOnline switch")) counted one literal in one file, and the copy it existed to forbid was in another file and written as if statements, so it evaded both axes at once.

The thing to decide first

What the viewer's sidebar dot should say for AwaitingFirstCollection. "Awaiting first collection" does not fit a dot, so it is a colour plus a tooltip — and the colour choice is the whole question. Amber matches the card and reads as "needs attention" for a server that is merely queued; grey matches today and reads as "no information", which is arguably honest for a server nothing is known about yet. The card already chose amber and wrote down why ("queued, not dead"), so matching it is the default — but it is worth saying out loud rather than inheriting, because the two surfaces are answering at different sizes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions