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.