Description
I would like to help address this issue as I'm a big fan of Blazor WebAssembly and a strong believer in GraphQL as the best API tech. So, supporting GraphQL.Client
is of paramount interest. If there is already an effort underway to achieve this, please close this issue as a duplicate and point me in the right direction.
Problem
I've started looking at the code to better understand where the problem is originating from. At the core of the problem are the limited capabilities of the Blazor WASM runtime. For instance, it's not possible to create threads or even block on a thread with Task.Wait()
or Task.Result
. All operations must be asynchronous as there is only one main thread in the browser execution environment.
The implementation of the GraphQL.Client.Http.Websocket.GraphQLHttpWebSocket
class uses System.Reactive.Concurency.EventLoopScheduler, which creates a thread internally. This causes the System.NotSupportedException: Cannot start threads on this runtime.
error when the websocket connection is opened.
Solution
There are 2 approaches to potentially address this problem:
Approach 1 - Blazor WASM-friendly System.Reactive.Concurrency.IScheduler
implementation
Implement a Blazor WASM-friendly version of System.Reactive.Concurrency.IScheduler
that does not require background threads. It would only work reliably when scheduled operations are asynchronous. However, it would be the least invasive change.
Benefits
- Least invasive
- Least amount of new code
- Requires small initialization change in
GraphQLHttpWebSocket
that could be controlled via aGraphQLHttpClientOptions
property to allow current and new implementations to exist side-by-side
Drawback
- No compile-time detection if the asynchronous requirement is not honored
Approach 2 - Replace System.Reactive
in favor of a pure asynchronous implementation
Benefits
- Removes dependency on
System.Reactive
(less is better) - Clean asynchronous interface enables compiler to assist with
async/await
code pattern enforcement. - Doesn't require to understand how
System.Reactive
works by deferring continuations toTask
-related methods
Drawbacks
- Breaking change if public interface of
GraphQL.Client
exposesIObservable
- Lots of code changes
- Even more complexity if old and new implementations need to exists side-by-side
Additional
As follow up to this issue, there should also be a sample Blazor WASM application to showcase and test the proper behavior.
Related
The following issues are related: