Comments (14)
One question I meant to ask is that if we go with my solution for the whole thing, do we accept to duplicate the 'Req' value with all of its contents? I know misultin already does sandboxing that way -- we'd end up with 3 copies of the socket by acting that way, but I see no other good fix that doesn't involve doing things that way. Is it worth it for the corner cases where people do it my way and punish everyone, or punish the few people who have that issue by needing them to look at documentation (which we will need to write at some point).
from socket.io-erlang.
@ferd, could you copy paste solution?
Thank you!
from socket.io-erlang.
Here you go, @sinnus. The code is a bit customized for some closed-source app I had, and you can disregard some options such as SessionMods
and SessionMethod
. They were application-specific things.
%% How to start the connection and whatnot
start_link(Options) ->
SessionMods = proplists:get_value(sessions, Options, []),
SessionMethod = proplists:get_value(session_method, Options, [{http_cookie, "sessionid"}]),
Port = proplists:get_value(port, Options),
{ok, Pid} = socketio_listener:start([{http_port, Port},
{default_http_handler, {?MODULE, [SessionMods, SessionMethod]}}]),
EventMgr = socketio_listener:event_manager(Pid),
ok = gen_event:add_handler(EventMgr, ?MODULE, [SessionMods, SessionMethod]).
%% Default HTTP Handler
handle_request(_Method, _Path, Req, SessionMods, SessionMethod) ->
%% Call some function to handle this HTTP call!
%% This depends on messy knowledge abouy misultin sadly.
%% This spawning business is necessary due to the following
%% socket.io issue: https://github.com/yrashk/socket.io-erlang/issues/42
Pid = spawn(fun() -> (my_module:loop(SessionMods, SessionMethod))(Req) end),
Ref = erlang:monitor(process,Pid),
receive
{'DOWN', Ref, process, _, _} -> ok
end.
You can see the trick is starting at Pid = spawn(....),
and finishes with the receive
block. Let me know if you need more explanations.
from socket.io-erlang.
@ferd, I can't understand how messages can get lost?
from socket.io-erlang.
New socket calls are received as messages by the TCP socket controlling process. Misultin dispatches a process to do that, which socket.io's code sits in to redirect the messages to the right spot.
So if the handle_request/N
function is a long running one (could take a few seconds), sits in the same process as socket.io (because it's a callback) and thus in the misultin process, and uses selective receives, then when more data is coming form the socket (say, pipelined calls) or whatever, the long-running function will be consuming these messages instead of leaving them to the socket.io process that usually deals with them.
These messages were likely meant for the socketio process in charge of handling queries, but might have been consumed or discarded by your handler. That means that on the other end of the request (the browser), the query will never be replied to and it will time out.
This can also be true of messages sent to the socketio process in charge of handling queries, unrelated to sockets (internal communications). Because of this, I had to split my queries into two processes. One one hand, the handle_request function will be guaranteed not to consume messages it wasn't meant to, and by spawning a new process to handle the actual request, I allow myself to do and receive whatever I want in my_module:loop/N
.
from socket.io-erlang.
@ferd, is it Misultin issue to bypass messages if a function takes a lot of time?
from socket.io-erlang.
I don't think we could pinpoint the problem to a single place. The problem comes from the interaction of many logical actors (Misultin's side, socket.io-erlang's side, the callback's side) running with the same mailbox. You can fix the issue on any side. I don't know of a way to do it that will not require adding processes, though.
from socket.io-erlang.
@ferd, thank you for your answers! As I can understand the problem is that mailbox is "shared" between other sides,
from socket.io-erlang.
Exactly. Then ownership of messages for each query or worker becomes extremely vague. Misultin doesn't read messages, but you can have conflicts between your callbacks and socket.io-erlang. Using processes the way I did it solves the problem.
from socket.io-erlang.
Hello, @ferd! I tested "long running" callback for longpolling and websocket using timer:sleep:
-module(socketio_transport_websocket).
...
%% Websockets
handle_call({websocket, Data, _Ws}, _From, #state{ heartbeat_interval = Interval, event_manager = EventManager } = State) ->
error_logger:info_msg("Before timer~n", []),
timer:sleep(1000),
error_logger:info_msg("After timer~n", []),
...
-module(socketio_transport_polling).
%% Incoming data
handle_call({_TransportType, data, Req}, From, #state{ server_module = ServerModule,
event_manager = EventManager,
polling_duration = Interval,
sup = Sup } = State) ->
error_logger:info_msg("Before timer~n", []),
timer:sleep(1000),
error_logger:info_msg("After timer~n", []),
...
I used flash socket.io client to send data to server and all messages was processed by server side. I only faced with longpolling timeout when sleep:timer > longpolling timeout.
Can you help me to write test to reproduce issue?
from socket.io-erlang.
I don't sure I understand? You're trying to reproduce the issue I had?
from socket.io-erlang.
Yes, I'm trying to reproduce the issue without "reloading many tabs of the same browser really fast".
from socket.io-erlang.
@ferd, I have reproduced your issue. My test code above was in wrong place because of misunderstanding, sorry.
My steps to reproduce:
- Open index.html
- Send data from flash client
- No echo on client side
- After 10 seconds (timeout) echo will be received
handle_request('GET', [], Req) ->
error_logger:info_msg("Before timer", []),
timer:sleep(10000),
error_logger:info_msg("after timer", []),
Req:file(filename:join([filename:dirname(code:which(?MODULE)), "index.html"]));
from socket.io-erlang.
As we can see handle_request('GET', [], Req) blocks socket.io server. All clients will be wait handle_request function.
from socket.io-erlang.
Related Issues (20)
- close client connection HOT 2
- socketio_listener:start/1 HOT 14
- disconnect event not sent for more than one client HOT 6
- Tests should be possible to run on something else than OSX
- Unable to stream to Android Froyo HOT 1
- submodules will have to be changed soon HOT 1
- git update submodule fails HOT 3
- unicode crash HOT 15
- socketio_data:encode does not count escapes when determining the length of a JSON string HOT 20
- Cannot include ex_uri.hrl HOT 7
- No disconnect by timeout for xhr-polling HOT 1
- Variable 'Host' is unbound when compiling HOT 3
- TCP Error when a client refresh HOT 4
- GET http://localhost:7878/socket.io/socket.io.js 404 (Not Found) HOT 4
- Can't use two event handlers for two different ports from the same socketio application HOT 3
- wrong post
- Can't run demo HOT 4
- Error on demo run HOT 18
- Not able to connect socket server using angular 6 HOT 2
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 socket.io-erlang.