Comments (7)
Would the goal then be that the room_name is stored in the handler and that when the Topic.pull produces a messages, only the messages that are for room_name are pushed?
Right, in fact thinking about it you can probably have a route like: GET /ws/room_name
and pass the room_name
to the service and then on to the WS handler, like:
let socket = (~room_name, _) => {
let%lwt subscription = Topic.subscribe(topic);
let rec handler = (~room_name, pull, push) => {
// handler will push only messages with { "room": room_name }
};
handler(~room_name) |> Response.of_websocket |> Lwt.return;
};
This certainly would be nice. It is nice that you can do some cleanup/detect when a client has been disconnected.
Agreed, in retrospect just having string option Lwt.t
is a little too anemic. I'll make the change (but it will be a breaking change).
from re-web.
Hi Thomas, the ephemeral cache works by retaining the key-value pair as long as the key is in scope somewhere else, but drops it at some GC run after the key goes out of scope. So based on the observed behaviour it seems like the topic_name
value is sometimes going out of scope?
Btw, I think we can rule out that cleanup line in find
, because it's not called for find_opt
. It was more an optimization to keep the hash table size trimmed for topics. But come to think of it, I should probably do the cleanup in find_opt
as well.
from re-web.
Does the clean-up clean everything or just what's not in scope? It's not clear to me why that is exactly needed?
Ok, I'll see how I can find out when the string is not in scope anymore, but it's part of the websocket handler so I guessed it would stay in scope. I also don't know enough about ocaml internals/GC to have any good intuition on this, so it will be some searching around.
Actually I was wondering if it would be possible to get some kind of signal when the websocket drops/is closed in re-web, because then I could do the cleaning manually.
from re-web.
It would force a cleanup of any key-value pairs whose keys are not in scope. This is done automatically when the ephemeron-based hash table is resized, but resizing is non-deterministic, so I wanted a slightly stronger guarantee that cache memory wouldn't grow too much. See https://caml.inria.fr/pub/docs/manual-ocaml/libref/Ephemeron.K1.MakeSeeded.html
The topic_name
value should stay in scope as long as the WS handler passes it in to itself recursively, but not otherwise because it would go out of scope as soon as one invocation of the handler function ended and its stack got cleared out.
Regarding getting an indication of when the socket gets closed, that's currently not possible...
from re-web.
The
topic_name
value should stay in scope as long as the WS handler passes it in to itself recursively, but not otherwise because it would go out of scope as soon as one invocation of the handler function ended and its stack got cleared out.
I've been able to make a smaller reproduction of the problem. The issues presents itself when the topic_name
is part of the path, for example here: | (
GET, ["ws", name]) => socket(cache, topic_name)`
I've created a gist with the relevant files here: https://gist.github.com/tcoopman/aa6727cef26fa8b734a150ae62c6fe74
If you use the index.js file and open a few tabs, you'll see you sometimes get CREATING A TOPIC
as output.
If you change name
to "a_fixed_name"
here https://gist.github.com/tcoopman/aa6727cef26fa8b734a150ae62c6fe74#file-app-re-L9 this doesn't happen.
I've thought about passing the name to the handler as well as an extra argument, but that doesn't fix it.
Regarding getting an indication of when the socket gets closed, that's currently not possible...
Is that because of the architectural design, or just something that's not yet implemented?
from re-web.
Ah, I think I understand what you're trying to do–it's like a chat server where people can connect to chat rooms by a topic name, and it gets created automatically if it doesn't exist, and deleted automatically as soon as no one is connected to it any more.
This is difficult with the current design of the ephemeral cache because it works by using the physical (heap pointer) location of the cache key to decide whether the key-value pair should be kept or removed. So in your example, each time the socket
service is invoked, it allocates a key by calling Context.Key(name)
, but doesn't actually store it anywhere. So each client that connects allocates a new key and looks up the topic in the ephemeral cache using that key.
Because the key is defined to use string value comparison in Context.Cache
, it sometimes successfully looks up the topic, but sometimes fails and creates a new topic, because the topic's key-value pair has been cleared out by that time (because the allocated key went out of scope).
One way to get around this limitation is to have a single topic for all the 'chatrooms' and define a more structured message (maybe using a JSON encoding) to communicate with clients. The client-server WS communication can look something like:
Client: GET /ws
Server: (responds with WS)
C: { "tag": "join", "payload": { "room": "room_name" } }
S: (filters the messages it sends to the client so that it only sends messages with "room": "room_name")
To answer your last question, there's no signal when the WS gets closed. This is by design currently: see
Line 84 in 0103f31
string option Lwt.t
to (string, [> `Timeout | `Connection_close]) result Lwt.t
, to convey what exactly happened. Would this be preferable, do you think?from re-web.
Ok, thank you for explaining. It's clear to me know why this sometimes works and sometimes fails.
One way to get around this limitation is to have a single topic for all the 'chatrooms' and define a more structured message (maybe using a JSON encoding) to communicate with clients.
Would the goal then be that the room_name
is stored in the handler and that when the Topic.pull
produces a messages, only the messages that are for room_name
are pushed?
Would this be preferable, do you think?
This certainly would be nice. It is nice that you can do some cleanup/detect when a client has been disconnected.
from re-web.
Related Issues (20)
- Conflict with compilerlibs Config.ml HOT 4
- Use logging framework HOT 2
- be able to configure the port and listen to inet_addr_any HOT 2
- build failure HOT 5
- How to write integration tests? HOT 1
- Tierless web development HOT 3
- Unable to load compilation data: No root directory found HOT 1
- Investigate server hot-reload on recompile
- build failure with current resolutions HOT 3
- current version of h2 seems to fail HOT 5
- Websockets are broken HOT 5
- a 400 from websocketaf should not result in a 500
- Incorrect handling of `Connection_close` can result in an endless loop HOT 2
- Lwt.choose over Lwt.pick HOT 5
- Getting "Error: Program "examples/1_hello_world/Main.bc" not found!" when running examples HOT 1
- Can't install using opam HOT 2
- Investigating handling databases
- multipart_form filter fails for some files HOT 2
- adding with `opam pin` HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from re-web.