You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
privatevoidEnqueueStreamMessage(byte[]frame){if(OperatingSystem.IsBrowser()){_=ProcessStreamMessageFireAndForgetAsync(frame);// straight to a handler, no queue}else{channel.Writer.TryWrite(frame);}}
Consequences in a browser:
ConnectionOptions.StreamMessageQueueCapacity does nothing. The queue is created — StartMessageProcessor runs regardless of platform — but never written to, so its reader idles.
The backlog is bounded by memory alone. One in-flight task per frame, with no ceiling: a handler slower than message arrival accumulates them until something gives.
Ordering is not guaranteed. The non-browser path sets SingleReader = true and processes frames one at a time; fire-and-forget dispatches concurrently, so handlers can observe events out of order.
Why it was not simply changed
The comment on StartMessageProcessor says the channel exists for this environment:
Uses Channel<T> for true async support in WebAssembly single-threaded environment.
So the bypass reads more like a leftover than a decision — but that cannot be settled by reading. WASM is single-threaded, Task.Run there is cooperative rather than parallel, and whether the background reader gets scheduled the way the non-browser path assumes needs checking in a real browser. Nothing in this repository can run that check: there are no WASM tests, only the Blazor-WebAssembly demo project.
Changing stream dispatch blind, inside a PR about observability, was the wrong trade — so #105 documented the limitation on DroppedStreamMessages, on StreamMessageQueueCapacity, on the interface member and in CHANGES.md, and left the behaviour alone.
What this issue is for
Decide whether browser frames should go through the same bounded queue, and verify it where it actually runs:
Establish, in Tests/TestsClients/Blazor-WebAssembly, whether the channel reader is scheduled reliably under WASM — that is the question the bypass exists to dodge, and everything else follows from the answer.
If yes: delete the browser branch, so capacity, eviction counting and single-reader ordering apply everywhere, and the two paths stop diverging.
If no: keep the bypass but bound it — a semaphore or an explicit in-flight cap — and count what it discards, so the counter means the same thing on both platforms.
Either way the goal is that StreamMessageQueueCapacity and DroppedStreamMessages describe reality on every target, rather than on all but one.
Under WebAssembly, stream frames bypass the bounded queue entirely, so nothing limits the backlog and nothing counts what is lost.
What happens
Connection.EnqueueStreamMessage(Xrpl/Client/connection.cs):Consequences in a browser:
ConnectionOptions.StreamMessageQueueCapacitydoes nothing. The queue is created —StartMessageProcessorruns regardless of platform — but never written to, so its reader idles.DroppedStreamMessagesstays at zero however far handlers fall behind, because nothing is ever evicted. The observability added in Обработчик потока выполняется внутри приёмного цикла: медленный подписчик останавливает всё соединение #105 is absent exactly where it is hardest to observe anything.SingleReader = trueand processes frames one at a time; fire-and-forget dispatches concurrently, so handlers can observe events out of order.Why it was not simply changed
The comment on
StartMessageProcessorsays the channel exists for this environment:So the bypass reads more like a leftover than a decision — but that cannot be settled by reading. WASM is single-threaded,
Task.Runthere is cooperative rather than parallel, and whether the background reader gets scheduled the way the non-browser path assumes needs checking in a real browser. Nothing in this repository can run that check: there are no WASM tests, only theBlazor-WebAssemblydemo project.Changing stream dispatch blind, inside a PR about observability, was the wrong trade — so #105 documented the limitation on
DroppedStreamMessages, onStreamMessageQueueCapacity, on the interface member and inCHANGES.md, and left the behaviour alone.What this issue is for
Decide whether browser frames should go through the same bounded queue, and verify it where it actually runs:
Tests/TestsClients/Blazor-WebAssembly, whether the channel reader is scheduled reliably under WASM — that is the question the bypass exists to dodge, and everything else follows from the answer.Either way the goal is that
StreamMessageQueueCapacityandDroppedStreamMessagesdescribe reality on every target, rather than on all but one.Found by review of #109.