I am pretty new to Mojo so may be off base. My first applications required users intact with a single back-end resource (hardware device) that was also under the control of the same application. Based on that wrong approach it looks like proper way is to use one application (not needed to be mojo) that does back-end processing. This application and a separate client side mojo/Websockets application would use IPC such as pub sub to interact.

John

On 12/30/2015 06:52 AM, Web Designer wrote:
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 mojolicious+unsubscr...@googlegroups.com <mailto:mojolicious+unsubscr...@googlegroups.com>. To post to this group, send email to mojolicious@googlegroups.com <mailto:mojolicious@googlegroups.com>.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

--
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 mojolicious+unsubscr...@googlegroups.com.
To post to this group, send email to mojolicious@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Reply via email to