Skip to content
Tracon

ILiveVoiceSideband

Namespace Tracon · Assembly Tracon.Abstractions.dll

The server-side control connection of a live voice session.

public interface ILiveVoiceSideband : IAsyncDisposable
Implements
IAsyncDisposable

Lifetime: never resolved from dependency injection, so neither singleton, scoped nor transient describes it. One instance belongs to one session, is produced by ILiveVoiceProvider.AttachSessionAsync, and is disposed when that session ends. ILiveVoiceSideband.AppendAsync may be called concurrently by several delegations, so an implementation serializes its writes; ILiveVoiceSideband.ReceiveAsync is consumed by a single pump.

Tenant: tenant-independent. The connection carries no tenant of its own — the caller establishes the session’s tenant before the first event is handled, and every run the delegations produce inherits it from there.

Delivery: best-effort in both directions. An append that the provider refuses is reported, not retried, because a retried append can make the model say the same sentence twice; and the event stream ends when the socket does, with no replay of what was missed.

There is deliberately no InterruptAsync: the provider surface offers no way for the sideband to stop the model mid-sentence. Should one appear, it is added as a new LiveVoiceAppendChannel value rather than as a new interface member, so the record and the enum grow while the interface does not.

Disposal races the pump. The host may call IAsyncDisposable.DisposeAsync from a caller-initiated close while the single pump described above still has an outstanding ILiveVoiceSideband.ReceiveAsync call in flight — closing a session does not wait for the pump to notice first. An implementation over a transport with its own two-way close (a ClientWebSocket, for one) must not call that two-way close from its own dispose: it typically reads as part of completing the close handshake, and a second, concurrent reader racing the pump’s own read can consume a message the pump never sees, even though the two-way call itself reports success. Send a one-way close signal instead (CloseOutputAsync on a ClientWebSocket) and let the pump’s own loop end on its own — only tearing the transport down once that loop has actually finished, bounded by a timeout for a peer that never acknowledges.

AppendAsync(LiveVoiceAppend, CancellationToken)

Section titled “ AppendAsync(LiveVoiceAppend, CancellationToken)”

Sends text into the live conversation’s context.

ValueTask AppendAsync(LiveVoiceAppend append, CancellationToken cancellationToken = default)

append LiveVoiceAppend

The channel, the delegation and the text.

cancellationToken CancellationToken

The cancellation token.

ValueTask

The completion task.

Reads the session’s events until the session closes.

IAsyncEnumerable<LiveVoiceEvent> ReceiveAsync(CancellationToken cancellationToken = default)

cancellationToken CancellationToken

The cancellation token.

IAsyncEnumerable<LiveVoiceEvent>

The event stream.