-
-
Notifications
You must be signed in to change notification settings - Fork 13
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
Websocket support #13
base: main
Are you sure you want to change the base?
Conversation
403af4d
to
9222073
Compare
9222073
to
0202ce2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fab work! Really cool stuff.
I think we're going to need a more flexible API for the websocket service. Currently a message of some kind comes in from the websocket client and then the server decides to either reply or not. This will work for many cases, but other times we need to be able to send a message to the client without the client sending anything. For example, notifying the user of a website when they have recieved a new direct message from another user.
To implement this I think we would want to model the service as an actor that accepts messages. This is an issue as I intend to make some large breaking changes in the OTP/Erlang libraries after finishing with this iteration of LSP work, and I want that to have as small an impact on other libraries such as this one.
On the other hand, this is fantastically useful! Even if we cannot today solve all the possible websocket use cases that doesn't mean we don't want this. If we don't have any good ideas I'd suggest we publish this as a second package, and perhaps later merge them together.
I've also got some very minor stylistic comments around naming but that can be discussed later :)
What are your thoughts?
@lpil Thanks for the feedback! So disclaimer, I'm still pretty unfamiliar with I would expect that would be the place that one one hook in to register their new Then that connection tracker can send normal messages to the pid which will trigger the Does that all make sense? Or am I'm misunderstanding how |
You've got the general idea, and that is largely how cowboy websockets work today as I understand. It becomes more complex when you consider the types of messages send to the websocket service process. If there's a The API would likely need to look less like a |
@lpil Ah, yes totally get it now when it comes to types. I think what I'll do is publish this as a separate experimental package for now then just so I can start playing around with real time apps with Gleam myself. Then once those new OTP APIs exist we can create a better more official API for this package! |
FYI, got tests all working over in the new repository here: https://github.com/vstreame/gleam_cowboy_websockets |
Thinking about this more, perhaps it's OK that the typing is not amazing here. If that's a limitation of cowboy it's good motivation to make a Gleam websocket server that is well typed and hopefully even faster than cowboy! |
@lpil I've also spent the last week learning more about |
(Note: This PR is rebased on #12 just to have some test infra in place. We'll need to merge that before this one can land)(Note 2: Cannot get tests to pass until we get a new version of
nerf
out that works with HTTP 3.0 APIs. PR: lpil/nerf#3)What
This is an experimental PR to add Websocket support to the Gleam API. The main change is that when dealing with websockets we more than one "handler". Not only do we need the initial HTTP handler, but we also needs handlers for
As well as we need a piece of state to share between all of these handlers.
Please view the tests for the proposed API.
Why
This would unlock Gleam as a language to build "real-time" applications with. Which would be a very neat use-case!
How
This PR is mostly to discuss the proposed API, but here is also how it currently implements that API (which I'm less sure of). Instead of passing a single handler function to
init/1
we instead pass down a map with known keys.handler
- The function that is passed ahttp/request.{Request}
and returns aWSResponse
. AWSResponse
is either a wrapper over a normalhttp/response.{Response}
or it's anUpgrade(init_state)
. WhenUpgrade
is returned this is signal to us that the developer wants to upgrade the request to a persistant websocket connection.on_ws_init
- This handler is used to grab any relevantpid
s and/or return a frame immediately to the clienton_ws_frame
- Handler called whenever a new WS frame is sent from the clienton_message
- Handler called whenever pid receives as message from ErlangEach handler is expected to tell us if we want to send any Frames in response as well as what the new state should be updated to.
Links