You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi,
the idea is to perform some heavy calculation in thread and send results directly through WS connection back to client.
Note, connection close is handled - so ws connection is open during worker thread is executing.
Again, maybe I do something wrong here? I guess, there is some mess with references to websocket object.
On the first run (client connects to server), there are only one or two client, which do not receive all results. On second attempt to connect to server, clients NEVER receive any results from worker threads (which are created as new on each connection).
/* * Case 01 * ------- * Worker task is executed always in same worker thread. * * How-To: * - open 4 parallel WS connection to service. * - in each connection send channel id, eg. "ch01", "ch02", ... * - observe logs * - worker thread name is always same * - worker cannot write to WS?*/import vibe.d;
import vibe.vibe;
import vibe.core.core;
import vibe.http.server;
import vibe.http.websockets;
import vibe.http.router;
import vibe.inet.url;
importcore.time;
importcore.thread : Thread;
importstd.conv;
static voidworkerFuncPingPongWS(Task caller, string channel_id, shared WebSocket s) nothrow {
WebSocket ws = cast(WebSocket) s;
int counter = 5;
try {
logInfo("WORKER :: thread-id=%s caller=%s channel-id=%s THREAD=%s", thisTid, caller, channel_id, Thread.getThis().name);
while (receiveOnly!string() =="ping"&&--counter) {
logInfo("%s :: %s :: pong=%s", Thread.getThis().name, channel_id, counter);
try {
ws.send("pong-"~ channel_id ~"-"~Thread.getThis().name);
} catch (Exception o) {
logError(">>> exception=%s", o);
}
caller.send("pong");
sleep(2.seconds);
}
caller.send("goodbye");
} catch (Exception e) assert(false, e.msg);
}
classWebsocketService {
@path("/ws") void getWebsocket1(scope WebSocket ws){
logInfo("X> connected=%s, ws=%s code=%s THREAD=%s", ws.connected, &ws, ws.closeCode, Thread.getThis().name);
auto channel_id = ws.receiveText;
logInfo("Receive channel '%s'.", channel_id);
auto callee = runWorkerTaskH(&workerFuncPingPongWS, Task.getThis, channel_id, cast(shared) ws);
do {
logInfo("ping");
callee.send("ping");
} while (receiveOnly!string() =="pong");
while (true) {
auto txt = ws.receiveText;
logInfo("Receive '%s'. thisTid=%s", txt, thisTid);
if (txt =="stop") {
break;
}
ws.send(txt ~" pong");
}
logInfo("Client disconnected - worker is done. THREAD=%s", Thread.getThis().name);
}
}
voidhelloWorld(HTTPServerRequest req, HTTPServerResponse res)
{
res.writeBody("Hello");
}
voidmain()
{
logInfo("APP::CASE::01");
auto router = new URLRouter;
router.registerWebInterface(newWebsocketService());
router.get("/hello", &helloWorld);
auto settings = new HTTPServerSettings;
settings.port = 8080;
settings.bindAddresses = ["::1", "127.0.0.1"];
auto listener = listenHTTP(settings, router);
scope (exit)
{
listener.stopListening();
}
runApplication();
}
client console output on 2nd attempt (server worker thread has only errors on sending data from the thread). Here none of clients received any results from worker threads.
The cast(shared)ws is most likely the problem here. Event based objects generally are always tied to their original thread - in this case the underlying TCP socket over which the WebSocket communicates. Using such an object generally leads to undefined behavior and, depending on the event driver/OS, might actually appear to work so some extent.
So to fix this, the worker task/thread should only perform the actual computation and should then report the result back to the original task. Likewise, if any intermediate communication is required, that should be channeled to the web socket owner task using something like message passing or vibe.core.channel and should then be sent from there.
Hi,
the idea is to perform some heavy calculation in thread and send results directly through WS connection back to client.
Note, connection close is handled - so ws connection is open during worker thread is executing.
Again, maybe I do something wrong here? I guess, there is some mess with references to websocket object.
On the first run (client connects to server), there are only one or two client, which do not receive all results. On second attempt to connect to server, clients NEVER receive any results from worker threads (which are created as new on each connection).
server console output
client console output. As you can see channel
0-fibonacci
did not received results from worker thread!client console output on 2nd attempt (server worker thread has only errors on sending data from the thread). Here none of clients received any results from worker threads.
The text was updated successfully, but these errors were encountered: