Diagnostics: surface upstream WS close reason + break the null-spin loop
The Pi journal showed 170 000 'upstream silent NxN' messages within one second — i.e. ReceiveJsonAsync was returning null in zero time, so the upstream WS to OpenAI was closed. The relay was spinning until idle watchdog (30 s) fired. Add IRealtimeUpstream.IsClosed + CloseReason, populated by OpenAIRealtimeUpstream from the close status / WS exception, and have PumpAsync stop on close and forward error code=upstream_closed message=close status=<X> desc=<Y> to the device. Closes the spin AND gives us the OpenAI close reason.
This commit is contained in:
@@ -128,9 +128,25 @@ public class RealtimeSession
|
||||
if (evt is null && ct.IsCancellationRequested) return;
|
||||
if (evt is null)
|
||||
{
|
||||
// Upstream has gone silent. Surface that to the device every
|
||||
// ~2s so we can tell "OpenAI is up but emitting nothing" from
|
||||
// "the upstream WS was closed" — Coolify logs aren't reachable.
|
||||
// If the upstream WS is closed, stop spinning — surface the
|
||||
// close reason to the device and bail with EndReason=Error.
|
||||
if (_upstream.IsClosed)
|
||||
{
|
||||
var reason = _upstream.CloseReason ?? "upstream closed";
|
||||
_logger.LogWarning("upstream closed mid-session: {Reason}", reason);
|
||||
await _output.WriteEnvelopeAsync(new JsonObject
|
||||
{
|
||||
["type"] = "error",
|
||||
["code"] = "upstream_closed",
|
||||
["message"] = reason,
|
||||
["fatal"] = false,
|
||||
}, ct);
|
||||
_endReason = EndReason.Error;
|
||||
return;
|
||||
}
|
||||
// Surface "alive but silent" every ~2s so we can tell that
|
||||
// from "the upstream WS was closed". Coolify logs aren't
|
||||
// reachable from the dev sandbox.
|
||||
if (++nullPolls % 8 == 0)
|
||||
{
|
||||
_logger.LogInformation("upstream silent ({Polls} x 250ms polls)", nullPolls);
|
||||
|
||||
Reference in New Issue
Block a user