Skip to content

fix(monitoring): report a standalone Apollo as streaming when it actually is - #50

Merged
vibesoftwarecoder merged 1 commit into
masterfrom
fix/warn-standalone-apollo-stall
Sep 11, 2026
Merged

fix(monitoring): report a standalone Apollo as streaming when it actually is#50
vibesoftwarecoder merged 1 commit into
masterfrom
fix/warn-standalone-apollo-stall

Conversation

@vibesoftwarecoder

Copy link
Copy Markdown
Owner

Addresses #23 — and found a live bug on the way.

The signal was wrong

HostApolloInfo.Streaming came from Apollo's serverinfo alone: state not ending in FREE, or currentgame != 0. Those describe a launched application, not a client session. Someone streaming the plain desktop — which is what a console Apollo is usually for — leaves currentgame at 0 and state at SUNSHINE_SERVER_FREE for the entire session.

Measured 2026-09-11:

now                     08:05:42
apollo log last written 07:39:47    <- encoder created, never torn down
encode (pid 10988)      15.9% -> 15.8% -> 15.8%   sustained
serverinfo              state = SUNSHINE_SERVER_FREE, currentgame = 0

So /api/host told the dashboard "not streaming" for the whole 26 minutes the host was streaming.

Streaming is now per-process GPU video encode OR the serverinfo signal, read through the same WMI GPU engine counters GpuMonitor already uses, filtered to the Apollo PID and the videoencode engine. Per process, never the GPU total — RustDesk encodes too, and a machine-wide reading answers a different question.

Verified in both directions on the reference host: False while idle with serverinfo FREE, and True during a live stream where serverinfo still insisted it was idle.

The warning #23 asked for

#23's own decomposition established the stall is not fixable here: stopping a seat's Apollo causes no reaction at all; ending the seat's RDP session is the desktop topology change any Apollo on the host reacts to — and a seat is an RDP session. What was wrong was that it happened invisibly: the operator interrupted someone and had no way to know.

SeatManager now logs before teardown when the standalone Apollo is streaming, naming the ~690 ms stall and that it self-recovers. It runs before the lifecycle gate is taken, so it adds no latency under the lock, and it can never block or fail a teardown — a seat that would not tear down because a status query timed out is a far worse bug than the one it reports.

Built on the old signal, this warning would have been silently dead for desktop streaming, which is the common case. That is why the signal was checked before being relied on rather than after — the same shape as the launch-on-connect watcher being gated off in #43.

Documentation

CLAUDE.md's non-destructive coexistence claim now states the exception, and that the cause is session churn rather than a second Apollo — the intuitive guess, and this issue's original premise, both wrong.

⚠️ Not yet verified

That the warning fires during a real teardown, and stays quiet when nothing is streaming. Both need seat churn, and the host was streaming while this was written. The signal it depends on is verified in both directions; the emission is not.

546 tests passing, 0 failing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw

…ally is

Addresses #23, and found a live bug on the way.

## The signal was wrong

HostApolloInfo.Streaming came from Apollo's serverinfo alone: state not ending
in FREE, or currentgame != 0. Those describe a launched APPLICATION, not a
client session. Someone streaming the plain desktop -- which is what a console
Apollo is usually for -- leaves currentgame at 0 and state at
SUNSHINE_SERVER_FREE for the entire session.

Measured 2026-09-11: the standalone Apollo encoding steadily at ~15.8% for 26
minutes, with an encoder created in its log and never torn down, still answered
state = SUNSHINE_SERVER_FREE, currentgame = 0. So /api/host showed the dashboard
"not streaming" for the whole time the host WAS streaming.

Streaming is now per-process GPU video encode OR the serverinfo signal, read
through the same WMI GPU engine counters GpuMonitor already uses, filtered to
the Apollo PID and the videoencode engine. Per process, never the GPU total --
RustDesk encodes too, and a machine-wide reading answers a different question.

Verified in both directions on the reference host: False while idle with
serverinfo FREE, and True during a live stream where serverinfo still insisted
it was idle.

## The warning #23 asked for

#23's decomposition established the stall is not fixable here: stopping a
seat's Apollo causes no reaction at all; ending the seat's RDP SESSION is the
desktop topology change any Apollo on the host reacts to, and a seat is an RDP
session. What was wrong was that it happened invisibly -- the operator
interrupted someone and had no way to know.

SeatManager now logs before teardown when the standalone Apollo is streaming,
naming the ~690 ms stall and that it self-recovers. It runs before the
lifecycle gate is taken, so it adds no latency under the lock, and it can never
block or fail a teardown -- a seat that would not tear down because a status
query timed out is a far worse bug than the one it reports.

⛔ Built on the OLD signal this warning would have been silently dead for
desktop streaming, which is the common case. That is why the signal was checked
before being relied on rather than after.

CLAUDE.md's non-destructive coexistence claim now states the exception, and
that the cause is session churn rather than a second Apollo.

⚠️ Not yet verified: that the warning fires during a real teardown, and stays
quiet when nothing is streaming. Both need seat churn and the host was
streaming.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
@vibesoftwarecoder
vibesoftwarecoder merged commit 164f445 into master Sep 11, 2026
3 checks passed
@vibesoftwarecoder
vibesoftwarecoder deleted the fix/warn-standalone-apollo-stall branch September 11, 2026 13:14
vibesoftwarecoder added a commit that referenced this pull request Sep 11, 2026
The warning shipped in #50 said the standalone Apollo's stream "will stall for
about a second". Verified on the reference host today and that is wrong in the
direction that matters -- it makes operators expect something worse than
happens.

Measured with a client genuinely streaming the console Apollo while a seat was
provisioned and torn down:

  08:49:23.503  warning fired
  08:49:24.661  Apollo: Creating encoder      <- 1.2s AFTER the warning
  08:49:25.099  Session 8 logged off
  08:49:31.996  Apollo: Creating encoder      <- 7s after teardown, unexplained

The rebuild took 266 ms, against the 690 ms measured on 2026-09-04, and the
person streaming DID NOT NOTICE IT AT ALL.

So: "hitch for a few hundred milliseconds", not "stall for about a second".
CLAUDE.md carries the same correction, with both measurements and the caveat
that one user's perception on one LAN does not prove it is always
imperceptible.

Two other things this run settled, both recorded on #23 rather than here:

- Provisioning did NOT cause a rebuild. The session was created at 08:49:09.933
  with no encoder activity near it, which supports the original observation in
  the issue rather than contradicting it. An earlier reading of mine that
  claimed otherwise was wrong -- corrected by correlating timestamps instead of
  eyeballing a log tail.
- The warning fires BEFORE the stall, by 1.2s, which was the whole point of
  placing it ahead of the lifecycle gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
@vibesoftwarecoder vibesoftwarecoder mentioned this pull request Sep 13, 2026
vibesoftwarecoder added a commit that referenced this pull request Sep 13, 2026
version.txt 0.6.4 -> 0.6.5, plus the notes the release workflow reads.

No code changes -- four merged commits ship: #49 (a streaming seat reported
Ready), #50 (a streaming standalone Apollo reported idle), #51 (that warning
overstated the stall), #52 (the audit gate failed on a registry outage).

⭐ Three of the four are runtime-verified on the reference host rather than only
CI-green:

  #49  Ready -> Streaming in 6s on connect, back in 3s on disconnect
  #50  streaming signal correct in BOTH directions, including a live stream the
       old serverinfo check reported as idle
  #51  266 ms measured, and the person streaming did not notice it

⚠️ And master CI was RED before this. 45f46b0 failed on a 400 from
registry.npmjs.org, not on our code -- the same commit had passed its own PR 45
minutes earlier and passed locally afterwards. #52 fixed the gate; the master
push on b5feaac is green across all three jobs, checked before cutting rather
than assumed.

That is worth recording: "the tests pass" is not "master is green", and I
reported the first while implying the second.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SQvL62WkT8xDWXqyjFCGDw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant