I have the following parts to a system:

1 - price_alerts.html
2 - WSServer.pl
3 - WSConnector.pm
4 - CoreApplicationEngine.pm

Basically the CoreApplicationEngine.pm is constantly running and for 
arguments sake parsing data coming from text files (nothing to do with 
websockets).

I want to send updates to the browser page price_alerts.html - which works 
but I am not sure if I am going about it in the correct way.

This is the program flow:

CoreApplicationEngine.pm

--------------------------------------------------

    package CoreApplicationEngine;

    use WSConnector;
    use threads;
    ...

    sub priceParser {
        my($self) = @_;
    
        ## Process some files here

        ## When a condition is met update any one browsing on the 
price_alerts.html page

        my $WSConnector = new WSConnector();
        my $thread = async {
            $WSConnector->sendPriceAlert($price, $itemid, $item_name);
        };
        $thread->detach;

    }



-----------------------------------------------------

    package WSConnector;

    use Mojo::UserAgent;
    use Mojo::IOLoop;
    use JSON;

    sub new {
        my $class = shift;
        my $ua    = Mojo::UserAgent->new;
        my $self  = { 'ua' => $ua };
        bless $self, $class;
        return $self;
    }

    sub sendPriceAlert {
        my ($self, $price, $itemid, $item_name) = @_;
        my $ua = $self->{ua};
        my $data;
        $data->{type} = "price_alert";
        $data->{price} = $price;
        $data->{itemid} = $itemid;
        $data->{item_name} = $item_name;
        my $json_data = encode_json($data);

        $ua->websocket(
            'ws://192.168.1.50:3000/prices' => sub {
                my ( $ua, $tx ) = @_;
                print 'WebSocket handshake failed!' and return unless 
$tx->is_websocket;
                # Send a message to the server
                $tx->send($json_return);
            }
        );
        Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
    }

    sub otherAlertsHere { ... }
    

----------------------------------------------------------------

    WSServer.pl

    #!/usr/bin/perl -w
    use strict;


    use Mojolicious::Lite;
    use JSON;

    websocket '/prices' => sub {
        my $c = shift;

        # Opened
        $c->app->log->debug('Prices WebSocket opened');

        my $cli = sprintf( "%s", $c->tx );
        $all_cli_txs->{$cli} = $c->tx; ## So I can broadcast to all 
connected browsers

        # Increase inactivity timeout for connection a bit
        $c->inactivity_timeout(1000);

        # Incoming message
        $c->on(
            message => sub {
                my ( $c, $msg ) = @_;
                my $json = decode_json($msg);

                ## Process some data here and determine which subscribers 
to send to - broadcast, subset or single user - for example sake simply 
passing original json data here as $msg
            
                if($json->{type} eq "price_alert"){
                    for my $client (keys %$all_cli_txs) {
                        $all_cli_txs->{$client}->send($msg);        
                    } 
                }
            }
        }

        $c->on(
            finish => sub {
                my ( $c, $code, $reason ) = @_;
                $c->app->log->debug("WebSocket closed with status $code");
            }
        );
    };

    websocket '/otherthings' => sub {
        my $c = shift;
        ## ...... more 

    };

----------------------------------------------------------------            

I will not post the javascript code on the front end as that is working 
without issue.

I have two main questions:

Question 1 - The code above works but eats memory. When running 1000s of 
updates a minutes, for example in a test, memory consumption rises until 
the whole system becomes unresponsive. This, I assume, is because of the 
thread async call to the WSConnector which is opening 1000s of ws 
connections and not closing them.

So the first question is how do I use 'Mojo::IOLoop->stop;' to stop the ws 
client after a single send - I dont want a loop?

I have tried a few variations, like the following but cannot seem to get it 
to work:


    sub sendPriceAlert {
        my ($self, $price, $itemid, $item_name) = @_;
        my $ua = $self->{ua};
        my $data;
        $data->{type} = "price_alert";
        $data->{price} = $price;
        $data->{itemid} = $itemid;
        $data->{item_name} = $item_name;
        my $json_data = encode_json($data);

        $ua->websocket(
            'ws://192.168.1.50:3000/prices' => sub {
                my ( $ua, $tx ) = @_;
                print 'WebSocket handshake failed!' and return unless 
$tx->is_websocket;
                # Send a message to the server
                $tx->send($json_return);
                Mojo::IOLoop->stop;
            }
        );
        Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
    }



Question 2 - I am having a really hard time understanding how websockets 
work in practice. The basics are straight forward and I have no problem 
implementing basic and more advanced examples. However, I suspect I am 
fundamentally missing something as all examples seem to only be reactive, 
rather than having the ability to react OR inject 'send' messages from 
outside the WS server they simply listen for messages and then send 
messages back.

Am I on the right track by using an intermediate ws client (WSConnector.pm) 
as the 'pusher' for messages to the front end from the 
CoreApplicationEngine.pm?

Or is there a better way to send messages from CoreApplicationEngine.pm 
directly to a WS server that would then pass it onto the front end html 
page rather than having to use an intermediate client setup.

Thanks in advance to anyone that may be able to help me or point me in the 
right direction.

-- 
You received this message because you are subscribed to the Google Groups 
"Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Reply via email to