Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling WebSocket Open Events #24

Open
collinkruger opened this issue Feb 23, 2020 · 5 comments
Open

Handling WebSocket Open Events #24

collinkruger opened this issue Feb 23, 2020 · 5 comments

Comments

@collinkruger
Copy link

Hi @Nhowka,

Thank you for providing this great library to the community.

In a recent project I had to update the Client/Library.fs file to include a withWhenOpened function so that I could listen for WebSocket open events.

Is this a feature you think should be included in your library?
If so, would you like for me to submit a pull-request with this feature added?

@Nhowka
Copy link
Owner

Nhowka commented Feb 23, 2020

Hi, thanks for using it!

About the use case, how different is it from having the server sending a message to the client on its init function? That should behave as same, as that message will go through as the socket opens.

There is another information that are you using about the socket on that function that a server message wouldn't be enough?

@collinkruger
Copy link
Author

Now that you mention that, that sounds like the better approach.

I have some root level UI elements that I want disabled until a connection is established.
Also, due to websockets being an application level concept, I had thought about the problem in those terms.

To your point, in my situation performing a projection off of the nested model is probably a better approach. (single source of truth, single concept, etc.)

I've now rewritten that part of my application to use projections off of the nested model and it is working perfectly.

Thank you for the feedback!

@mrakgr
Copy link

mrakgr commented May 7, 2023

@Nhowka

About the use case, how different is it from having the server sending a message to the client on its init function? That should behave as same, as that message will go through as the socket opens.

The difference is that having the server send an open message is more indirect, which has implications to the way we can architect our programs. For example.

Program.mkProgram Index.init Index.update Index.view
|> Program.withSubscription (fun model ->
    let body (msg : MsgServer) msg_closed dispatch =
        let config =
            Bridge.endpoint $"{Url.learn_server}/{socket_endpoint}"
            |> Bridge.withName "learn" // it uses names to find the sockets under the hood
            |> Bridge.withWhenDown msg_closed
            |> Bridge.withMapping Index.FromServer

        Bridge.asSubscription config dispatch
        Bridge.NamedSend("learn",msg)

        config :> IDisposable
    [
        for KeyValue(name,pl) in model.cfr_players do
            if pl.training_iterations_left > 0 then
                let key = [ string name; "train" ]
                key, body (FromClient (MsgClientToServer.Train (pl.training_iterations_left, pl.training_model)))
                        (Index.ConnectionClosed(name,true))
            if pl.testing_iterations_left > 0 then
                let key = [ string name; "test" ]
                key, body (FromClient (MsgClientToServer.Test (pl.testing_iterations_left, pl.testing_model)))
                        (Index.ConnectionClosed(name,false))
    ]
    )
|> Program.withBridgeConfig (
        Bridge.endpoint socket_endpoint
        |> Bridge.withMapping Index.FromServer
        )
|> Program.withReactSynchronous "app"
#if DEBUG
|> Program.withDebugger
#endif
|> Program.run

Right now I am getting in connecting errors in the browser console when I try to run this. If I had an event handler for when the connection opens, I could just have the Bridge.NamedSend("learn",msg) execute there and it would take care of my problem.

Instead if I have to wait for the message from the server, I'll have to implement a queue to store the messages until a response comes from the other side of the "learn" bridge.

@Nhowka
Copy link
Owner

Nhowka commented May 13, 2023

Hi, @mrakgr! That's a strong argument. I'll try to add this feature soon, but not sure how it should be implemented. Two options I see would be a simple Msg to be dispatched just like the server could do, or instead a function of dispatch where one could dispatch any messages they'd like or call Bridge.Send directly like in your example.

Having a simple Msg would encourage handling it in the update function resulting in more explicit code, but the function would give the developer more freedom. What do you think?

@mrakgr
Copy link

mrakgr commented May 13, 2023

What do you think?

Sigh, I am not sure.

What I wanted to do with the above was implement a system that has a websocket connection open only during the time the server is processing. In the end I made a significantly better system that isn't coupled with the UI code in any way, but it requires the full flexibility of SignalR hubs and wouldn't be possible to imitate even if you added the open event handlers. I made a Youtube video on this.

I find it difficult to think about this question due to that, but I think you should just go with the more flexible approach, as the library is restrictive at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants