in reply to Net::Async::WebSocket::Server in a separate main loop

if (//data to read) { $loop->loop_once; }

That feels weird - I think you should always call ->loop_once from within your other main loop.

Alternatively, you could set up a timer callback to be called from within IO::Async:

use IO::Async::Timer::Periodic; use IO::Async::Loop; my $loop = IO::Async::Loop->new; my $timer = IO::Async::Timer::Periodic->new( interval => 1, on_tick => sub { // something before // something after }, ); $timer->start; $loop->add( $timer ); $loop->run;

Replies are listed 'Best First'.
Re^2: Net::Async::WebSocket::Server in a separate main loop
by Talkabout (Novice) on Jan 12, 2023 at 18:22 UTC

    That is exactly the problem, I cannot use "loop->run" as this blocks the complete application. I need to find a way to call the websocket server logic from within my main loop only using "loop_once", as this is not a blocking call.

    But it seems I have figured out what the problem is... The check for data on socket seems to "destroy" the async loop logic. I will need to find another way to get the main loop to hook into my logic so I can process websocket messages.

      The main loop should not be checking to see if the socket is ready to read because that's the job of the event system. In your hybrid design, the main loop should just ask the event system every 1ms or so whether it has anything to do.

      But, what is your main loop doing that can't be done in IO::Async?

      Since perl is single-threaded, if you want anything to be event-driven, it should all be event-driven. That means you really do want to use ->run, and find a way to take the "main loop" of your script and re-package it into event-style code.

      Most event systems have an "idle" event that fires whenever the application lacks events to process, and you can use that to continue doing segments of a larger bulk task. But, you have to keep the segments of that large task brief, or it will block the events. For instance, if you want your application to respond to a network message within 1ms, then the 'idle' event should not run for more than 1ms at a time.

Re^2: Net::Async::WebSocket::Server in a separate main loop
by Talkabout (Novice) on Jan 12, 2023 at 19:00 UTC

    Ok, finally even the main loop concept with "loop_once" does not work, as the main loop is blocked too much. My only current solution is to create the websocket server via threads, which works quite well. I was concerned about memory, as threads are copying a lot of stuff, but as I will create only 1 I think I can live with it.

    Thanks anyways

      Will you, please, if you'll come to solution with threads, post it here too?

      P.S.: I was trying to figure out about the same scheme - I'm already have CGI processed by Mojolicious server, which take HTTP requests, send them through RabbitMQ to backend, listening for answer. But with websocket connections server needs to listen for messages coming through RabbitMQ from backend to send them to websocket, and it's without request from user. So I need Mojolicious to read RabbitMQ queue in a Mojo::IOLoop event loop system while serving CGI and websocket requests, and for now there are two good queue readers - AnyEvent::RabbitMQ (nonblocking, based on other than Mojolicious AnyEvent loop system) and Net::AMQP::RabbitMQ (blocking), so none of them fit to Mojolicious system. Solution not found so far.

        If you tell AnyEvent and Mojo to use the same event library (like EV) then they are compatible. Make sure you have libev installed and that Mojo::Reactor::EV works. Maybe set MOJO_REACTOR to convince it to work: BEGIN { $ENV{MOJO_REACTOR} = 'Mojo::Reactor::EV'; }

        Also, I see Mojo::RabbitMQ::Client. No experience with it, but you might try that first.