RFC
Until now, if the initial `BeginPlaySession()` call failed, the client
would continue operating as if it didn't - it would still continue to
send frames and call `EndPlaySession()` at the end of a session.
Server-side, two things generally can happen after this:
- The sent frames and the `EndPlaySession()` call are
[completely](https://github.com/ppy/osu-server-spectator/blob/7bab117e9d161455485368f63a0607a9e53f9f8a/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs#L122-L125)
[ignored](https://github.com/ppy/osu-server-spectator/blob/7bab117e9d161455485368f63a0607a9e53f9f8a/osu.Server.Spectator/Hubs/Spectator/SpectatorHub.cs#L153-L157)
as no-ops, or
- A hub filter (like `ClientVersionChecker`) that failed the initial
`BeginPlaySession()` call continues to fail the calls to
`SendFrameData()` and `EndPlaySession()`, all the while creating a storm
in logs, because it needs to throw `HubException`s to communicate to
users that they need to update their game, and the exceptions can't be
silenced from logs because they look like every other failure.
To that end, this has two goals: reduce useless network traffic, and
reduce noise in spectator server logs after the client version checks
were recently reactivated.
Probably needs tests, but unsure if everyone's going to be on board with
this to begin with to be quite frank, so I'm leaving tests for when I'm
told this needs tests.
Fell out when attempting
https://github.com/ppy/osu-server-spectator/pull/346.
Functionally, if a true non-`HubException` is produced via an invocation
of a spectator server hub method, this doesn't really do much - the
error will still log as 'unobserved' due to the default handler, it will
still show up on sentry, etc. The only difference is that it'll get
handled via the continuation installed in `FireAndForget()` rather than
the `TaskScheduler.UnobservedTaskException` event.
The only real case where this is relevant is when the server throws
`HubException`s, which will now instead bubble up to a more
human-readable form. Which is relevant to the aforementioned PR because
that one makes any hub method potentially throw a `HubException` if the
client version is too old.
Obviously this does nothing for the existing old clients.
Closes https://github.com/ppy/osu/issues/33465 probably.
This reverts the replay frame de-duplication logic to what it was before
https://github.com/ppy/osu/pull/33148#discussion_r2091549388.
I don't have good reproduction steps. I tried to write a test case for
this that isn't just "press and release a key in the same frame",
thinking that maybe there was some loophole in the osu! touch input
mapper that may produce this situation artificially, but I could not in
many configurations. So I have to assume that this just *can happen*
organically.
When the server requests a disconnect due to a user connecting
via a second device, the client will now log the user out on the first
device and show a notification informing them of the cause of
disconnection.